# Implementation Plans

Generated by the `improve` skill on 2026-07-13 against commit `31afb08`,
reconciled on 2026-07-18 against commit `3d768f3` after PR #414 merged, and
extended on 2026-07-19 against commit `f839477` by a delta audit of the code
merged since `31afb08` (PRs #400–#414 source changes; the prior deep audit
covered everything older), and reconciled on 2026-07-20 after PR #421 merged.
The separately commissioned post-GO dataflow exhaustive-state plan was
completed after `e925853`. Under this root plan workflow, completed plan files
are deleted and Git history is the recovery path; this is distinct from the
parent `docs/plans/` archive protocol.

Future plans are implementation handoffs, not permission to push, publish,
deploy, or open a pull request. Those actions require separate operator
instruction.

## Execution order and status

| Plan | Title | Priority | Effort | Depends on | Status |
|---|---|---:|---:|---|---|
| 014 | Deepen the typed-sheet application owner | P1 | L | Accepted EGW projection boundary; completed Plan 013 adapter | DONE (closed 2026-08-02; private owner deepening complete) |
| 013 | Run the typed-spreadsheet EGW boundary experiment | P1 | L | Published EGW 0.4.0 | DONE (closed 2026-07-24; bounded adapter experiment complete) |

Status values: `TODO` | `IN PROGRESS` | `DONE` |
`BLOCKED (<reason>)` | `REJECTED (<reason>)`.

Plan 013 completed the first application-specific EGW adapter and evidence
harness for
[dowdiness/event-graph-walker#72](https://github.com/dowdiness/event-graph-walker/issues/72).
It remains inside the standalone `incr` repository and adds no generic
`egw_incr` bridge. The reconciliation note below records the bounded result,
dependency convergence, decision record, and separately shaped follow-ups.

## Reconciliation notes

- Plan 015 is complete. K1.1–K1.6 are accepted/merged, establishing the
  semantic kernel, independent Fresh oracle, ownership closure, and generated
  shrinkable conformance for the unpublished `dowdiness/incr_next` sibling.
  The accepted product decision is [ADR 2026-08-17](../docs/decisions/2026-08-17-incr-next-pre-1-0-sibling-product.md),
  and the implementation record remains at the [Plan 015 GitHub blob at
  commit 5846993](https://github.com/dowdiness/incr/blob/58469934c5644686992688bc7a9f1685326a081d/plans/015-incr-next-kernel-alpha.md).
  Publication, K2 implementation, Mount, Program/Port/Formula, and Canopy
  production integration remain gated; K2 is next but not yet commissioned.

- Plan 014 closed 2026-08-02 after implementation commits `ef89254` through
  `c005130` deepened the private typed-spreadsheet shell into one
  `TypedSheetApplication`. The owner now hides state, five Programs, renderer,
  EGW adapter, AI publication, collaboration callbacks, and teardown while the
  sole public callable remains `mount_typed_spreadsheet_incr_tea_demo`.
  Validation covered all six demo package roots (99 targeted JS tests), the
  workspace (1,131 wasm-gc and 256 JS tests), release/browser build and smoke,
  9 standalone DOM scenarios, 7 same-origin collaboration scenarios, 4 Worker
  hibernation tests, and both 11-scenario Worker collaboration modes. Locked
  interface and post-fix MoonBit reviews passed against `origin/main`
  `7a336e9`. `npx playwright install chromium --with-deps` could not repeat the
  system-package installation because passwordless `sudo` was unavailable;
  the already-installed Chromium and system dependencies ran every browser
  gate successfully. The completed plan file is deleted; Git history recovers
  the execution record. Publication, PR creation, and any parent Canopy
  submodule-pointer update remain separate authorized tasks.
  **No ADR needed:** this private, behavior-preserving application-local
  deepening implements the existing EGW, `incr_tea`, collaboration, and AI
  context decisions without changing their contracts.
- Plan 013 closed 2026-07-24 as a completed bounded adapter experiment.
  Correctness and application boundary succeeded: committed browser commands
  use EGW authority and local/remote projection uses one path. The
  pre-registered browser-baseline rule stopped adapter browser A/B, so
  performance outcome is inconclusive and authorizes no EGW performance/API
  proposal. The original browser-comparison criterion remains intentionally
  unmet because its prerequisite baseline failed; closure records that terminal
  outcome and does not claim the missing comparison was completed.
  Error-transparent property mutation and conservative post-apply impact
  reporting remain deferred/rejected-for-now until second-driver,
  compatibility, convergence, and quantified-gain gates pass. The existing
  [EGW register-projection ADR](../docs/decisions/2026-07-20-typed-spreadsheet-egw-register-projection.md)
  is the updated decision record; its API-quality checkpoint now contains the
  durable conclusions. The completed plan file is deleted; Git history recovers
  the execution record. Transport, payload-opaque runtime/provider, room/join
  UX, and presence are separate follow-ups.
- Plan 012 shipped in [PR #421](https://github.com/dowdiness/incr/pull/421),
  merged as commit `d512b63`. Package-local parse-don't-validate `SheetCommand`
  variants own submitted text, typed `CellId`, `DocumentGeneration`, and
  variant-implied preconditions; `UiEffect` is focus-only; AI publication
  remains unconditional. Public `incr_tea`, `incr`, `typed_spreadsheet`, and
  EGW APIs are unchanged. The future application-specific EGW adapter and
  formula policy remain separate; issue
  [dowdiness/event-graph-walker#72](https://github.com/dowdiness/event-graph-walker/issues/72)
  remains driver-gated; no generic `egw_incr` bridge. No ADR needed: this is an
  application-local unpublished pilot.
- Plan 009 added lifecycle contract tests for rejecting relation/rule disposal
  during a fixpoint and for rebuilding a fresh Datalog graph after full teardown
  in the same runtime. Execution found that the original plan had mistaken
  disposed-slot guards for support of mid-fixpoint mutation; those guards only
  skip tombstones created before evaluation. Its completed plan file was
  deleted; Git history recovers the execution record. Decision record: the
  existing [Datalog relation-rule lifecycle ADR](../docs/decisions/2026-07-18-datalog-relation-rule-lifecycle.md)
  was updated to record the stable-program invariant.
- Plan 008 extended controlled `value` reconciliation to `<textarea>` in
  [PR #418](https://github.com/dowdiness/incr/pull/418), merged as commit
  `889ac2d`. Its completed plan file was deleted; Git history recovers the
  execution record. Decision record: the existing
  [controlled form-property ADR](../docs/decisions/2026-07-15-incr-tea-controlled-form-properties.md)
  was amended to define `attr("value", value)` as explicit controlled intent on
  input, select, and textarea elements.
- Plan 011 completed its deterministic 5,424-case dataflow matrix; the module
  README retains the bounded exhaustive evidence. No ADR needed: the change is
  test-only and preserves the accepted module boundary.
- Plan 007 was independently verified and merged in
  [PR #415](https://github.com/dowdiness/incr/pull/415) as commit `823e63f`.
  Its completed plan file was deleted; Git history recovers the execution
  record. No ADR needed: this is a small local checker bug fix guarded by
  regression tests.
- Plan 006's 17 immutable GitHub Action references, syntax checks, repository
  checks, and GitHub-hosted CI were verified after PR #414 merged. Its completed
  plan file was deleted; Git history recovers the execution record.
- R03 is complete: `CLAUDE.md` is a symlink to canonical `AGENTS.md`.
- R06 is complete: commit `b1a4531` deleted the stale alien-signals comparison
  and refreshed the surviving Salsa comparison.
- R15's timing-evidence gate has fired now that Plan 006 is complete, but no CI
  performance investigation is commissioned.
- R16 is complete: PR #408 shipped the typed-spreadsheet `incr_tea` proof and
  issue #268 is closed.
- R21 remains blocked. The repository pins MoonBit `0.10.4+ade96c819`; its
  official GitHub release still contains only `moonbit-wasm.tar.gz`, not the
  native CLI-plus-core artifacts and independent provenance required by R21.

## Recorded for later revisit

The deep audit findings not selected for implementation are retained here so a
future audit does not rediscover them without context. `RECORDED` means no
implementation is currently commissioned. `BLOCKED` means the opportunity is
valid but its explicit external evidence gate has not fired.

| ID | Opportunity | Category | Est. | Revisit trigger / next evidence | Status |
|---|---|---|---:|---|---|
| R01 | Delete stopped animation-frame loop tombstones from `globalThis.__incrTeaRafLoops` while preserving stop-during-callback race safety | bug/tests | S | Add a JS store-size stress test and a stop-during-callback case against the shared-Program mount-lifecycle baseline | RECORDED |
| R02 | Enforce committed `pkg.generated.mbti` freshness in CI with `moon info` plus a clean-diff gate | dx/tests | S | After R21's provenance gate fires and a canonical verified bootstrap lands | RECORDED |
| R03 | Replace stale `CLAUDE.md` API/package duplication with a short pointer to canonical `AGENTS.md` | docs/dx | S | `CLAUDE.md` now resolves to `AGENTS.md` through the required symlink | DONE |
| R04 | Remove the repository-authored `REQUIRED SUB-SKILL` agent directive from the shipped `docs/plans/2026-06-25-program-stateful.md` plan and prevent shipped plans from being indexed as executable | security/docs | S | Combine with R05; retain historical intent without direct agent commands | DONE |
| R05 | Rebuild `docs/roadmap.md`, `docs/todo.md`, and the `docs/README.md` Active Plans list as a target-vocabulary current backlog; archive shipped `Expr`, hooks, and `Program::stateful` work | docs | M | Maintainer chooses the one canonical current-priority document | DONE (completed-plan cleanup) |
| R06 | Refresh or explicitly mark historical the Salsa and alien-signals comparison documents, which describe shipped subscriber/effect/GC work as deferred and show removed APIs | docs | M | Commit `b1a4531` retired the alien-signals note and refreshed the Salsa note | DONE |
| R07 | Repair `incr_tea` relocation links and update the direction note to distinguish the root framework module from the `examples/incr_tea` harness | docs | S | Next `incr_tea` documentation pass | RECORDED |
| R08 | Remove or rename publicly exposed legacy `ReactiveId` in `dowdiness/incr/types` without breaking supported consumers | architecture/migration | S | After R02; first confirm whether any external deep-package consumer exists | RECORDED |
| R09 | Make the Rabbita demo's local `build:moonbit` script honor `NEW_MOON_MOD=0` and target only its own package | dx | S | Next demo-tooling cleanup | RECORDED |
| R10 | Measure the production renderer tax from unconditional derived-event recompute instrumentation | perf investigation | M | Add enabled/disabled JS/browser measurements; optimize only on a material result | RECORDED |
| R11 | Establish a real 50×50 spreadsheet interaction benchmark covering selection, typing, and commit with sparse/dense drafts | perf investigation | M | Before changing draft lookup shape, view windowing, or render boundaries | RECORDED |
| R12 | Re-measure keyed prepend/removal DOM work and compare an anchor-based minimal-move prototype | perf investigation | M | Current Chromium numbers reproduce and move counts dominate | RECORDED |
| R13 | Measure stable subscription reconciliation at 0/1/16/256 subscriptions before adding version/change gating | perf investigation | M | Stable-set scans and allocations are material in JS measurements | RECORDED |
| R14 | Benchmark disconnected Datalog graphs with 1/100/1,000 rules before considering active-rule scheduling | perf investigation | S benchmark / L fix | Whole-runtime scanning dominates a realistic workload | RECORDED |
| R15 | Measure repeated MoonBit installation/update time across CI jobs before adding caches or consolidating jobs | perf/dx investigation | S | Plan 006 is complete; use PR #414 Actions timing data and preserve failure isolation | RECORDED |
| R16 | Complete the typed-spreadsheet `incr_tea` integration as the framework acceptance driver | direction | L | PR #408 shipped the proof and closed issue #268 | DONE |
| R17 | Add namespace-aware SVG support after controlled-form correctness | direction | M | Controlled-form reconciliation is complete; remaining trigger is an editor/diagram consumer supplying acceptance cases | RECORDED |
| R18 | Run reactive-collection driver discovery in Canopy before adding any `ReactiveMap`, relation-delta, or cleanup public API to `incr` | direction/spike | M | A downstream workload proves `DerivedMap` insufficient | RECORDED |
| R19 | Explore WebComponent/custom-element mount boundaries as a spike, not a stability commitment | direction/spike | M–L | The editor driver demonstrates concrete embedding and teardown pressure | RECORDED |
| R20 | Retire or refresh `docs/research/next-sessions-runtime-roadmap.md`, whose mandatory starting point predates composable listeners and the v0.13/v0.14 boundary cleanup | docs | S–M | Combine with R05 or revalidate across Loom and Canopy | DONE |
| R21 | Replace the mutable MoonBit installer/setup path with an independently verified native CLI-plus-core bootstrap | security/ci | M | Official MoonBit publishes durable versioned native CLI and core artifacts plus immutable vendor-published digests, signatures, or attestations for the repository's pinned version; do not substitute mutable `latest` checksums, runtime-computed digests, or the WASM compiler release | BLOCKED (vendor provenance) |
| R22 | Bound the `ViewUnchanged` controlled-reconcile scan (`renderer_js.mbt` `reconcile_controlled_rendered` recurses all nodes and attrs on every no-op flush) e.g. by recording controlled-subtree presence at render time | perf investigation | M | JS/browser measurement on a large mostly-static tree shows the per-flush traversal is material; `controlled_reconcile_dom_bench.mbt` is the starting harness | RECORDED |
| R23 | Decide the Scope-vs-datalog bulk-disposal contract: `Scope` disposes owned cells in registration order (`scope.mbt:108-110`), which would dispose relations before their pinning rules if datalog `CellId`s were ever adopted via `add_cell_ids` | architecture | M | Latent — no current constructor scopes datalog cells; decide (reverse-order disposal or explicit rejection of datalog ids) before scoping datalog lifecycles | RECORDED |
| R24 | AI-context operation intake: the spreadsheet demos publish a read-only `AiContextSnapshot` (globalThis accessors, evidence classification) with no matching `apply(op)` intake; a validated command intake routed through `run_batched_op` would close the agent loop. Trust boundary for agent-authored formula text must be decided first | direction/spike | L (coarse) | Maintainer wants the closed-loop AI spreadsheet driver; `bench_api.mbt`'s dispatch-from-JS harness proves the mechanism | RECORDED |
| R25 | Separate Runtime memo-hook selection policy from execution with a small pure `HookDispatchPlan`; do not introduce services/packages or alter hook ordering | architecture | S | Reopen only when a second event-surface family (push/effect/fixpoint) lands, another non-delegator coordinator concern appears, or index/order coupling causes a concrete defect | RECORDED |

## Findings considered and rejected

- **Runtime-to-services decomposition**: rejected by the current R2 ADR. The
  runtime is a coordinator facade over already-separated engines; no second
  consumer or dependency-injection driver exists.
- **Per-mode Runtime split**: rejected by ADR. One revision clock and
  cross-strategy edges are intentional differentiators, not accidental coupling.
- **Optimize `AccumulatorCommitHook::after_abort`'s quadratic scan now**:
  rejected for current workloads. The repository's measured evidence says real
  consumers use roughly 1–2 accumulators per memo; reopen only around 50+
  accumulators with frequent aborts.
- **Treat `Derived::map_no_backdate`'s permissive read as an observer-allocation
  performance bug**: rejected after source verification. Current strict and
  permissive reads share `read_honest()` internally; the difference is the
  tracked-context guard, not an extra observer lifecycle.
- **Expose the private static/applicative Derived fast path now**: rejected by
  the accepted public-surface ADR until `Expr`, an attachment pipeline, or a
  downstream UI supplies a measured driver. The shipped dynamic `map` helpers
  do not reopen that decision.
- **Consolidate CI jobs solely because installation is duplicated**: not
  commissioned without timing evidence. R15 preserves the measurement question;
  PR #414 pins third-party action code without changing job isolation, while
  R21 separately tracks the blocked MoonBit bootstrap provenance gap.
- **`request_after_flush` per-command snapshot allocation**
  (`incr_tea/program.mbt:221-228`): the `.map` is a defensive copy against
  re-entrant registration mutation, runs only per `AfterFlush` command (not
  per flush), and is negligible. Not worth doing.
- **Machine-composition bench mutation-observer leak on assertion failure**
  (`machine_composition_dom_bench.mbt` sets the module-global
  `dom_set_property_mutation_observer` and resets it only on the success
  path): benchmark-only, affects no shipped code path. Not worth doing.
- **Introduce a `ScopeDisposePlan` now**: rejected. `Scope::dispose` already
  closes before effects, is re-entrant safe, documents and directly implements
  the short children → hooks → cells order, and has lifecycle coverage. A plan
  value would currently repackage the same mutable handles and closures without
  reducing meaningful policy complexity. Reopen only for branching teardown
  policy, recoverable/async teardown, a concrete ordering bug, or scoped
  Datalog ownership that invalidates registration-order disposal (R23).

## Audit coverage and verification note

The source audit covered every active workspace package and all nine Improve
categories. Historical files under the retired archive, external Loom/Canopy
source, network dependency advisories, runtime tests, builds, and benchmarks
were not executed during the read-only audit.

This reconciliation verified the merged Plan 006 action inventory, `actionlint`,
documentation boundaries, PR #414's merged state, and its GitHub-hosted checks.
The full MoonBit suite was not rerun because reconciliation changes only plan
metadata and deletes the completed plan record.

The 2026-07-19 delta audit (standard level) covered only source changed in
`31afb08..f839477`: `incr/cells` datalog lifecycle + scope + kernel fixpoint,
`incr_tea` renderer/program/controlled-forms/machine-composition, the
spreadsheet-demo AI-context code, changed CI workflows, and the new
documentation-boundary scripts. It did not re-audit unchanged code, execute
tests/builds/benchmarks, or audit external Loom/Canopy source. Key vetted
verifications: the `urlsplit` scheme misparse behind Plan 007 was reproduced
directly; the `<textarea>` exclusion behind Plan 008 was confirmed at
`renderer_js.mbt:581`/`:723` with reachability via the public
`node(tag, ...)` constructor; the delta's CI workflow steps preserved PR
#414's SHA pinning, and no injection sinks or secrets were found in the
changed code.
