Orchestrata Ultimate › Plans › spec-audit › reverify-2026-10-18 › L-newest
L-newest — Spec-gap re-verification (SPEC-106 … SPEC-114)
Source: plans/spec-audit/reverify-2026-10-18/L-newest.md at 8a2cb42ad · last changed 2026-10-18 · first committed 2026-10-18 · 252 lines.
Prose pending.
Plan text
L-newest — Spec-gap re-verification (SPEC-106 … SPEC-114)
Cluster L — newest specs, bonus beyond the 000-105 task scope.
Verified against CURRENT code on branch components (HEAD de9e996f2, 337 commits ahead of the 3-month-old audits). No prior audits exist for this cluster; every verdict below is fresh, evidence-grade (file:line), judged by code only — never by checklists/requirements.md boxes.
AST toolkit used exclusively for Python structure (symbols, refs, source); .pl/.sh/.json/.tf/.yml inspected directly (non-Python).
SPEC-106 context-semantic-layer — DONE
Specifies: Deterministic context assembly: canonical KG identity/schema, request analysis → selection → budgeted packing, Prolog (symbolic) relevance refinement, production wiring.
Verified:
- ✅
analyze_request(text|payload) -> RequestFrame—frame.py:245(RequestFrameframe.py:102) - ✅
select(frame) -> RankedSubgraph—selector.py:225(RankedSubgraphselector.py:152) - ✅
pack(subgraph, budget) -> ContextPack+empty_pack+validate_pack—packer.py:134/190/296(ContextPackpacker.py:60) - ✅ Prolog relevance
refine+rescore_by_tier(core/related/peripheral) —relevance.py:237(KgRelevanceRetrieverrelevance.py:113), rulebaseprolog/kg_relevance.pl - ✅ Single DDL source
get_all_ddl—knowledge_graph/schema.py:272; canonical merge keys + non-canonical scan —canonical_schema.py:1015/1366 - ✅ Production wiring:
PipelineKGMixin(kernel/pipeline_kg.py:78) constructsKgRelevanceRetriever(:222);ContextInjector.inject_for_task(context_injector.py:1369) routes through selector; assembler imported bykernel/pipeline_kg.py(refs: USE 934/178/193) - ✅ CLI
scripts/context_pack.py(docstring cites REQ-106-041/043, empty-pack-on-unavailable) - ✅ FR-006 hardening:
kg_relevance.pltabledkg_relevance_tier/2 as incremental;ownership_chain/3tabledknowledge.pl:65;assess_harm/3untabledconstitutional.pl:184
Remaining work / plan: None. Scope —, target —, approach —, deps —, effort —.
Evidence log:
symbols --pattern UnifiedContextAssembler|RequestFrame|RankedSubgraph|analyze_request|pack|PipelineKGMixin|get_all_ddl|inject_for_task|ContextInjector→ all present incontext/assembler.py,knowledge_graph/context_pack/*,kernel/pipeline_kg.pysymbols --pattern refine→context_pack/relevance.py:237refs UnifiedContextAssembler→ USEkernel/pipeline_kg.py:934/178/193(wired, not orphaned)grep ownership_chain knowledge.pl→ tabled:65;grep assess_harm constitutional.pl→ untabled:184
SPEC-107 context-injection-improvements — DONE
Specifies: Fill/refresh the layered assembler (session/plan, bounded memory, semantic-graph, AST, artifact store, on-demand tools, caching, expanded graph context, runtime signals, validator loop, AST-snapshot freshness, deployed claude/ config, ship).
Verified:
- ✅ Session/plan:
render_plan_context(context/providers/plan_context.py:22),render_mission_context(providers/mission_context.py);Goal.current_step+advance_goal_step(session/controller/_goals.py:242) /set_goal_step(:265) - ✅ Bounded memory:
MemoryEngine.search(..., max_entries, max_age_seconds)—memory/memory_engine.py:209(Protocolcore/protocols/memory.py:191) - ✅ Semantic layer:
render_semantic_context(context/providers/semantic_context.py:52,@traces REQ-107-015) - ✅ AST layer:
context/providers/ast_context.py - ✅ Telemetry:
ContextUsage(context/budget.py:75),scripts/context_usage_report.py - ✅ Artifact store:
ArtifactStoreJSONL replay (core/artifact_store.py:196/233),render_artifact_digest(:393) - ✅ On-demand tools (all 4):
GetCodeTool:205,GetTestsTool:349,GetRequirementsTool:462,SearchCodeTool:617—tools/context_tools.py - ✅ Pack caching:
ContextPackCache(knowledge_graph/context_pack/cache.py:31) - ✅ Validator loop:
GraphContextValidator(graph_context_validator.py:87),ValidatorLoop(context_validator_loop.py:43),ContextExpansion(context_injector.py:100) - ✅ Runtime signals:
RuntimeSignalWriter(knowledge_graph/runtime_writer.py:42) - ✅ FR-012 freshness:
tools/ast_pipeline.py:119main(argv)(argv=None fix),--snapshot-only:125,--incremental:134 - ✅ FR-013/014:
deploy/install-claude-config.sh(31,393 B, delegatesclaude/pinned-ref + byte-exact check);deploy/ship.sh+shipon PATH
Remaining work / plan: None. Two cosmetic divergences only — spec names PlanParser/SemanticGraphContextProvider classes; code implements render_plan_context/render_semantic_context functions (same behavior, different shape). Effort —.
Evidence log:
symbols --pattern advance_goal_step|set_goal_step|RuntimeSignalWriter|GraphContextValidator|ValidatorLoop|ContextExpansion|ContextUsage|ArtifactStore|render_artifact_digest→ all presentsymbols --pattern Toolgrepcontext_tools→ 4 tool classessymbols --pattern max_entries→memory_engine.py:209source context.providers.plan_context --no-daemon→render_plan_context:22;source context.providers.semantic_context→render_semantic_context:52source tools.ast_pipeline --no-daemon→main:119,--snapshot-only:125,--incremental:134
SPEC-108 environment-installer — DIVERGENCE
Specifies: Tracked idempotent installers (claude-env/install.sh, install-infra.sh) replicating the global Claude layer (delegating to deploy/install-claude-config.sh) and the infra fleet (Incus/Terraform or Docker), with neo4j fleet (FR-007/008), license boundary, session-state replication.
Verified:
- ✅ FR-001 delegation:
claude-env/install.shdelegates config layer todeploy/install-claude-config.sh(CONFIG_INSTALLER, header + invocation); delegate exists (31,393 B) - ✅ FR-002 preflight:
install.shfail-fast tool check (git rsync cmp uv python3+ FT interpreter) - ✅ FR-003 dry-run:
--dry-runon both installers - ✅ FR-005 backend detection/choice:
install-infra.sh--backend incus|docker+--yes+ interactive - ✅ FR-006 terraform:
infra/terraformpresent - ⚠️ FR-007 incus fleet — DIVERGED: spec says "8-node public tier (redis, neo4j primary + 3 replicas, 3 prolog/app)". Current
infra/rawmachine/main.tfdefines onlyincus_instance "redis"(:57) +incus_instance "prolog"withfor_each local.prolog_nodes(:78,node-1/2/3:44) = 4-node fleet. neo4j tier retired 2026-07-27 (install-infra.sh header). Orchgraph/memgraph tier is private-release only (coordinator.yaml.tftpl/data_node.yaml.tftplexist ininfra/cloud-init/but are NOT referenced bymain.tf). - ⚠️ FR-008 docker fleet — DIVERGED: spec says "redis + neo4j primary + 3 workers + memgraph-community". Current
infra/docker/infra-compose.ymlservices =redis,memgraph,memgraph-data(3 services, no neo4j). - ✅ FR-009 license boundary:
infra-compose.ymlusesmemgraph/memgraph:3.11.0(community), orchgraph private path stated ininstall-infra.shheader - ✅ FR-011 cloud-init systemd:
infra/cloud-init/{redis,prolog,prometheus}.yaml+ coordinator/data templates - ✅ FR-010 session-state:
context.json/context.md/context.history.mdtracked in repo (present at repo root) - ✅ FR-012 suite acceptance: trigger-armed (no code change possible to verify; infra build is the trigger)
Remaining work / plan: Narrow — update spec FR-007/FR-008 (and "Complete" status) to the neo4j→orchgraph/memgraph retirement; the installer machinery itself is built and functional. Scope: spec text + verification table. Target: specs/108-environment-installer/spec.md. Approach: amend FR-007 (4-node redis+3 prolog public tier, orchgraph via private release) and FR-008 (redis+memgraph community+data). Dependencies: none. Effort S, low risk.
Evidence log:
ls claude-env/ deploy/ infra/→ install.sh, install-infra.sh, install-claude-config.sh, infra/docker, infra/rawmachine, infra/cloud-initgrep -nE 'resource "incus_instance"' infra/rawmachine/main.tf→ only redis + prolog (2 blocks, prolog for_each 3)grep -nE '^ [a-z-]+:$' infra/docker/infra-compose.yml→ redis, memgraph, memgraph-datagrep -n 'prolog_nodes' infra/rawmachine/main.tf→node-1/2/3 = 16/17/18
SPEC-109 rename-engine — DONE
Specifies: Type-resolved (basedpyright LSP) symbol rename with same-name disambiguation, atomic module move, declarative rename plans, residue report, volk tool.
Verified:
- ✅ FR-001 LSP transport:
LspTransport(lsp_client.py:70),PyrightLangServer(:438, open_document/prepare_rename/rename/definition) - ✅ FR-002 workspace config:
WorkspaceConfigBuilder(workspace.py:37); FR-003 preflight:ResolutionPreflight(workspace.py:98) - ✅ FR-004 symbol rename:
SymbolRenamer(symbol_rename.py:37,_prepare_or_refuse,_assert_no_foreign_definition) - ✅ FR-005 oracle/residue:
CandidateScanner(scanner.py:43),ResidueClassifier(residue.py:227) - ✅ FR-006 module move:
ModuleMover(module_move.py:74) - ✅ FR-008 plan:
RenamePlan(plan.py:81),load_plan(plan.py:245); FR-009 executor:PlanExecutor(executor.py:131),EditApplier(applier.py:44,_resolve_in_repopath guard) - ✅ Models contract:
RenameStatus:33,RenameOutcome:118(models.py) - ✅ FR-010 CLI:
scripts/rename_engine.pysubcommandssymbol|module|plan|report(:84/92/98/103), dry-run default - ✅ FR-011 tool:
RefactorRenameTool(tool.py:84,requires_approval,executenever raises) - ✅ 13 modules in
refactor/rename/(applier, executor, lsp_client, models, module_move, plan, report, residue, scanner, string_refs, symbol_rename, tool, workspace)
Remaining work / plan: None. Note: spec explicitly scopes agents/tool_registry.py wiring OUT of SPEC-109 (later step), so its absence is not a gap. Effort —.
Evidence log:
ls src/orchestrata_ultimate/refactor/rename/→ 13 filessymbols --pattern LspTransport|ResolutionPreflight|WorkspaceConfigBuilder|CandidateScanner|ResidueClassifier|EditApplier|ModuleMover|PlanExecutor|load_plan|PyrightLangServer|RefactorRenameTool→ all presentgrep add_parser scripts/rename_engine.py→ symbol/module/plan/report
SPEC-110 codemod-engine — DONE
Specifies: In-memory lossless CST-forest platform: load/index (CIG+CSR), composable transforms, review-before-write, transactional write-back, graph persistence, observability, analysis passes, 40-check in-memory review, warm daemon.
Verified:
- ✅ FR-001 load:
CodemodWorkspace(workspace.py:248); FR-002 indexmodules/dependencies/dependents/symbol_table - ✅ FR-003 transforms (5):
TransformPass:50,ReplaceStringLiteralPass:268,AddImportPass:470,RemoveUnusedImportPass:666,DocstringSweepPass:878,RenameSymbolPass:943(passes.py) - ✅ FR-004 reviews (4):
ReviewPass:135(Protocol),ParseIntegrity:144,BannedConstructs:183,DiffBudget:275,PrologSemanticReview:338(review.py) - ✅ FR-008 CIG:
CodeIntelligenceGraph(_cig.py:28),_CSRIndex(_csr_index.py:18); builder_cig_builder_ast.py(ADR-0068 ast overlay) - ✅ FR-005 txn:
commit_changes(txn.py:125) - ✅ FR-006 CLI:
scripts/codemod.pysubcommands load-bench/run/report/analyze (:64/71/128/138) - ✅ FR-009 observers (5):
TracingObserver,GraphWriterObserver,ErrorDetector,MetricsObserver,DebugPanelObserver(observability/*.py) - ✅ FR-010 persistence:
CodemodGraphRepository(persistence/repository.py:24),BoltSyncCodemodRepository(:43) - ✅ FR-011 analysis (7):
BlastRadiusAnalyzer,BreakingChangeDetector,ComplexityAnalyzer,TestCoverageMapper,AbstractionAnalyzer,CouplingAnalyzer,DeadCodeDetector(analysis/*.py) - ✅ FR-012 review engine:
InMemoryReviewEngine(review_engine.py:151);ctok/token array +review_catalogue.py/review_checks.py/review_context.py - ✅ Daemon (REQ-110-133..140):
CodemodDaemon:46,CodemodServer:139,CodemodClient:35,FileWatcher:54,_daemon_entry.py; C extscripts/_codemod_fast/ - ✅ Prolog:
prolog/codemod_review.pl(pass_safe/blast_radius_ok/rename_safe/string_replace_safe)
Remaining work / plan: None. Two spec-text nuances: ReviewPass is a Protocol not ABC (review.py:135), and _cig_builder.py shipped as _cig_builder_ast.py (ADR-0068). Effort —.
Evidence log:
symbols --pattern CodemodWorkspace|CodeIntelligenceGraph|_CSRIndex|TransformPass|ReviewPass|ChangeSet|CommitReport|Finding|CodemodGraphRepository|BoltSyncCodemodRepository→ all presentsymbols --pattern CodemodDaemon|CodemodClient|CodemodServer|FileWatcher|RenameSymbolPass|ReplaceStringLiteralPass|AddImportPass|RemoveUnusedImportPass|DocstringSweepPass|ParseIntegrity|BannedConstructs|DiffBudget|PrologSemanticReview|InMemoryReviewEngine→ all presentls refactor/codemod/{observability,analysis,persistence}/→ 7 observers/files, 11 analysis files, repository.pygrep add_parser scripts/codemod.py→ 4 subcommands;symbols --pattern commit_changes→txn.py:125
SPEC-111 live-code-substrate — GAP
Specifies: Resident multi-agent substrate: warm forest daemon, subtree checkouts + MVCC delta/merge queue, streaming per-delta gates, basedpyright oracle over in-memory buffers, crash-safe checkpoints, agent steering, deterministic Prolog write-gate + escalation loop.
Verified:
- ❌
refactor/codemod/substrate/,delta/,oracle/,stream/,checkpoint/— none exist (ls→ No such file or directory) - ❌ FR-002 subtree checkouts / FR-003 delta+invert+describe / FR-007 checkpoint / FR-008 steering — no symbols (
symbols --pattern Substrate|invert|describe|checkpoint→ only unrelatedfactory/scheduler/queue.py:MergeQueue:88(SPEC-033) andfactory/enforcement) - ❌ FR-005 streaming gates / FR-006 oracle (only reuse target
lsp_client.pyexists) / FR-009 Prolog write-gate escalation loop — unbuilt - ⚠️ FR-001 daemon residency: PARTIAL — skeleton exists (
CodemodDaemon:46,CodemodServer:139,CodemodClient:35,FileWatcher:54from SPEC-110) +scripts/ast_daemon.py/ast_daemon_publish.py(FR1-004, ADR-0097), but no subtree-checkout API or multi-agent delta path on top
Remaining work / plan: Scope: 5 new packages (substrate, delta, oracle, stream, checkpoint) + steering + write-gate. Target files: src/orchestrata_ultimate/refactor/codemod/{substrate,delta,oracle,stream,checkpoint}/. Approach: build FR-001 wiring (watcher→incremental reparse already noted resolved 2026-08-03), then FR-002/003 delta+merge, then FR-004..009 gates/oracle/checkpoint/steering/write-gate. Dependencies: SPEC-110 (forest/CIG/txn), SPEC-109 (lsp_client), SPEC-033 (MergeQueue model). Effort XL, high risk (P0 multi-week substrate; concurrency + optimistic-concurrency core).
Evidence log:
ls src/orchestrata_ultimate/refactor/codemod/substrate→ No such file or directory (×5 for substrate/delta/oracle/stream/checkpoint)symbols --pattern Substrate|invert|describe→ no SPEC-111 symbolsls scripts/ast_daemon.py scripts/ast_daemon_publish.py→ both exist
SPEC-112 scripts-to-modules — GAP
Specifies: Consolidate scripts/ to thin CLI shims; extract 6 category-A scripts (flagship serialize_codebase_ast.py → refactor.codemod), 52 category-B, audit 79 category-C, enforce a thin-shim gate.
Verified:
- ⚠️ Mapping committed:
plans/scripts-migration-map.json(30,932 B) exists - ❌ Category-A NOT extracted:
serialize_codebase_ast.pystillscripts/(553,182 B), pluscodemod.py,pyright_autofix.py,add_traces_from_evidence.py,attribute_traces_runtime.py,refactor.pyall stillscripts/*.py - ❌
refactor/package has no AST-toolkit module (ls refactor/→ agent.py, codemod, ctok, init, rename, tools.py) - ❌ FR-007 gate:
symbols --pattern scripts_are_thin→ 0 symbols; no gate - ⚠️ scripts/ has grown to 181
.pyfiles (spec baseline: 137) - ✅ One incidental extraction:
run_ast_pipeline.pyis now a thin shim →orchestrata_ultimate.tools.ast_pipeline(tools/ast_pipeline.py)
Remaining work / plan: Scope: category-A first (flagship AST-toolkit decomposition from a 12K-line script), then B by package, then C audit + FR-007 gate. Target files: scripts/serialize_codebase_ast.py → refactor/codemod/*, 5 more A-scripts, 52 B-scripts; new standards package. Approach: behavior-preserving extraction (shim --help/outputs byte-compatible), @traces + gates on extracted modules. Dependencies: SPEC-110/111 (substrate needs the toolkit importable). Effort XL, high risk (12K-line decomposition + 52-package migration + gate).
Evidence log:
ls -la plans/scripts-migration-map.json→ 30,932 Bls -la scripts/serialize_codebase_ast.py→ 553,182 B (still a script)for f in pyright_autofix.py add_traces_from_evidence.py attribute_traces_runtime.py refactor.py codemod.py serialize_codebase_ast.py; do ls scripts/$f; done→ all STILL-SCRIPTls scripts/*.py | wc -l→ 181symbols --pattern scripts_are_thin→ 0 symbolshead scripts/run_ast_pipeline.py→ thin shim →orchestrata_ultimate.tools.ast_pipeline
SPEC-113 measurement-retention — PARTIAL
Specifies: Retain test/runtime measurements with joinable run identity (never statistical prediction): run/batch identity, per-phase durations, per-fixture cost, freshness guard, container-CPU floor, Prolog-boundary prohibition.
Verified:
- ✅ FR-001 run identity:
run_identity(pytest_live_observer.py:283),_run_identity(scripts/run_tests.py:329) - ✅ FR-002 phase durations:
phase_durations_ndjson_path(:255),_append_test_phase_durations(:368) - ✅ FR-003 instrument (BUILT):
pytest_fixture_setup(pytest_live_observer.py:634, hookwrapper,ORCH_FIXTURE_COST_DIRgated) - ❌ FR-003 reader (REQ-113-FR3-002) — STILL OPEN: no reader consumes
fixture-durations-*.ndjson; only reference is the writer (grep -rl fixture-durations scripts/ src/→pytest_live_observer.pyonly). Top-N-fixtures-by-setup report unmet. - ✅ FR-004 freshness guard:
scripts/freshness_guard.py+scripts/run_tests.pyinvokes it - ✅ FR-005 container CPU:
_snapshot_container_cpu_before(run_tests.py:998),_measure_container_cpu(:1025),scripts/container_cpu_accounting.py - ✅ FR-006 prohibition: standing (no statistical facts in
prolog/; verified no change in mechanism shape)
Remaining work / plan: One small reader. Scope: scripts/ fixture-durations reader (or extend scripts/test_durations.py) answering "top-N fixtures by total setup seconds for run R" from retained rows. Target: scripts/test_durations.py (or new scripts/fixture_durations.py). Approach: glob fixture-durations-*.ndjson, group by fixture argname/scope, join (run_id,batch_id), report top-N. Dependencies: none. Effort S, low risk. (The spec's own 2026-08-20 status already flags this as the sole open item in FR-001..FR-005.)
Evidence log:
symbols --pattern pytest_fixture_setup|run_identity|_append_test_phase_durations|phase_durations_ndjson_path→ all presentgrep -rl fixture-durations scripts/ src/→ onlypytest_live_observer.py(writer); no readersymbols --pattern _snapshot_container_cpu_before|_measure_container_cpu→run_tests.py:998/1025ls scripts/test_durations.py scripts/freshness_guard.py scripts/container_cpu_accounting.py→ all present
SPEC-114 governance-rule-learning — PARTIAL
Specifies: Induce governance rules from open-vocabulary defect corpora (LEARN), quarantine as pending (QUARANTINE), promote by dual human review (PROMOTE), why-not sidekick (EXPLAIN).
Verified:
- ❌ FR-001 LEARN: no miner induces
.plcandidate rules. Onlyscripts/mine_prompt_history.py(advisory rulings miner, "never writes a ruling"). NoGovernanceRuleLearner/rule_learningmodule. - ⚠️ FR-002 QUARANTINE — PARTIAL:
- ✅ REQ-114-FR2-004(a) clause-count invariant BUILT:
gates/engine.py:297rules_loaded != expected→ clobber reason (supersedesrules_loaded == 0-only guard) - ✅ REQ-114-FR2-004(b) redefinition check BUILT:
scripts/prolog_meta_lint.py:1049check_no_redefinition - ❌ quarantine rulebase NOT built:
candidate_violation/4absent (grep -rl candidate_violation prolog/→ nothing); nopendingseverity ingate_severity.pl(onlyerror/warning)
- ✅ REQ-114-FR2-004(a) clause-count invariant BUILT:
- ❌ FR-003 PROMOTE: no induced-rule promotion path (substrate
factory/promotion/store.pyexists; no SPEC-114 promotion of learned rules, no demotion) - ✅ FR-004 EXPLAIN — DONE:
scripts/trace_intel.pywhy-notsubcommand (:1170,_cmd_why_not:1092→tool_why_not_req), fact layer +requirement_implemented/2decomposable body intools/traceability_db.pl(req_traced_by_code:196); freshnesssidekick_precondition_report/1; acceptance MET 2026-08-21 per spec (named conjunct, not empty list)
Remaining work / plan: Scope: (1) LEARN miner over rulings/adjudications/postmortems → provenance'd .pl candidates + tombstones; (2) quarantine rulebase with candidate_violation/4 + :- module + pending severity value in gate_severity.pl (one channel); (3) PROMOTE .pl-diff + dual-review + demotion. Target files: new src/orchestrata_ultimate/governance/rule_learning/ (or scripts/mine_governance_rules.py), prolog/gate_severity.pl, prolog/quarantine.pl. Approach: FR-002 quarantine isolation (head+module, not file) first (prerequisites already landed), then FR-001 miner, then FR-003 promotion. Dependencies: SPEC-113 FR-006 (statistical-fact boundary is the shared prohibition); explain.pl/ADR-0031; factory/promotion/store.py. Effort L, high risk (correctness of gate isolation is load-bearing — the spec documents a measured 5→1 clobber).
Evidence log:
ls scripts/ | grep -iE 'mine|learn|induc|rule'→ onlymine_prompt_history.pygrep -rl candidate_violation src/orchestrata_ultimate/prolog/→ exit 1 (absent)grep -n pending gate_severity.pl→ absentgrep -nE 'def check_' scripts/prolog_meta_lint.py→check_no_redefinition:1049(plus the 4 original checks)grep -n rules_loaded gates/engine.py→:297rules_loaded != expectedguardgrep -nE 'why-not|why_not|requirement_implemented' scripts/trace_intel.py tools/traceability_db.pl→ present
Cluster summary
| Spec | Class | Effort | Hard deps |
|---|---|---|---|
| 106 context-semantic-layer | DONE | — | — |
| 107 context-injection-improvements | DONE | — | — |
| 108 environment-installer | DIVERGENCE | S | — (spec-text amend for neo4j retirement) |
| 109 rename-engine | DONE | — | — |
| 110 codemod-engine | DONE | — | — |
| 111 live-code-substrate | GAP | XL | SPEC-110, SPEC-109, SPEC-033 |
| 112 scripts-to-modules | GAP | XL | SPEC-110/111 (toolkit importable) |
| 113 measurement-retention | PARTIAL | S | — (FR-003 reader) |
| 114 governance-rule-learning | PARTIAL | L | SPEC-113 FR-006, explain.pl/ADR-0031, factory/promotion |
Cross-cluster dependencies
- SPEC-111 ← SPEC-110 + SPEC-109 + SPEC-033: substrate composes forest/CIG/txn (110),
lsp_clientoracle (109), MergeQueue model (033). - SPEC-112 ← SPEC-110/111: extracting the AST toolkit into
refactor.codemodis the substrate's own engine; 112 is sequenced FIRST (unblocks 110/111). - SPEC-114 ← SPEC-113 FR-006: the statistical-facts-into-Prolog prohibition is the shared boundary between measurement retention and rule learning.
- SPEC-113 + SPEC-114 jointly supersede
docs/architecture/learning.md(retired vision doc).