Research: AXIOM repo full inventory (e:\gh\axiom)
Note: Explore mode has no terminal, so rg --files was replaced by the workspace glob search (352 files, node_modules/dist excluded). Everything below is from reading source; nothing was run. Claims marked VERIFIED are file contents I read; “EXPECTED” is inference.
A. FILE INVENTORY
Section titled “A. FILE INVENTORY”(a) Source code worth keeping (17 files)
Section titled “(a) Source code worth keeping (17 files)”(b) Tests (30 files)
Section titled “(b) Tests (30 files)”- vitest, packages/axiom-tests/src/: 27
*.test.ts+run.ts(smoke runner used bypnpm test; generates into roottmp_artifacts/). - node:test: packages/policies/test/evaluator.test.ts.
- Loose debug scripts in
packages/axiom-tests/:test-split.mjs,test-regex.mjs,test-parser.mjs,test-parser-inline.mjs,test-optional.mjs,test-block-cap.mjs,debug-manifest.mjs,debug-manifest-v2.mjs,test-manifest-output.txt→ litter.
(c) Docs/specs (16)
Section titled “(c) Docs/specs (16)”README.md, SECURITY.md, SUPPORT.md, LICENSE, CHANGELOG.md, HOWTO_RUN_TESTS.md, docs/{syntax_spec,ir_spec,mcp_api,plugin_api,reverse_ir_spec,versioning,MCP-ONLY-PUBLIC-SURFACE}.md, docs/mcp-config-snapshot.json, examples/{README.md,blog.axm,blog.ir.json}, sanity/README.md, packages/axiom-mcp/README.md.
(d) Generated outputs / scratch / AI-report litter — every file
Section titled “(d) Generated outputs / scratch / AI-report litter — every file”Root AI reports (23): ANNOUNCEMENT.md, FINAL_SUMMARY.md, FINAL_VALIDATION_REPORT.md, GO-NOGO-AXIOM-1.0.9.md, GO-NOGO-REPORT.md, GO-NOGO-REPORT-1.0.20.md, HARDENING-IMPLEMENTATION-SUMMARY.md, IMPLEMENTATION-COMPLETE.md, PR-FINAL-SUMMARY.md, PR-SUMMARY.md, PRODUCTION_READY_SUMMARY.md, PRODUCTION_VALIDATION_REPORT.md, PROFILE_COMPARISON_REPORT.md, PROOF_1.0.17.md, RELEASE-ANNOUNCEMENT-1.0.17.md, RELEASE-ANNOUNCEMENT-1.0.18.md, RELEASE-NOTES-1.0.0.md, RELEASE-NOTES-1.0.7.md, RELEASE-NOTES-1.0.8.md, RELEASE-NOTES-1.0.21.md, RELEASE-NOTES-1.0.22.md, RELEASE-NOTES-1.0.23.md, RELEASE-NOTES-1.0.24.md, REVERSE_IR_IMPLEMENTATION_REPORT.md, TEST-MATRIX-REPORT-ENHANCED-FS.md, TEST-MATRIX-REPORT-v1.0.22.md, VALIDATION-REPORT-1.0.18.md.
Root scratch scripts/data: debug-manifest.cjs, test-generate.mjs, test-json.cjs, test-posix.cjs, test-replace.cjs, test.json, test-output.txt, manifest.json, manifest-notes-final.json, mcp-config-snapshot.json, sbom.json, axiom-1.0.0-bundle.tar.gz, axiom-1.0.0-bundle.tar.gz.sha256, codai-axiom-mcp-1.0.11.tgz, .archive/axiom_starter_full.zip.
Root sample .axm/IR: axiom/{edge-notes,notes,notes-v2,test-invalid,test-no-cap,test-pii,test-with-pii}.axm, axiom/{notes-old,notes-new}.ir.json, axiom/notes-v2.manifest.json.
Generated output trees: out/** (web, web/notes, api, api/notes, docker, docker/notes, tests, test-complete, axiom.json/), out-edge/manifest.json, out-budget/manifest.json, test-results/* (23 json/sha/axm), tmp_artifacts/.
Under packages/axiom-tests: .axiom/cache/v1/* (36 sha files), manifest.json, snapshots/{edge,budget}-profile.snapshot.json, test-debug-output/**, and fixture app trees test-app/, smoke-app/, heavy-app/, simple-app/, clean-app/ (generated by check tests writing into process.cwd()).
(e) CI/config
Section titled “(e) CI/config”package.json, pnpm-workspace.yaml, pnpm-lock.yaml, tsconfig.base.json, .gitignore, .vscode/mcp.json, .github/workflows/axiom-conformance.yml, workflows/ci.yml (wrong location — never runs), profiles/{default,edge,budget}.json, scripts/{determinism-test.ps1/.sh, production-validation*.ps1/.sh, smoke.sh, repro-samedrive.ts}, per-package tsconfig.json, .npmignore (core, mcp).
B. PUBLIC SURFACE
Section titled “B. PUBLIC SURFACE”axiom-core (index.ts re-exports all)
Section titled “axiom-core (index.ts re-exports all)”- ir.ts:3
Capability, :9Constraint, :15Check, :21EmitItem, :27AgentIR, :36AxiomIR(Zod objects); :41-42TAxiomIR,TAgentIR. - parser.ts:17
parseAxiomSource(source: string): { ir?: TAxiomIR, diagnostics: string[] } - validator.ts:3
interface Diagnostic { message; path? }; :5validateIR(ir): { ok, diagnostics }
axiom-engine (index.ts)
Section titled “axiom-engine (index.ts)”- manifest.ts:1
Artifact, :11Evidence, :18Manifest(TS interfaces only, no Zod). - generate.ts:48
generate(ir, outRoot = process.cwd(), profile?): Promise<{artifacts, manifest}> - check.ts:13
check(manifest, ir?, outRoot?): Promise<CheckResult>; :7CheckResult { passed, report, evaluated } - reverse-ir.ts:5
ReverseIROptions { repoPath; outDir? }, :16reverseIR(options): TAxiomIR(sync) - axpatch.ts:7
AXPatchOp,AXPatch; :17diff(oldIR, newIR): AXPatch; :103applyPatch(ir, patch): TAxiomIR - apply.ts:10
ApplyOptions, :18ApplyResult, :43apply(options): Promise<ApplyResult> - util.ts:5
sha256, :11ensureDir, :19toPosixPath, :26writeFile(root, relPath, content): {full, posixPath} - NOT exported from index but imported by tests via
dist/*: emitter.ts:4EmitterContext, :12Emitter; artifactStore.ts:15class ArtifactStore { put, get, static hash, static verify }; fs-axiom: :22resolveRepoRoot(repoPathArg), :154resolveArtifactAbs(repoRootAbs, outRootAbs, artifactRelPosix), :254resolveOutRoot(repoPath, envOutRoot?), :290bufferFromArtifact(artifact, repoAbs), :344writeAndVerify(absFile, buf, expectedSha256?, expectedBytes?).
policies
Section titled “policies”- index.ts:4
PolicyContext { metrics; artifacts; capabilities; outRoot? }; :375evalCheck(ctx, expr): Promise<boolean>. Whitelisted functions:http.healthy(url)(requiresnet('http')capability, HEAD with 1 s timeout),scan.artifacts.no_personal_data()(5 regexes incl. Romanian CNP/phone; reads files fromctx.outRoot).
axiom-mcp — MCP tools (mcp-stdio.ts)
Section titled “axiom-mcp — MCP tools (mcp-stdio.ts)”| Tool | inputSchema | required |
|---|---|---|
axiom_parse :52 |
source: string |
source |
axiom_validate :66 |
ir: object |
ir |
axiom_generate :80 |
ir: object, profile?: string |
ir |
axiom_check :98 |
manifest: object, ir?: object |
manifest |
axiom_reverse :116 |
repoPath?: string, outDir?: string (default "out") |
— |
axiom_diff :134 |
oldIr, newIr: object |
both |
axiom_apply :152 |
manifest, mode?: "fs"|"pr" (default fs), repoPath?, branchName?, commitMessage? |
manifest |
All responses wrapped by addVersionMetadata (:29) adding _axiom_mcp_version, _axiom_engine_version. axiom_generate/axiom_check/axiom_reverse/axiom_apply all default to process.cwd() of the MCP server process — for a VS Code stdio server that is wherever VS Code spawned it. fs_probe_write tool def exists in fs-probe-write.ts:80 but is NOT registered in stdio; it writes to any absolute path with zero validation.
HTTP routes (server.ts), port AXIOM_MCP_PORT || 3411
Section titled “HTTP routes (server.ts), port AXIOM_MCP_PORT || 3411”POST /parse :25, /validate :30, /generate :36, /check :42 (accepts outRoot), /reverse :48, /diff :55, /apply :62 (adds errorCode+Romanian hint on ERR_REPOPATH_RELATIVE_UNSAFE), /fs-probe-write :95 — unauthenticated arbitrary-path write on localhost. No auth, no CORS, no body-size limit, JSON.parse unguarded inside the end handler (throws → unhandled, outer try does not cover it).
Skips if npm_command === 'exec' or execpath contains npx. Otherwise mkdir -p ~/.mcp/servers and overwrites ~/.mcp/servers/axiom.json with {command:"npx", args:["@codai/axiom-mcp"], env:{AXIOM_MCP_PORT:"3411"}, description, endpoints:[7 HTTP strings]}. That JSON is not a format any MCP client reads (~/.mcp/servers/ is not a standard location), and args launches the HTTP server.js bin, not the stdio one. .vscode/mcp.json uses the correct axiom-mcp-stdio bin instead. Runs via node dist/postinstall.js — fails on a fresh workspace clone before build (dist absent).
C. DATA CONTRACTS
Section titled “C. DATA CONTRACTS”IR Zod schema — full (ir.ts)
Section titled “IR Zod schema — full (ir.ts)”Capability { kind: "fs"|"net"|"secret"|"ai"|"compute"; args?: (string|number|boolean)[]; optional?: boolean }Constraint { lhs: string; op: "=="|"!="|"<="|">="|"<"|">"; rhs: string|number|boolean }Check { kind: "unit"|"policy"|"sla"; name: string; expect: string }EmitItem { type: "service"|"tests"|"report"|"manifest"; subtype?: string; target: string }AgentIR { name; intent; constraints=[]; capabilities=[]; checks=[]; emit: EmitItem[] }AxiomIR { version: literal "1.0.0"; agents: AgentIR[] (min 1) }Manifest — three contradictory definitions
Section titled “Manifest — three contradictory definitions”- TS manifest.ts:
Artifact{path, kind:"file"|"report", sha256, bytes, contentUtf8?, contentBase64?},Evidence{checkName, kind, passed, details?},Manifest{version:"1.0.0", buildId, irHash, profile?, artifacts, evidence, createdAt}. - JSON manifest.schema.json:
kindenumfile|directory(notreport);evidence[]items{stage, result: pass|fail|skip, message}— a completely different shape from the TSEvidence;createdAtformat: date-timebut code emitsdeterministic-<hex16>;profileabsent; sha256 pattern lowercase only. Actual manifests would fail this schema. - JSON ir.schema.json:
version: "1",product,components,policies— unrelated to the Zod IR. Pure fiction.
axpatch format (axpatch.ts)
Section titled “axpatch format (axpatch.ts)”{op:"add"|"remove"|"replace", path: "/agents/0/…", value?}. diff() handles only agents[0]; if agent count differs → whole /agents replace. Constraints/capabilities diffed by JSON string equality (whole-array replace), checks keyed by name, emit keyed by target. Bug: remove emits indexes from the OLD array while add uses /-; applying multiple removes shifts indices (:80-85). No test/move/copy ops; not RFC 6902 compliant.
Profiles
Section titled “Profiles”default.json: only map (subtype → @axiom/emitter-* — old scope, wrong names). edge.json adds constraints{timeout_ms:50, memory_mb:128, max_artifact_size_mb:50, cold_start_ms:100, no_fs_heavy:true}; budget.json constraints{max_bundle_size_kb:500, max_dependencies:5, no_analytics:true, no_telemetry:true}.
How profiles actually affect generation: the constraints block is never read anywhere. The profile is (1) hashed into buildId (generate.ts:56), (2) passed as a string to emitters, which branch on === "edge" / === "budget" (webapp:8-9: edge → runtime:'edge' next.config; budget → drop @vercel/analytics; apiservice:356: edge → PORT 8787), (3) mapped to hardcoded cold_start_ms 50/100/120 in check.ts:96-103. getEmitter fallback reads profiles/<name>.json relative to process.cwd() and does await import(cfg.map[subtype]) — dynamic import of an arbitrary module name from a cwd-relative JSON (generate.ts:27-40).
D. ENGINE INTERNALS
Section titled “D. ENGINE INTERNALS”generate.ts
Section titled “generate.ts”- Emitters statically imported from
@codai/axiom-emitter-*/dist/index.js— engine depends on emitters and emitters depend on engine (type-only) → circular workspace dependency. - Writes every artifact to disk immediately via
writeFile(outRoot, …)AND to.axiom/cache/v1/<sha>AND inlines it (contentUtf8/contentBase64) when ≤ 256 KiB (AXIOM_INLINE_CONTENT,AXIOM_INLINE_THRESHOLD_BYTES). The UTF-8 detection (:88-101) is dead logic:contentis already astring, soBuffer.from(string).toString().round-trip is always equal → alwayscontentUtf8. buildId = sha256(JSON.stringify(ir, Object.keys(ir).sort()) + profile)— passing a key array as the replacer toJSON.stringifyfilters nested keys too:Object.keys(ir)=["version","agents"], so every agent object serialises as{}.irHashis therefore identical for all IRs with the same top-level shape. EXPECTED, not run — but this defeats determinism claims.posixArtifacts(:135) stripscontentUtf8/contentBase64(only copies path/kind/sha256/bytes) — so the manifest passed tocheckand the returnedfinalArtifactslose inline content… butfinalManifest.artifactscomes frommanifest.artifacts=posixArtifactstoo. Yetgenerate-then-apply-statelessexpects inline content inmanifest.artifacts. Wait —manifestTemp.artifacts = posixArtifacts(stripped). So the returned manifest has no inline content; the only place with content is the un-returnedartifactsarray. This is the root cause for the stateless pipeline cluster (see §D-tests).manifest.jsonis written throughwriter()aftercheck, so the manifest on disk does not include its own entry but the cache does.- Three redundant backslash-replace passes; Romanian comments;
console.erroron suspected bug only.
check.ts
Section titled “check.ts”- Hardcoded: cold_start 50/100/120; analytics denylist
@vercel/analytics|analytics|ga-lite; telemetry@opentelemetry/api|pino|winston; fs-heavyfs.readFileSync|writeFileSync|createReadStream;frontend_bundle_kbcounts only paths containing/web/,/webapp/,health-endpoint;no_pii_in_artifactsis alwaystrue(comment admits it);size_under_5mb,response_under_500msderived. - Reads files from
outRooton disk (not from manifest content) — socheckon a manifest from another machine measures nothing. - AND aggregation is correctly implemented (:80);
evaluated:trueset in both branches.
apply.ts + fs-axiom.ts
Section titled “apply.ts + fs-axiom.ts”- Security:
resolveArtifactAbsrejects backslash, POSIX-absolute (/x— but NOTC:\xbecause backslash check fires first;C:/xpassesposix.isAbsolute=false → written under out/ asout/C:/x→ Windows invalid-char check catches:only on win32),..after normalize (also rejects legitimatea..bfilenames), Windows reserved names / trailing dot. No symlink check (target dir could be a symlink out ofout/), no check thatabsFilestarts withoutRootAbs(relies on normalize),AXIOM_OUT_ROOTmay be relative → joined to repo.resolveRepoRootfail-closes only when the result equals$HOMEexactly;$HOME/xis fine. bufferFromArtifactfallback 3 reads.axiom/artifacts/<sha>but generate writes.axiom/cache/v1/<sha>— cache never hit.ArtifactStoreis imported in apply.ts but unused.writeAndVerify: tmp+fsync+rename, then read-back + sha/size compare. Hash mismatch → failure, file left in place (not rolled back).filesWritten=artifact.path(noout/prefix);result.error="N artifact(s) failed verification or processing"— never contains per-artifact reason.- Noise: ~60
console.errorlines per artifact (every step of fs-axiom logs to stderr). On MCP stdio this floods the client’s stderr channel. - PR mode:
git checkout -bon the user’s repo (mutates shared tree),spawn("git", args, {shell:true})withbranchName/commitMessagefrom tool input → command injection via shell. Stagesout/<path>assuming generate already wrote there; never writes files itself. Manifestinput is not validated (no Zod) —manifest.artifactsundefined → TypeError caught as FATAL.
reverse-ir.ts
Section titled “reverse-ir.ts”Heuristics only: dir with package.json+next → web-app; express/fastify or any .js/.ts → api-service; Dockerfile → docker-image; tests → subtype "contract" (not an emitter). Always injects constraints latency_p50_ms<=100, pii_leak==false and check no-pii. Never reads a manifest for real state.
artifactStore.ts
Section titled “artifactStore.ts”put() uses writeFile(path, content, "utf-8") — a Buffer with binary content still works, but encoding arg is misleading. Not wired into apply.
Failing test clusters — root causes (by reading)
Section titled “Failing test clusters — root causes (by reading)”| Cluster | Tests | Expected by test | Code does | Verdict |
|---|---|---|---|---|
1. out/ prefix in filesWritten |
apply-security, apply-stateless-inline, apply-inline-content, apply-absolute-repoPath, apply-enhanced-fs, apply-repopath-dot, apply-sandbox, apply-physical-smoke, apply-phantom-smoke | "out/manifest/README.md" |
"manifest/README.md" (apply.ts:157) |
Code-vs-test contract mismatch. apply-same-drive-abs.test.ts:185 expects NO prefix → tests contradict each other; one set was written against 1.0.20, the other against 1.0.23. |
2. result.error text |
apply-security ("Absolute paths not allowed", "Path traversal not allowed"), apply-sandbox ("traversal" — lowercase; code says ERR_ARTIFACT_PATH_TRAVERSAL… contains “TRAVERSAL” uppercase → fails toContain("traversal")), apply-reject-backslash-paths (ERR_POSIX_ONLY), apply-stateless-inline + phantom/physical (ERR_ARTIFACT_CONTENT_MISSING + path/sha in error) |
reason string in result.error |
error = "N artifact(s) failed…", reasons only in failures[].reason, codes renamed to ERR_ARTIFACT_PATH_* |
Error-code rename in 1.0.23 without updating tests; aggregation hides reasons. |
| 3. Fake sha256 in “happy” tests | apply-security “safe path” (sha of empty string, bytes 14 vs 13-byte content), apply-sandbox “under out/” (sha256:"valid", no content → CONTENT_MISSING), apply-inline-content paths start with out/ → written to out/out/… |
success | HASH/SIZE mismatch or content missing → success:false |
Tests predate post-write verification. |
| 4. check AND-logic | check-aggregate-and, check-evaluator-and-logic | frontend_bundle_kb <= 1/<= 50 to FAIL; cold_start_ms <= 100 to pass |
target "test-app" → paths test-app/… contain no /web/ → frontend_bundle_kb = 0 → <= 1 passes → aggregate true where false expected. “All pass” cases: no_fs_heavy is true; but response_under_500ms == true compares true === true fine. Generation writes into process.cwd() (= packages/axiom-tests) creating the test-app/, clean-app/… litter. |
Metric heuristic depends on path naming; tests assume it measures the webapp. |
| 5. generate→apply stateless | generate-then-apply-stateless (both tests) | manifest.artifacts.some(a => a.contentUtf8) |
posixArtifacts strips content (generate.ts:135-140) → returned manifest has none → apply falls to cache at wrong path → CONTENT_MISSING |
Real bug: inline-content feature (1.0.19) broken by 1.0.20 “POSIX fix”. |
| 6. path-normalization-deepcopy | 1 test | artifacts > 0, POSIX, IR unmutated | should pass on the face of it — EXPECTED failure only if generate throws: check() reads test-app/package.json from cwd fine… Likely passes; if it fails it is the console.log of artifacts.slice(0,5) — no. Flag as needs run to confirm; possible cause: webappEmitterImpl import of dist not rebuilt. |
|
| 7. error-paths E3/E4/E5/E6 | error-paths | failures[0].reason matches ERR_ARTIFACT_PATH_BACKSLASH etc. |
matches | Should pass; E1/E2 skip on Windows. |
| 8. Windows-only skips | golden (3 it.skip), cross-drive/same-drive T3 skip if no second drive |
— | — | 3 skipped confirmed. |
E. DOCS — promise vs code
Section titled “E. DOCS — promise vs code”| Doc | Promises | Reality |
|---|---|---|
| syntax_spec.md | Block syntax constraints { a <= 1, b == false }, checks { policy "x" expect expr }, emit { service type="web-app" target="…" } |
Parser splits constraints on `\n |
| ir_spec.md | “See ir.ts” | Fine. |
| mcp_api.md | 4 HTTP endpoints; check requires fs capability for scan.* |
Server has 8; scan.artifacts.no_personal_data explicitly does NOT require a capability (policies:243); validator does. Artifact paths shown as out/web/README.md — generate emits ./out/web/README.md for blog.axm targets, or bare web/…. |
| plugin_api.md | Emitter API, “network access enforced in engine revisions” | Emitters run arbitrary code with no sandbox; profile fallback import()s any module name. |
| reverse_ir_spec.md | detects integration subtype, adds net(http) default |
integration never emitted; net only if api detected. |
| versioning.md | “Production Ready”, SLSA L3, signed manifest, SBOM, capability bypass MITIGATED, {result, diagnostics} pattern |
None of SLSA/signing exists; sbom.json is a static file; responses are not {result,…}. Node ≥18 claimed; SDK 1.20 needs ≥18 OK. |
| MCP-ONLY-PUBLIC-SURFACE.md | ~/.mcp/servers/axiom.json auto-config, HTTP on 3411 as “MCP” |
The HTTP server is not MCP; real MCP is the stdio bin, which the postinstall config does not reference. |
F. DEPENDENCY GRAPH
Section titled “F. DEPENDENCY GRAPH”graph LR core["@codai/axiom-core 1.0.1 (zod ^3.23)"] pol["@codai/axiom-policies 1.0.1"] eng["@codai/axiom-engine 1.0.24"] web["emitter-webapp 1.0.1"]; api["emitter-apiservice"]; job["emitter-batchjob"]; dok["emitter-docker"] mcp["@codai/axiom-mcp 1.0.24 (+ @modelcontextprotocol/sdk ^1.20.1)"] tests["@axiom/tests (workspace:*)"] eng --> core & pol & web & api & job & dok web & api & job & dok -.type-only.-> eng mcp --> core & eng & pol & web & api & job & dok tests --> core & eng & web & api & job & dok
- Cycle: engine ⇄ emitters (runtime one way, type import the other; pnpm tolerates it, tsc builds by luck of
distbeing present). - Version ranges are semver
^1.0.xnotworkspace:*(except tests) — so a freshpnpm installmay resolve engine/emitters from npm instead of the workspace unless pnpm’slink-workspace-packageskicks in. That is how 1.0.21–24 shipped from an uncommitted tree with the wronggitHead. - pnpm-workspace.yaml: 6 explicit globs +
packages/emitters/*;allowBuilds: esbuild: "set this to true or false"— literal placeholder string (invalid). Nocatalog:. - tsconfig.base.json: ES2022 /
moduleResolution: bundler/ strict /outDir: dist.bundlerresolution +"./dist/*"subpath exports is why every cross-package import is@codai/axiom-x/dist/foo.js. - Root devDeps: typescript ^5.6.3, zod ^3.23.8, tsx ^4.19. Tests: vitest ^2.0.0. Node engines not declared; CI matrix Node 20/22/24 with pnpm 10, but workflows/ci.yml (pnpm 9, Node 20) is outside
.github/and dead. - Policies test script uses
node --test --experimental-strip-types(Node ≥22.6).
G. GIT — likely-uncommitted (from filenames/versions; not run)
Section titled “G. GIT — likely-uncommitted (from filenames/versions; not run)”Per repo memory HEAD is c7298fe “v1.0.20”. Files that only exist for ≥1.0.21 and are therefore EXPECTED uncommitted: packages/axiom-engine/src/lib/fs-axiom.ts, packages/axiom-engine/schemas/*.json, packages/axiom-mcp/src/tools/fs-probe-write.ts, tests apply-cross-drive-semantics, path-validation-fastcheck, long-paths-windows, concurrency-uniqueness, error-paths, apply-enhanced-fs, apply-same-drive-abs, apply-repopath-dot, apply-absolute-repoPath, apply-reject-backslash-paths; RELEASE-NOTES-1.0.21..24.md, TEST-MATRIX-REPORT-*.md, HARDENING-IMPLEMENTATION-SUMMARY.md, HOWTO_RUN_TESTS.md, scripts/repro-samedrive.ts, CHANGELOG.md (top entry 1.0.24), packages/axiom-{engine,mcp}/package.json (version 1.0.24), and the generated litter (test-app/, heavy-app/, .axiom/cache/, test-results/). .gitignore ignores *.manifest.json and tmp_artifacts but not out/, out-edge/, test-app/ etc.
Risks to carry into the rebuild design
Section titled “Risks to carry into the rebuild design”- Contract drift is the core disease: 3 manifest definitions, 2
filesWrittenconventions, 2 error-code vocabularies, tests written against different versions. A single Zod-validatedManifest/ApplyResultshared by engine, MCP and tests is the fix. generatecouples emit → disk → cache → inline;applyreads a different cache path. Separate pure generation (content in memory) from materialisation.- Security holes worth not re-creating:
/fs-probe-write,shell:truegit spawn with user strings, cwd-relative profileimport(), no symlink/containment check, stderr flood on stdio. JSON.stringify(ir, Object.keys(ir).sort())makesirHashnon-discriminating — verify by running before relying on determinism claims.checkmeasures disk, not manifest — cannot verify a manifest received over MCP.
Repo memory updated with the failure-cluster root causes.