Skip to main content

Autonomy matrix (generated)

A1. Tier decision (no deployment block)​

ci = host CI green; verdict = TFactory verdict; val = achieved/floor VAL; parity = CI parity (T = true, F = false).

tierresultwhen
(blank)hold-blockingalways
asynchold-asyncalways
autoauto-mergeci=T verdict=pass val=2/1 parity=T
autohold-asyncotherwise
blockinghold-blockingalways
bogushold-blockingalways
hardhold-blockingalways
lowauto-mergeci=T verdict=pass val=2/1 parity=T
lowhold-asyncotherwise
mediumhold-asyncalways

A2. Deployment overlay (applied before the tier; all-green low change)​

Required gates: human-approval, security-scan.

block reasonsresultinputs
(none)auto-merge9 combos, e.g. risk=medium prod=staging satisfied=human-approval,security-scan
deployment risk_class=high is never auto-mergedhold-blocking3 combos, e.g. risk=high prod=staging satisfied=human-approval,security-scan
deployment risk_class=high is never auto-merged
production change is VAL-4 / never autonomous (human-approval required)
hold-blocking1 combos, e.g. risk=high prod=production satisfied=human-approval,security-scan
deployment risk_class=high is never auto-merged
production change is VAL-4 / never autonomous (human-approval required)
required system gate 'human-approval' is not satisfied (only a human can clear it)
hold-blocking1 combos, e.g. risk=high prod=production satisfied=security-scan
deployment risk_class=high is never auto-merged
production change is VAL-4 / never autonomous (human-approval required)
required system gate 'human-approval' is not satisfied (only a human can clear it)
required system gate 'security-scan' is not satisfied
hold-blocking1 combos, e.g. risk=high prod=production satisfied=-
deployment risk_class=high is never auto-merged
required system gate 'human-approval' is not satisfied (only a human can clear it)
hold-blocking3 combos, e.g. risk=high prod=staging satisfied=security-scan
deployment risk_class=high is never auto-merged
required system gate 'human-approval' is not satisfied (only a human can clear it)
required system gate 'security-scan' is not satisfied
hold-blocking3 combos, e.g. risk=high prod=staging satisfied=-
production change is VAL-4 / never autonomous (human-approval required)hold-blocking3 combos, e.g. risk=medium prod=production satisfied=human-approval,security-scan
production change is VAL-4 / never autonomous (human-approval required)
required system gate 'human-approval' is not satisfied (only a human can clear it)
hold-blocking3 combos, e.g. risk=medium prod=production satisfied=security-scan
production change is VAL-4 / never autonomous (human-approval required)
required system gate 'human-approval' is not satisfied (only a human can clear it)
required system gate 'security-scan' is not satisfied
hold-blocking3 combos, e.g. risk=medium prod=production satisfied=-
required system gate 'human-approval' is not satisfied (only a human can clear it)hold-blocking9 combos, e.g. risk=medium prod=staging satisfied=security-scan
required system gate 'human-approval' is not satisfied (only a human can clear it)
required system gate 'security-scan' is not satisfied
hold-blocking9 combos, e.g. risk=medium prod=staging satisfied=-

A3. VAL floor semantics​

achievedfloormeets floor
2NoneTrue
2''True
2'VAL-three'False
12False
22True
32True
None2False
'VAL-2 (3 lanes)'2True

A4. Path floor​

High-risk patterns: auth, login, session, password, secret, credential, token, oauth, iam, rbac, permission, migration, alembic, schema.prisma, terraform, .tf, dockerfile, docker-compose, k8s, kubernetes, helm, .github/workflows, ci.yml, deploy, payment, billing

changed pathfloor
authblocking
loginblocking
sessionblocking
passwordblocking
secretblocking
credentialblocking
tokenblocking
oauthblocking
iamblocking
rbacblocking
permissionblocking
migrationblocking
alembicblocking
schema.prismablocking
terraformblocking
.tfblocking
dockerfileblocking
docker-composeblocking
k8sblocking
kubernetesblocking
helmblocking
.github/workflowsblocking
ci.ymlblocking
deployblocking
paymentblocking
billingblocking
README.mdauto
(no changed files)auto

B. Live wiring (pr_endgame)​

B1. Blank tier vs low (all-green signals)​

reviewTierdisposition
Noneauto-merge
''auto-merge
'low'auto-merge
checkresult
blank == lowTrue

B2. Signals when nothing was measured​

signaldefault
achieved_val0
ci_parityTrue
host_ci_greenFalse
tfactory_verdictNone
val_floorNone

B3. Flags​

flagenv varunsetset to "1"
auto-mergeAIFACTORY_AUTO_MERGEFalseTrue
path-floor enforcementAIFACTORY_PATH_RISK_FLOOR_ENFORCEFalseTrue

B4. Path floor on a low task touching auth: (effective tier, floor)​

enforcementeffective tierfloor
advisory (unset)'low''blocking'
enforced (1)'blocking''blocking'

B5. Deployment overlay on the live path (low task, non-risky diff)​

deploymentenforceeffective tierfloorlive disposition
production_classification=productionunset'low''blocking'hold-blocking
production_classification=production1'blocking''blocking'hold-blocking
risk_class=highunset'low''blocking'hold-blocking
risk_class=high1'blocking''blocking'hold-blocking
system_gates=['human-approval'], satisfied_gates=['human-approval']unset'low''blocking'hold-blocking
system_gates=['human-approval'], satisfied_gates=['human-approval']1'blocking''blocking'hold-blocking

Defaults shown; per-project settings and per-deployment env override them.

B2. Child-process git config pins​

keypinned value
core.hooksPath/dev/null
core.fsmonitorfalse
protocol.ext.allownever
core.sshCommandssh
core.pagercat
core.editortrue
core.askPass(empty)
credential.helper(empty)
credential.https://github.com.helper!gh auth git-credential
sequence.editortrue
GIT_PAGER (env default)cat

C. Gate determinism (static import closure)​

label = the gate module's own transitive imports; package __init__ side effects are reported separately in the next column.

gatelabelmodel clients importedpackage init reaches a model clientlocal modulesvia spawn
merge.merge_policydeterministic-yes (1): apps/backend/merge/__init__.py; reaches anthropic, claude_agent_sdk, core.client, core.simple_client, openai, providers2-
server.services.pr_review_servicemodel-assisted (dynamic import: core.auth:364 (+2 more))anthropic, claude_agent_sdk, core.client, core.simple_client, openai, providersyes (15): see JSON gates[].init_reach; reaches anthropic, claude_agent_sdk, core.client, core.simple_client, openai, providers277runners/github/runner.py
server.services.pr_endgamemodel-assisted (dynamic import: core.auth:364 (+3 more))anthropic, claude_agent_sdk, core.client, core.simple_client, openai, providersyes (21): see JSON gates[].init_reach; reaches anthropic, claude_agent_sdk, core.client, core.simple_client, openai, providers374-

Declared, unverified (cross-repo, not probed):

repogate
PFactoryplan/review/gates.py::run_gates
TFactoryapps/backend/agents/evaluator.py::_run_evaluator_session

pr_endgame's review verdict is injected, not computed there; the review component is the separate pr_review_service row.

D. Control objectives​

controlobjectiveframeworksevidenceclaim
gate.merge.merge_policyThe merge decision itself is deterministic: its own import closure reaches no model client.ISO 27001:2022 A.8.32; SOC 2 CC8.1; NIST 800-53 CMapps/backend/merge/merge_policy.pyEnforced by branch protection for non-admin merges; the fleet's merge paths do not use admin bypass, but GitHub does not prevent it while enforce_admins is false (measured 2026-10-07, Factory#943).
gate.server.services.pr_endgameThe endgame that applies the merge decision imports model clients; the review verdict it consumes is injected, not computed there.ISO 27001:2022 A.8.32; SOC 2 CC8.1; NIST 800-53 SA; NIST 800-53 RAapps/web-server/server/services/pr_endgame.pyEnforced by branch protection for non-admin merges; the fleet's merge paths do not use admin bypass, but GitHub does not prevent it while enforce_admins is false (measured 2026-10-07, Factory#943).
gate.server.services.pr_review_serviceThe review that feeds the merge verdict is model-assisted, and the page says so; it runs as a spawned runner whose model clients are found by following the declared spawn edge.ISO 27001:2022 A.8.32; SOC 2 CC8.1; NIST 800-53 SA; NIST 800-53 RAapps/web-server/server/services/pr_review_service.pyEnforced by branch protection for non-admin merges; the fleet's merge paths do not use admin bypass, but GitHub does not prevent it while enforce_admins is false (measured 2026-10-07, Factory#943).
policy.overlayA high-risk or production deployment block, or an unsatisfied required system gate, holds the change for blocking approval before the tier is consulted; it can only tighten the decision.ISO 27001:2022 A.8.32; SOC 2 CC8.1; SOX ITGC change management; SOX ITGC segregation of duties; NIST 800-53 CMapps/backend/merge/merge_policy.py-
policy.path_floorA change touching auth, secrets, migrations, infrastructure or CI paths is floored at blocking review, so a change cannot declare itself routine.ISO 27001:2022 A.8.32; SOC 2 CC8.1; SOX ITGC change management; NIST 800-53 CMapps/backend/review_tier.py-
policy.tier.hardA hard-tier change is never auto-merged; it is held for blocking human approval, which separates the author from the approver.ISO 27001:2022 A.8.32; SOC 2 CC8.1; SOX ITGC change management; SOX ITGC segregation of duties; NYDFS 500.3; NIST 800-53 CMapps/backend/merge/merge_policy.pyEnforced by branch protection for non-admin merges; the fleet's merge paths do not use admin bypass, but GitHub does not prevent it while enforce_admins is false (measured 2026-10-07, Factory#943).
policy.tier.lowA low-tier change auto-merges only when host CI is green, TFactory passed, the achieved VAL meets the floor and CI parity holds; otherwise it is held for async review.ISO 27001:2022 A.8.32; SOC 2 CC8.1; SOX ITGC change management; NIST 800-53 CMapps/backend/merge/merge_policy.pyEnforced by branch protection for non-admin merges; the fleet's merge paths do not use admin bypass, but GitHub does not prevent it while enforce_admins is false (measured 2026-10-07, Factory#943).
policy.tier.mediumA medium-tier change is never auto-merged; it is always held for asynchronous human review.ISO 27001:2022 A.8.32; SOC 2 CC8.1; SOX ITGC change management; NIST 800-53 CMapps/backend/merge/merge_policy.pyEnforced by branch protection for non-admin merges; the fleet's merge paths do not use admin bypass, but GitHub does not prevent it while enforce_admins is false (measured 2026-10-07, Factory#943).
policy.val_floorA change whose achieved Verification Assurance Level is missing or below its declared floor is not auto-merged, and an unreadable floor fails closed.ISO 27001:2022 A.8.32; SOC 2 CC8.1; NIST 800-53 CMapps/backend/merge/merge_policy.py-
sandbox.git_config_pinsEvery child process the server spawns, and the web terminal, runs git with command-scope pins that override the repo config keys an agent could use to run a program (hooks, fsmonitor, ext transport, ssh, pager, editor, askpass, credential helper, sequence editor).ISO 27001:2022 A.8.28; SOC 2 CC6.8; NIST 800-53 SIapps/backend/core/child_env.py-
wiring.auto_merge_flagAuto-merge is off by default and is enabled only by an explicit per-project or per-deployment setting.ISO 27001:2022 A.8.32; SOC 2 CC8.1; NIST 800-53 CMapps/web-server/server/services/pr_endgame.py-
wiring.blank_tierA task with no recorded review tier is decided as low, so the live merge path treats a blank tier exactly as the policy treats low.ISO 27001:2022 A.8.32; SOC 2 CC8.1; NIST 800-53 CMapps/web-server/server/services/pr_endgame.py-
wiring.live_overlayOn the live merge path a high risk or production deployment holds the merge for a human regardless of the path-floor flag; a required human-approval gate clears only on a GitHub approval of the head commit by someone other than the PR author or a bot; an unreadable contract holds it too. The PR author is the GitHub App bot and no PAT is in the server pod.ISO 27001:2022 A.8.32; SOC 2 CC8.1; NIST 800-53 CMapps/web-server/server/services/pr_endgame.pyAccepted residual risks (#1671): non-Claude runners and the GitHub MCP server still receive the App token; PAT copies in project .env files and the UI settings token are not removed by this change; a stored per-project clone PAT is accepted (#1703): it is read only at project add for the clone, through GIT_ASKPASS, never pushes and stays encrypted at rest; projects added without one clone with the App token, and App-token clones for stored credentials are #1700.
wiring.path_floor_flagThe path-derived risk floor is advisory by default for tasks with a signed contract and changes their merge tier only when enforcement is explicitly switched on; for tasks without a signed contract (legacy and from-issue) it always decides the merge tier.ISO 27001:2022 A.8.32; SOC 2 CC8.1; NIST 800-53 CMapps/web-server/server/services/pr_endgame.py-