@junghanacs/entwurf 0.12.9 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/AGENTS.md +135 -248
  2. package/BASELINE.md +46 -7
  3. package/CHANGELOG.md +35 -0
  4. package/CONTRIBUTING.md +4 -2
  5. package/DELIVERY.md +5 -4
  6. package/README.md +46 -18
  7. package/VERIFY.md +10 -6
  8. package/demo/demo.sh +7 -1
  9. package/docs/setup-clean-host.md +10 -4
  10. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +159 -66
  11. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/backend-adapter.js +148 -5
  12. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/config.js +16 -4
  13. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/models.js +66 -7
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/overlay.js +190 -3
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/tool-surface.js +12 -4
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-core.js +26 -9
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-deliverability.js +10 -6
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-fact-provider.js +15 -17
  19. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-facts.js +13 -13
  20. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-resume-args.js +31 -41
  21. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-self-address.js +8 -9
  22. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-contract.js +32 -25
  23. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-decider.js +4 -4
  24. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-lock.js +5 -4
  25. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-production.js +9 -11
  26. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-spawn-production.js +3 -1
  27. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +17 -20
  28. package/mcp/entwurf-bridge/src/index.ts +190 -82
  29. package/package.json +7 -3
  30. package/pi/settings.reference.json +1 -1
  31. package/pi-extensions/acp-provider.ts +20 -10
  32. package/pi-extensions/entwurf-control.ts +69 -27
  33. package/pi-extensions/lib/acp/augment.ts +60 -2
  34. package/pi-extensions/lib/acp/backend-adapter.ts +183 -8
  35. package/pi-extensions/lib/acp/backend.ts +5 -1
  36. package/pi-extensions/lib/acp/config.ts +19 -5
  37. package/pi-extensions/lib/acp/engraving.ts +3 -1
  38. package/pi-extensions/lib/acp/event-mapper.ts +10 -3
  39. package/pi-extensions/lib/acp/models.ts +69 -7
  40. package/pi-extensions/lib/acp/overlay.ts +234 -3
  41. package/pi-extensions/lib/acp/tool-surface.ts +12 -4
  42. package/pi-extensions/lib/entwurf-core.ts +26 -9
  43. package/pi-extensions/lib/entwurf-deliverability.ts +10 -6
  44. package/pi-extensions/lib/entwurf-fact-provider.ts +15 -17
  45. package/pi-extensions/lib/entwurf-facts.ts +13 -13
  46. package/pi-extensions/lib/entwurf-resume-args.ts +40 -46
  47. package/pi-extensions/lib/entwurf-self-address.ts +8 -9
  48. package/pi-extensions/lib/entwurf-v2-contract-schema.ts +7 -2
  49. package/pi-extensions/lib/entwurf-v2-contract.ts +32 -25
  50. package/pi-extensions/lib/entwurf-v2-decider.ts +8 -8
  51. package/pi-extensions/lib/entwurf-v2-lock.ts +5 -4
  52. package/pi-extensions/lib/entwurf-v2-production.ts +14 -11
  53. package/pi-extensions/lib/entwurf-v2-spawn-production.ts +3 -1
  54. package/pi-extensions/lib/meta-session.ts +17 -20
  55. package/run.sh +200 -62
  56. package/scripts/agy-bridge-config.py +249 -49
  57. package/scripts/agy-bridge.sh +59 -14
  58. package/scripts/check-acp-carrier-augment.ts +34 -2
  59. package/scripts/check-acp-cortex.ts +668 -0
  60. package/scripts/check-acp-provider-surface.ts +50 -6
  61. package/scripts/check-acp-sdk-surface.ts +22 -11
  62. package/scripts/check-acp-session-reuse.ts +64 -1
  63. package/scripts/check-agy-permission-matrix.py +655 -0
  64. package/scripts/check-entwurf-deliverability.ts +9 -6
  65. package/scripts/check-entwurf-fact-provider.ts +7 -7
  66. package/scripts/check-entwurf-facts.ts +12 -12
  67. package/scripts/check-entwurf-resume-args.ts +22 -60
  68. package/scripts/check-entwurf-self-address.ts +187 -4
  69. package/scripts/check-entwurf-v2-contract.ts +2 -2
  70. package/scripts/check-entwurf-v2-production.ts +5 -5
  71. package/scripts/check-entwurf-v2-spawn-production.ts +6 -2
  72. package/scripts/check-entwurf-v2-surface.ts +327 -14
  73. package/scripts/check-gate-qualification.ts +787 -0
  74. package/scripts/check-meta-identity-consumers.ts +1 -1
  75. package/scripts/check-probe-cli-shim.ts +879 -0
  76. package/scripts/check-probe-ordering.ts +2450 -0
  77. package/scripts/check-shell-quote.ts +5 -4
  78. package/scripts/fixtures/probe-cli-shim +20 -0
  79. package/scripts/fixtures/probe-mcp-server.ts +168 -12
  80. package/scripts/lib/mutation-qualify.ts +794 -0
  81. package/scripts/lib/probe-acp-turn.ts +207 -0
  82. package/scripts/lib/probe-cli-shim.ts +464 -0
  83. package/scripts/lib/probe-cli-target.ts +165 -0
  84. package/scripts/lib/probe-event-log.ts +383 -0
  85. package/scripts/lib/probe-verdict.ts +1213 -0
  86. package/scripts/mutants/acp-augment.json +30 -0
  87. package/scripts/mutants/acp-cortex.json +196 -0
  88. package/scripts/mutants/agy-permission.json +144 -0
  89. package/scripts/mutants/meta-identity.json +17 -0
  90. package/scripts/mutants/probe-ordering.json +1032 -0
  91. package/scripts/mutants/self-address.json +59 -0
  92. package/scripts/mutants/v2-surface.json +87 -0
  93. package/scripts/smoke-acp-cortex-live.ts +392 -0
  94. package/scripts/smoke-acp-ordering-probe-live.ts +848 -0
  95. package/scripts/smoke-acp-raw-turn-live.ts +1 -1
  96. package/scripts/smoke-acp-v2-send-live.ts +33 -18
  97. package/scripts/smoke-agy-install-state.sh +205 -20
  98. package/scripts/smoke-entwurf-v2-matrix-live.ts +3 -2
  99. package/pi-extensions/lib/entwurf-mailbox-guard.ts +0 -100
  100. package/scripts/check-entwurf-mailbox-guard.ts +0 -266
@@ -0,0 +1,30 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "lane": "acp-augment",
4
+ "mutants": [
5
+ {
6
+ "claim": "AUGMENT-BUDGET-FITS",
7
+ "title": "shrinking the augment cap re-opens the tail-cut that hid AGENTS rules + cwd from ACP siblings",
8
+ "subject": "pi-extensions/lib/acp/augment.ts",
9
+ "find": ["const MAX_AUGMENT_BYTES = 50 * 1024;"],
10
+ "replace": ["const MAX_AUGMENT_BYTES = 20 * 1024;"],
11
+ "gate": ["bash", "run.sh", "check-acp-carrier-augment"],
12
+ "timeoutSeconds": 60,
13
+ "signature": "[QK:AUGMENT-BUDGET-FITS]",
14
+ "signatureSource": "scripts/check-acp-carrier-augment.ts"
15
+ },
16
+ {
17
+ "claim": "AUGMENT-TRUNC-MARKER",
18
+ "title": "silent truncation: dropping the honest marker leaves a cut augment with no trace",
19
+ "subject": "pi-extensions/lib/acp/augment.ts",
20
+ "find": [
21
+ "\tconst marker = `\\n\\n[entwurf: context augment truncated to ${MAX_AUGMENT_BYTES} bytes; read AGENTS.md files directly if more detail is needed.]`;"
22
+ ],
23
+ "replace": ["\tconst marker = \"\";"],
24
+ "gate": ["bash", "run.sh", "check-acp-carrier-augment"],
25
+ "timeoutSeconds": 60,
26
+ "signature": "[QK:AUGMENT-TRUNC-MARKER]",
27
+ "signatureSource": "scripts/check-acp-carrier-augment.ts"
28
+ }
29
+ ]
30
+ }
@@ -0,0 +1,196 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "lane": "acp-cortex",
4
+ "mutants": [
5
+ {
6
+ "claim": "CORTEX-CURATED-FOUR-ROWS",
7
+ "title": "dropping a curated row silently shrinks the GLG-decided 4-row cortex surface",
8
+ "subject": "pi-extensions/lib/acp/models.ts",
9
+ "find": [
10
+ "export const SUPPORTED_CORTEX_MODEL_IDS = [",
11
+ "\t\"cortex-auto\",",
12
+ "\t\"cortex-claude-opus-5\",",
13
+ "\t\"cortex-claude-sonnet-5\",",
14
+ "\t\"cortex-openai-gpt-5.4\",",
15
+ "] as const;"
16
+ ],
17
+ "replace": [
18
+ "export const SUPPORTED_CORTEX_MODEL_IDS = [",
19
+ "\t\"cortex-auto\",",
20
+ "\t\"cortex-claude-sonnet-5\",",
21
+ "\t\"cortex-openai-gpt-5.4\",",
22
+ "] as const;"
23
+ ],
24
+ "gate": ["bash", "run.sh", "check-acp-cortex"],
25
+ "timeoutSeconds": 300,
26
+ "signature": "[QK:CORTEX-CURATED-FOUR-ROWS]",
27
+ "signatureSource": "scripts/check-acp-cortex.ts"
28
+ },
29
+ {
30
+ "claim": "CORTEX-AUTH-NARROW-CREDENTIAL-CACHE",
31
+ "title": "widening the auth passthrough to the whole cortex/cache leaks operator tool_outputs/tip_history into the child",
32
+ "subject": "pi-extensions/lib/acp/overlay.ts",
33
+ "find": [
34
+ "\tcortexLinkIfExists(",
35
+ "\t\tjoin(realSnowflake, \"cortex\", \"cache\", \"credential_cache\"),",
36
+ "\t\tjoin(cortexDir, \"cache\", \"credential_cache\"),",
37
+ "\t);"
38
+ ],
39
+ "replace": [
40
+ "\trmSync(join(cortexDir, \"cache\"), { recursive: true, force: true });",
41
+ "\tcortexLinkIfExists(join(realSnowflake, \"cortex\", \"cache\"), join(cortexDir, \"cache\"));"
42
+ ],
43
+ "gate": ["bash", "run.sh", "check-acp-cortex"],
44
+ "timeoutSeconds": 300,
45
+ "signature": "[QK:CORTEX-AUTH-NARROW-CREDENTIAL-CACHE]",
46
+ "signatureSource": "scripts/check-acp-cortex.ts"
47
+ },
48
+ {
49
+ "claim": "CORTEX-AUTOUPDATE-OFF",
50
+ "title": "flipping autoUpdate back on lets the cortex runtime replace itself on launch mid-rail (D4)",
51
+ "subject": "pi-extensions/lib/acp/overlay.ts",
52
+ "find": ["\treturn `${JSON.stringify({ autoUpdate: false }, null, \"\\t\")}\\n`;"],
53
+ "replace": ["\treturn `${JSON.stringify({ autoUpdate: true }, null, \"\\t\")}\\n`;"],
54
+ "gate": ["bash", "run.sh", "check-acp-cortex"],
55
+ "timeoutSeconds": 300,
56
+ "signature": "[QK:CORTEX-AUTOUPDATE-OFF]",
57
+ "signatureSource": "scripts/check-acp-cortex.ts"
58
+ },
59
+ {
60
+ "claim": "CORTEX-BRIDGE-DUAL-HOME",
61
+ "title": "dropping the bridge-only real-HOME restore leaves the garden store cut off — tools reach the model but see an empty garden (D10)",
62
+ "subject": "pi-extensions/lib/acp/overlay.ts",
63
+ "find": ["\t\tif (stdio.name === CORTEX_DUAL_HOME_BRIDGE_SERVER) env.HOME = realHome;"],
64
+ "replace": ["\t\tvoid realHome;"],
65
+ "gate": ["bash", "run.sh", "check-acp-cortex"],
66
+ "timeoutSeconds": 300,
67
+ "signature": "[QK:CORTEX-BRIDGE-DUAL-HOME]",
68
+ "signatureSource": "scripts/check-acp-cortex.ts"
69
+ },
70
+ {
71
+ "claim": "CORTEX-MCP-NON-STDIO-FAILLOUD",
72
+ "title": "silently dropping a non-stdio server advertises a config the session does not have (D9 fail-loud)",
73
+ "subject": "pi-extensions/lib/acp/overlay.ts",
74
+ "find": [
75
+ "\t\tif (\"type\" in server && (server.type === \"http\" || server.type === \"sse\")) {",
76
+ "\t\t\tthrow new Error(",
77
+ "\t\t\t\t`entwurf: cortex mcp.json projection cannot represent ${server.type} server ` +",
78
+ "\t\t\t\t\t`${JSON.stringify(server.name)} — only stdio entries are measured through ` +",
79
+ "\t\t\t\t\t`$SNOWFLAKE_HOME/cortex/mcp.json (CP0 D9). Remove it from entwurfProvider.mcpServers ` +",
80
+ "\t\t\t\t\t`for cortex models or front it with a stdio bridge.`,",
81
+ "\t\t\t);",
82
+ "\t\t}"
83
+ ],
84
+ "replace": [
85
+ "\t\tif (\"type\" in server && (server.type === \"http\" || server.type === \"sse\")) {",
86
+ "\t\t\tcontinue;",
87
+ "\t\t}"
88
+ ],
89
+ "gate": ["bash", "run.sh", "check-acp-cortex"],
90
+ "timeoutSeconds": 300,
91
+ "signature": "[QK:CORTEX-MCP-NON-STDIO-FAILLOUD]",
92
+ "signatureSource": "scripts/check-acp-cortex.ts"
93
+ },
94
+ {
95
+ "claim": "CORTEX-OVERLAY-SESSION-SCOPED",
96
+ "title": "a static shared overlay dir lets two residents overwrite one mcp.json/envelope",
97
+ "subject": "pi-extensions/lib/acp/overlay.ts",
98
+ "find": ["\tconst scopeDir = join(overlaysRoot, cortexOverlayScopeId(params.scopeKey));"],
99
+ "replace": ["\tconst scopeDir = join(overlaysRoot, \"shared\");"],
100
+ "gate": ["bash", "run.sh", "check-acp-cortex"],
101
+ "timeoutSeconds": 300,
102
+ "signature": "[QK:CORTEX-OVERLAY-SESSION-SCOPED]",
103
+ "signatureSource": "scripts/check-acp-cortex.ts"
104
+ },
105
+ {
106
+ "claim": "CORTEX-HOME-PRESENCE-REFUSED",
107
+ "title": "a truthy check instead of presence lets an empty-string CORTEX_HOME slip past the refusal (D3 E2b nuance)",
108
+ "subject": "pi-extensions/lib/acp/backend-adapter.ts",
109
+ "find": ["\t\tif (\"CORTEX_HOME\" in process.env) {"],
110
+ "replace": ["\t\tif (process.env.CORTEX_HOME) {"],
111
+ "gate": ["bash", "run.sh", "check-acp-cortex"],
112
+ "timeoutSeconds": 300,
113
+ "signature": "[QK:CORTEX-HOME-PRESENCE-REFUSED]",
114
+ "signatureSource": "scripts/check-acp-cortex.ts"
115
+ },
116
+ {
117
+ "claim": "CORTEX-LAUNCH-NO-MODEL-PIN",
118
+ "title": "re-introducing the launch -m pin creates a second model authority that drifts from per-turn set-model",
119
+ "subject": "pi-extensions/lib/acp/backend-adapter.ts",
120
+ "find": [
121
+ "\tresolveLaunch({ config }) {",
122
+ "\t\tconst settings = config.adapterSettings as CortexAdapterSettings | undefined;",
123
+ "\t\tconst connection = settings?.cortexConnection?.trim() || undefined;",
124
+ "\t\tconst selectionArgs: string[] = [];"
125
+ ],
126
+ "replace": [
127
+ "\tresolveLaunch({ config, nativeModelId }) {",
128
+ "\t\tconst settings = config.adapterSettings as CortexAdapterSettings | undefined;",
129
+ "\t\tconst connection = settings?.cortexConnection?.trim() || undefined;",
130
+ "\t\tconst selectionArgs: string[] = [\"-m\", nativeModelId];"
131
+ ],
132
+ "gate": ["bash", "run.sh", "check-acp-cortex"],
133
+ "timeoutSeconds": 300,
134
+ "signature": "[QK:CORTEX-LAUNCH-NO-MODEL-PIN]",
135
+ "signatureSource": "scripts/check-acp-cortex.ts"
136
+ },
137
+ {
138
+ "claim": "CORTEX-ENFORCE-SET-MODEL",
139
+ "title": "enforcing a constant instead of the native id silently answers with the wrong model (CP0-M)",
140
+ "subject": "pi-extensions/lib/acp/backend-adapter.ts",
141
+ "find": [
142
+ "\t\tawait setConfig.call(connection, { sessionId: acpSessionId, configId: \"model\", value: nativeModelId });",
143
+ "\t},",
144
+ "",
145
+ "\t// A connection change must invalidate a reused session (§4/§7). Flat,"
146
+ ],
147
+ "replace": [
148
+ "\t\tawait setConfig.call(connection, { sessionId: acpSessionId, configId: \"model\", value: \"auto\" });",
149
+ "\t},",
150
+ "",
151
+ "\t// A connection change must invalidate a reused session (§4/§7). Flat,"
152
+ ],
153
+ "gate": ["bash", "run.sh", "check-acp-cortex"],
154
+ "timeoutSeconds": 300,
155
+ "signature": "[QK:CORTEX-ENFORCE-SET-MODEL]",
156
+ "signatureSource": "scripts/check-acp-cortex.ts"
157
+ },
158
+ {
159
+ "claim": "CORTEX-OVERLAY-KEY-IS-SESSION-KEY",
160
+ "title": "re-deriving the overlay scope from ambient env drops opts.sessionId — two same-process/cwd sessions alias one overlay/mcp.json",
161
+ "subject": "pi-extensions/lib/acp/backend-adapter.ts",
162
+ "find": ["\t\tconst overlay = ensureCortexDualHomeOverlay({", "\t\t\tscopeKey: sessionKey,"],
163
+ "replace": ["\t\tconst overlay = ensureCortexDualHomeOverlay({", "\t\t\tscopeKey: piSessionId ?? \"static\","],
164
+ "gate": ["bash", "run.sh", "check-acp-cortex"],
165
+ "timeoutSeconds": 300,
166
+ "signature": "[QK:CORTEX-OVERLAY-KEY-IS-SESSION-KEY]",
167
+ "signatureSource": "scripts/check-acp-cortex.ts"
168
+ },
169
+ {
170
+ "claim": "ACP-OVERLAY-SESSIONKEY-WIRED",
171
+ "title": "passing a cwd-derived key instead of resolveSessionKey's value silently merges distinct sessions' overlay scopes at the production call site",
172
+ "subject": "pi-extensions/lib/acp/backend.ts",
173
+ "find": [
174
+ "\t\t\tconst overlay = adapter.ensureOverlay({ cwd, modelId: model.id, nativeModelId, config, sessionKey });"
175
+ ],
176
+ "replace": [
177
+ "\t\t\tconst overlay = adapter.ensureOverlay({ cwd, modelId: model.id, nativeModelId, config, sessionKey: `cwd:${cwd}` });"
178
+ ],
179
+ "gate": ["bash", "run.sh", "check-acp-session-reuse"],
180
+ "timeoutSeconds": 300,
181
+ "signature": "[QK:ACP-OVERLAY-SESSIONKEY-WIRED]",
182
+ "signatureSource": "scripts/check-acp-session-reuse.ts"
183
+ },
184
+ {
185
+ "claim": "CORTEX-PROVIDER-SIX-ROW-SURFACE",
186
+ "title": "filtering the cortex rows out of the REAL provider entry drops the whole backend from the operator's model list while models.ts and check-acp-cortex stay green",
187
+ "subject": "pi-extensions/acp-provider.ts",
188
+ "find": ["\t\tmodels: allCuratedModels(),"],
189
+ "replace": ["\t\tmodels: allCuratedModels().filter((m) => !m.id.startsWith(\"cortex-\")),"],
190
+ "gate": ["bash", "run.sh", "check-acp-provider-surface"],
191
+ "timeoutSeconds": 300,
192
+ "signature": "[QK:CORTEX-PROVIDER-SIX-ROW-SURFACE]",
193
+ "signatureSource": "scripts/check-acp-provider-surface.ts"
194
+ }
195
+ ]
196
+ }
@@ -0,0 +1,144 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "lane": "agy-permission",
4
+ "mutants": [
5
+ {
6
+ "claim": "AGY-EXACT-RULE-SET",
7
+ "title": "over-grant: adding entwurf_inbox_read to ALLOW_RULES must die at the independent literal oracle",
8
+ "subject": "scripts/agy-bridge-config.py",
9
+ "find": [
10
+ "ALLOW_RULES = tuple(f\"mcp({SERVER_KEY}/{tool})\" for tool in (\"entwurf_v2\", \"entwurf_peers\", \"entwurf_self\"))"
11
+ ],
12
+ "replace": [
13
+ "ALLOW_RULES = tuple(",
14
+ " f\"mcp({SERVER_KEY}/{tool})\" for tool in (\"entwurf_v2\", \"entwurf_peers\", \"entwurf_self\", \"entwurf_inbox_read\")",
15
+ ")"
16
+ ],
17
+ "gate": ["bash", "run.sh", "smoke-agy-install-state"],
18
+ "timeoutSeconds": 180,
19
+ "signature": "[QK:AGY-EXACT-RULE-SET]",
20
+ "signatureSource": "scripts/smoke-agy-install-state.sh"
21
+ },
22
+ {
23
+ "claim": "AGY-INSTALL-MALFORMED-PRIOR",
24
+ "title": "install reverts to a shallow prior-state check (empty provenance map passes all()) and re-captures",
25
+ "subject": "scripts/agy-bridge-config.py",
26
+ "find": [
27
+ " try:",
28
+ " _prior_rules, prior_existed = _parse_permission_state(prior)",
29
+ " except _PermissionStateError as exc:",
30
+ " _die(4, f\"agy-bridge: prior permission install-state is unusable — {exc}. Refusing to \"",
31
+ " \"overwrite provenance this entwurf cannot read; inspect it by hand.\")",
32
+ " for rule in ALLOW_RULES:",
33
+ " if rule in prior_existed:",
34
+ " rules_existed[rule] = prior_existed[rule]"
35
+ ],
36
+ "replace": [
37
+ " if prior.get(\"schemaVersion\") == 1:",
38
+ " legacy_rule = prior.get(\"rule\")",
39
+ " if isinstance(legacy_rule, str) and isinstance(prior.get(\"ruleExistedBefore\"), bool):",
40
+ " if legacy_rule in ALLOW_RULES:",
41
+ " rules_existed[legacy_rule] = prior[\"ruleExistedBefore\"]",
42
+ " else:",
43
+ " prior_existed = prior.get(\"rulesExistedBefore\")",
44
+ " if isinstance(prior_existed, dict) and all(isinstance(v, bool) for v in prior_existed.values()):",
45
+ " for rule in ALLOW_RULES:",
46
+ " if rule in prior_existed:",
47
+ " rules_existed[rule] = prior_existed[rule]"
48
+ ],
49
+ "gate": ["bash", "run.sh", "smoke-agy-install-state"],
50
+ "timeoutSeconds": 180,
51
+ "signature": "[QK:AGY-INSTALL-MALFORMED-PRIOR]",
52
+ "signatureSource": "scripts/smoke-agy-install-state.sh"
53
+ },
54
+ {
55
+ "claim": "AGY-UNINSTALL-VALIDATE-FIRST",
56
+ "title": "uninstall validates the state only inside the settings-exists branch (refusal after mutation)",
57
+ "subject": "scripts/agy-bridge-config.py",
58
+ "find": [
59
+ " ours = _owned_rules(state)",
60
+ "",
61
+ " if os.path.islink(settings_path):",
62
+ " _die(3, f\"agy-bridge: refusing to uninstall — {settings_path} became a symlink since install \"",
63
+ " f\"(someone else's SSOT now). Resolve by hand.\")",
64
+ "",
65
+ " if os.path.exists(settings_path):",
66
+ " data = _load_config(settings_path)"
67
+ ],
68
+ "replace": [
69
+ " if os.path.islink(settings_path):",
70
+ " _die(3, f\"agy-bridge: refusing to uninstall — {settings_path} became a symlink since install \"",
71
+ " f\"(someone else's SSOT now). Resolve by hand.\")",
72
+ "",
73
+ " ours = []",
74
+ " if os.path.exists(settings_path):",
75
+ " data = _load_config(settings_path)",
76
+ " ours = _owned_rules(state)"
77
+ ],
78
+ "gate": ["bash", "run.sh", "smoke-agy-install-state"],
79
+ "timeoutSeconds": 180,
80
+ "signature": "[QK:AGY-UNINSTALL-VALIDATE-FIRST]",
81
+ "signatureSource": "scripts/smoke-agy-install-state.sh"
82
+ },
83
+ {
84
+ "claim": "AGY-DOCTOR-OWNERSHIP-AXIS",
85
+ "title": "the state-doctor rounds a path-correct but unreadable ownership record up to ok",
86
+ "subject": "scripts/agy-bridge-config.py",
87
+ "find": [
88
+ " try:",
89
+ " rules, _existed = _parse_permission_state(state)",
90
+ " except _PermissionStateError as exc:",
91
+ " sys.stdout.write(f\"corrupt {exc}\\n\")",
92
+ " return",
93
+ " sys.stdout.write(f\"ok {len(rules)}\\n\")"
94
+ ],
95
+ "replace": [" sys.stdout.write(\"ok 0\\n\")"],
96
+ "gate": ["bash", "run.sh", "smoke-agy-install-state"],
97
+ "timeoutSeconds": 180,
98
+ "signature": "[QK:AGY-DOCTOR-OWNERSHIP-AXIS]",
99
+ "signatureSource": "scripts/smoke-agy-install-state.sh"
100
+ },
101
+ {
102
+ "claim": "AGY-CROSS-LIST-BROAD-FIRST",
103
+ "title": "broad-most-covering runs only within each list, so a deny-exact shadows an ask-broad host wrongly",
104
+ "subject": "scripts/agy-bridge-config.py",
105
+ "find": [
106
+ " for rule_set, scope in ((BROAD_RULES, \"broad\"), (ALLOW_RULES, \"exact\")):",
107
+ " for list_name in SHADOWING_LISTS:",
108
+ " rules = perms.get(list_name)",
109
+ " if not isinstance(rules, list):",
110
+ " continue",
111
+ " for rule in rules:",
112
+ " if rule in rule_set:",
113
+ " sys.stdout.write(f\"shadowed-by-{list_name} {scope} {rule}\\n\")",
114
+ " return"
115
+ ],
116
+ "replace": [
117
+ " for list_name in SHADOWING_LISTS:",
118
+ " rules = perms.get(list_name)",
119
+ " if not isinstance(rules, list):",
120
+ " continue",
121
+ " for rule_set, scope in ((BROAD_RULES, \"broad\"), (ALLOW_RULES, \"exact\")):",
122
+ " for rule in rules:",
123
+ " if rule in rule_set:",
124
+ " sys.stdout.write(f\"shadowed-by-{list_name} {scope} {rule}\\n\")",
125
+ " return"
126
+ ],
127
+ "gate": ["bash", "run.sh", "check-agy-permission-matrix"],
128
+ "timeoutSeconds": 60,
129
+ "signature": "[QK:AGY-CROSS-LIST-BROAD-FIRST]",
130
+ "signatureSource": "scripts/check-agy-permission-matrix.py"
131
+ },
132
+ {
133
+ "claim": "AGY-SCHEMA-VERSIONS-APART",
134
+ "title": "re-merging the two state schema constants stamps a lying version onto the MCP install-state",
135
+ "subject": "scripts/agy-bridge-config.py",
136
+ "find": ["STATE_SCHEMA_VERSION = 1 # MCP install-state (server key + preimage); shape unchanged"],
137
+ "replace": ["STATE_SCHEMA_VERSION = 2 # re-merged with the permission version (the schema re-merge defect)"],
138
+ "gate": ["bash", "run.sh", "smoke-agy-install-state"],
139
+ "timeoutSeconds": 180,
140
+ "signature": "[QK:AGY-SCHEMA-VERSIONS-APART]",
141
+ "signatureSource": "scripts/smoke-agy-install-state.sh"
142
+ }
143
+ ]
144
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "lane": "meta-identity",
4
+ "mutants": [
5
+ {
6
+ "claim": "META-FIFO-NONBLOCK",
7
+ "title": "removing O_NONBLOCK makes a fifo-shaped record block the open — the 7/26 mutation evidence, committed",
8
+ "subject": "pi-extensions/lib/meta-session.ts",
9
+ "find": ["\tconst fd = fs.openSync(file, fs.constants.O_RDONLY | O_NOFOLLOW_FLAG | O_NONBLOCK_FLAG);"],
10
+ "replace": ["\tconst fd = fs.openSync(file, fs.constants.O_RDONLY | O_NOFOLLOW_FLAG);"],
11
+ "gate": ["bash", "run.sh", "check-meta-identity-consumers"],
12
+ "timeoutSeconds": 120,
13
+ "signature": "[QK:META-FIFO-NONBLOCK]",
14
+ "signatureSource": "scripts/check-meta-identity-consumers.ts"
15
+ }
16
+ ]
17
+ }