Plan: Govern Project Settings and Scaffold State Safely
Plan: Govern Project Settings and Scaffold State Safely
Plan State
- Status: complete; T1-T8, final review, tracker reconciliation, draft-PR verification, and stack dry-run gate passed
- Mode: sequential implementation inside this epic child PR, with cross-epic task-order dependencies
- Scope: IP-318 with every IP-327, IP-328, and IP-329 acceptance signal
- Planning branch:
team/stefan/ip-318-settings-state - Current delivery branch:
team/stefan/m7-m9-effect-v4-convergence, draft PR #87 based onteam/stefan/refactor-cli-architecture; original draft PR #80 remains a sibling source PR - Pull-request base intent:
team/stefan/refactor-cli-architecture, nevermain - Merge policy: keep this child PR draft, unmerged, and undeployed
- Completed work: T1 and T2 for IP-327; T3 and T4 for IP-328; T5 and T6 for IP-329
- Ready work: none inside IP-318; draft PR #87 remains open for maintainer review
Initial Situation
Project settings are currently implemented inside apps/cli/src/core/tools.ts beside process execution and tool bootstrap. Commands call readRepoSettings and writeRepoSettings directly. writeRepoSettings(..., { stampVersions: false }) is the current behavioral switch between user-choice and managed-version writers. Invalid settings normalize to null, while some legacy inference reads wiki hints and git config. This does not expose a typed distinction among missing, safely upgradable, ambiguous, and invalid state.
Before T2, lifecycle behavior was also split. The former nested init route prompted and wrote initial settings, hi ensure rewrote selected fields, hi check read version pins, and hi update independently derived an expected temporary tree, compared it to disk, applied whole-file changes, removed stale paths, and replaced the manifest. The manifest therefore participated in both ownership discovery and replacement even though the accepted design limits it to successful-application evidence.
The IP-319 behavior-contract work on the parent architecture branch characterizes current CLI/context/scaffold output. Its accepted evidence closes IP-330 in repository truth, although Linear IP-318 remains Backlog with a 2026-07-16 comment saying delivery should wait for IP-319/IP-330 closure. This tracker checkpoint is stale relative to the approved IP-318 spec and accepted IP-319 implementation notes. IP-327 itself had no native blocker, and T1/T2 are now complete. Linear correctly records IP-327 -> IP-328 -> IP-329 and the cross-epic IP-326 -> IP-328 blocker.
Issue
The CLI cannot currently guarantee one writer per settings ownership class, one deterministic desired state across init/check/update, or non-destructive mixed-outcome reconciliation. Direct command reads/writes and whole-file update behavior can blur user choices, calculated tools, managed version pins, observed repository state, and prior receipt evidence. A user-modified managed field or file can be replaced or removed without a typed conflict, and a manifest rewrite can overstate what actually succeeded.
Proposed Solution Shape
Build two deep CLI-owned feature boundaries.
project-settingsowns decoding, safe upgrade assessment, typed ambiguity/validation failures, ownership-preserving change requests, and persistence. Commands receive validated settings and request only their allowed mutation class.scaffold-stateowns a pure desired-state compiler plus separate observation, reconciliation planning, and application interfaces. The compiler consumes only the neutral context plan, validated settings, baseline/catalog data, and IP-326 harness capability/projection results. The reconciliation planner compares desired state, observed state, and the prior receipt. The applicator executes independent actions and advances receipt entries only for successful actions.
Keep both features in apps/cli: no second app currently consumes their behavior, so moving them into packages/scaffold would create a shared contract prematurely and violate that package's behavior-free boundary. Keep filesystem/process implementations as outer adapters and expose presentation-neutral typed results to command orchestration. Preserve the IP-319 public behavior classifications: managed bytes and public JSON remain byte-locked unless the approved requirement intentionally changes them; desired context/scaffold semantics use semantic equality.
Design-it-twice result:
- Extend
core/tools.tsandupdate/run.tswith more flags. This minimizes file movement but keeps ownership policy implicit and makes command-specific mutation rules part of a broad utility surface. - Add feature-owned settings and scaffold-state interfaces with narrow ports and migrate callers vertically. This concentrates authority, supports deterministic test Layers, and lets filesystem/process adapters change without callers learning reconciliation internals.
Choose option 2. Remove only legacy exports and paths made unused by the migration.
Locked Decision Ledger
| Decision | Status | Reason |
|---|---|---|
| Three settings ownership classes | Locked | User choices, calculated tools, and managed versions have different writers. |
| One shared settings boundary | Locked | Commands must not parse or persist settings independently. |
| Safe upgrades only | Locked | Ambiguous legacy conversion fails without guessing or rewriting. |
| Corrected command responsibilities | Locked | hi init, hi scaffold, hi ensure, hi check, and hi update have accepted distinct roles. |
| One pure desired-state compiler | Locked | Identical semantic inputs must produce identical state across lifecycle commands. |
| Receipt is evidence only | Locked | Desired state cannot derive from a prior application receipt. |
| Field/key-level structured changes | Locked | Unrelated user content must survive managed updates. |
| Mixed outcomes continue safely | Locked | Independent success must not roll back because another action conflicts or fails. |
| IP-327 and IP-326 precede IP-328 | Locked | Linear native blockers and the approved spec agree. |
| IP-329 follows IP-328 | Locked | Reconciliation requires the shared desired state. |
| Child branch and PR base | Locked | team/stefan/ip-318-settings-state targets team/stefan/refactor-cli-architecture; main is forbidden. |
Assumptions and Constraints
- The approved SPEC and completed Q18-Q31 grill decisions are requirements authority; no product question remains open.
- IP-319/IP-330 repository evidence is accepted. Its remaining Linear status sync belongs to that epic's owner and does not change IP-327's native no-blocker state.
- IP-326 must expose its accepted harness capability/projection public seam before T3 starts. This plan consumes that seam and does not implement IP-326.
- The parent Effect v4 architecture branch may change exact APIs before implementation. Executors must use the version then pinned on
team/stefan/refactor-cli-architecture, readopensrc/effect.md, and rerunopensrc path --cwd . effect; this plan does not freeze today's Effect 3.22.0 source shape. - Observation, desired-state compilation, reconciliation planning, application, terminal rendering, and process execution remain separate.
- No task adds speculative conflict-resolution commands. Conflicts are typed and reported for explicit resolution through accepted surfaces.
- No task hand-edits shared skill mirrors or operator-skill state.
- Each behavior-changing task executes one RED -> GREEN vertical slice before the next task.
Branch/Base Intent
- Child branch:
team/stefan/ip-318-settings-state. - Draft child PR base:
team/stefan/refactor-cli-architecture. - Forbidden base:
main. - Merge/deployment state: remain draft, unmerged, and undeployed.
- Native task-order dependencies: IP-327 blocks IP-328; IP-326 blocks IP-328; IP-328 blocks IP-329.
- Evidence: live Linear relations read 2026-07-16; approved SPEC; completed Q18-Q31 grill; accepted IP-319 implementation notes.
- Start rule: IP-327 T1/T2 are green. IP-328 now waits until the accepted #77/IP-326 public capability/projection contract is incorporated into the effective base after final #77 acceptance. IP-329 waits until T4 is green.
- PR topology: IP-327, IP-328, and IP-329 remain task order inside this epic child PR. They are not separate PRs. These dependencies do not authorize merge, deployment, or a PR to
main.
Research and Codebase Findings
apps/cli/src/core/tools.tscurrently owns settings types, normalization, legacy inference, persistence, repository-manager tool derivation, process execution, and tool bootstrap.apps/cli/src/scaffold/stage.ts,apps/cli/src/scaffold/run.ts,apps/cli/src/cli/ensure-command.ts,apps/cli/src/cli/check-command.ts, andapps/cli/src/update/run.tsare direct settings callers.apps/cli/src/update/run.tsmixes manifest parsing, repository observation, desired temporary-tree generation, diffing, conflict policy, application, stale deletion, receipt replacement, and output assembly.- Current comparison is mostly file/hash based, with JSON semantic equality in selected paths. Structured package/config ownership is not modeled per dependency/key.
- Existing public contracts in
apps/cli/src/cli/public-output-contract.test.ts,apps/cli/src/context/public-context-contract.test.ts, andbehavior-contract/cli.jsonare the regression authority from IP-319. packages/scaffoldowns shared behavior-free schemas only. No second consumer justifies moving CLI reconciliation behavior there now.- Notes require fresh init to keep the complete default-pack managed surface, update/check to preserve exact managed bytes, and focused validation when known baseline drift can make broad update checks misleading.
- Current external source resolution points to Effect 3.22.0, but implementation must refresh after the cross-epic v4 pin rather than copy current v3 symbols.
- Linear hierarchy and native blockers are already present. No backlog item or relation mutation is needed from this planning pass.
Planning Method
grilling: reused completed Q18-Q31 decisions; no new question was required.parallel-research: considered for settings, scaffold, and tracker sidecars. The global four-agent set was full with the parent, IP-317 planning, repository audit, and this run, so bounded readonly discovery remained local.swarm-planner: shaped atomic Tn tasks, explicit dependencies, write scopes, and waves.tdd: attached public-seam RED/GREEN targets to every behavior-changing task.codebase-design: selected deep feature boundaries and kept adapters outside pure policy.plan-reviewer: independently passed the execution graph before the latest branch/base topology correction; the targeted readonly re-review of the corrected topology is now complete.
Dependency Graph
IP-327: T1 -> T2 -------------------+
+-> IP-328: T3 -> T4 -> IP-329: T5 -> T6 -> T7 -> T8
IP-326 external public-seam gate ----+Parallel Execution Waves
| Wave | Tasks | Start condition | Write-scope rule |
|---|---|---|---|
| 1 | T1 | Immediately after plan review | Project-settings feature boundary and its focused tests only |
| 2 | T2 | T1 green | Lifecycle callers, command routes, and command public contracts |
| External gate | IP-326 | Owned by IP-317 delivery | No IP-318 writes; provide capability/projection seam and evidence |
| 3 | T3 | T2 green and IP-326 green | Pure desired-state feature and deterministic tests |
| 4 | T4 | T3 green | Shared lifecycle orchestration and observation adapter wiring |
| 5 | T5 | T4 green | Pure reconciliation planner and structured ownership tests |
| 6 | T6 | T5 green | Applicator, typed outcomes, receipt advancement, update integration |
| 7 | T7 | T6 green | Public-seam and temporary-repository manual acceptance |
| 8 | T8 | T7 green | Docs ingest, implementation evidence, tracker handoff, final review |
Implementation is sequential by default because T1-T7 touch overlapping CLI lifecycle seams. Cross-epic IP-326 may proceed independently under its own plan and worker.
Tasks
T1: Establish one ownership-enforcing project-settings boundary
- depends_on: []
- location:
apps/cli/src/features/project-settings/{model.ts,errors.ts,service.ts,live.ts,index.ts,project-settings.test.ts},apps/cli/src/core/tools.ts,apps/cli/src/core/tools.test.ts - description: Introduce the CLI-owned project-settings public interface for read/decode, safe-upgrade assessment, typed missing/invalid/ambiguous failures, required-tool derivation, and mutation requests scoped to user choices, calculated tools, or managed versions. Use an injected filesystem port. Preserve unknown/unowned fields when safe, never return ambiguous legacy state as missing, and remove settings responsibilities from
core/tools.tsonly after the new public seam owns them. - validation: Public feature tests prove current settings, missing settings, safe legacy conversion, ambiguous provider evidence, invalid values, preserved user choices, exact writer permissions, and no write during read/upgrade assessment. A real temporary-filesystem contract proves bytes and preservation through the same interface callers use.
- status: Completed
- log: Added the Effect project-settings service, narrow filesystem port/live adapter, schema decoding and safe-upgrade assessment, typed missing/invalid/ambiguous/access failures, initialization, ownership-scoped writes, unknown-field preservation, and real scoped temporary-filesystem proof. Independent-review repairs keep every writer based on raw JSON, let the user-choice writer resolve ambiguity inside its own ownership class, collect all Git remote repository-manager hints before resolving or rejecting them, and map only
ENOENTreads to missing. Moved settings types and repository-manager tool derivation out ofcore/tools.ts; retained its existing synchronous read/write compatibility path for T2 caller migration. - files edited/created:
apps/cli/src/features/project-settings/{model.ts,errors.ts,service.ts,live.ts,index.ts,project-settings.test.ts},apps/cli/src/core/tools.ts,apps/wiki/content/docs/project/specs/cli/IP-318-govern-project-settings-and-scaffold-state-safely/{PLAN.md,IMPLEMENTATION-NOTES.md} - backlog_item_id: IP-327
- backlog_item_url: https://linear.app/devpunks/issue/IP-327/preserve-project-setting-authority-across-every-lifecycle-command
- relation_mode: native
- assigned_skills: [
autoreview,codebase-design,effect-authoring,effect-backend-structure,effect-best-practices,effect-recoverable-actions,improve-codebase-architecture,parallel-research,quality-types,simplify,swarm-planner,tdd,turborepo] - tdd_status: required
- tdd_target: Reading ambiguous legacy settings returns a typed ambiguity failure and leaves the original bytes unchanged instead of returning
nullor guessing. - red_command:
bun run --cwd apps/cli test -- src/features/project-settings/project-settings.test.ts - expected_red_failure: The public assertion expects a typed
AmbiguousSettingsUpgraderesult naming the conflicting provider evidence and an unchanged settings-file SHA-256, but the current read path returnsnullor an inferred selection instead of that result. - green_command:
bun run --cwd apps/cli test -- src/features/project-settings/project-settings.test.ts src/core/tools.test.ts && bun run --cwd apps/cli check-types - reason_not_testable:
- red_evidence:
bun run --cwd apps/cli test -- src/features/project-settings/project-settings.test.tsexited 1 because the public./indexboundary did not exist. Subsequent atomic REDs proved missing ownership-scopedwrite, missing live adapter, ambiguous repository evidence incorrectly classified, required-tool normalization not assessed as an upgrade, and missing initialization. Independent-review REDs showed managed-version writes persisting inferredassetProviderSlug/requiredTools, multi-remote GitLab plus Bitbucket config resolving to one manager, liveEACCESreads returning missing, and authorized user choices blocked from repairing a missing repository manager. - green_evidence:
bun run --cwd apps/cli test -- src/features/project-settings/project-settings.test.ts src/core/tools.test.tspassed 26 tests in 2 files;bun run --cwd apps/cli check-typesandbun run --cwd apps/cli buildpassed. Targetedoxfmt --checkpassed; targeted Oxlint remains blocked by the pre-existing missing@typescript-eslint/utilsdependency in the installed Effect plugin graph. - codebase_design_notes:
ProjectSettingsis the small public interface. Schema, upgrade, ownership, and preservation policy stay behind it.ProjectSettingsFileSystemis the narrow local-substitutable port with in-memory and real-node adapters proven through the same service. Discriminated initialization/change inputs make field authority explicit.core/tools.tsre-exports the moved model/tool derivation while its synchronous command compatibility path remains until T2 routes callers through the service. - review_mode: cli
- runtime_validation: not_required
- runtime_target: not_applicable
- runtime_evidence: not_applicable
- runtime_cleanup: not_applicable
T2: Route every lifecycle command through settings authority
- depends_on: [T1]
- location:
apps/cli/src/index.ts,apps/cli/src/cli/{scaffold-command.ts,ensure-command.ts,check-command.ts,update-command.ts},apps/cli/src/scaffold/{stage.ts,run.ts,settings-selection.ts},apps/cli/src/update/run.ts,apps/cli/src/cli/{ensure-command.test.ts,check-command.test.ts,public-output-contract.test.ts},apps/cli/src/scaffold/{stage.test.ts,run.test.ts},apps/cli/test-fixtures/public-output/command-modes.json,behavior-contract/cli.json - description: Migrate callers to the T1 interface and implement accepted command ownership. Promote initial adoption to root
hi init; make roothi scaffoldretain former setup responsibility; keephi ensurelimited to user choices plus recalculated tools; makehi checkassess/report upgrades without persisting; and makehi updatepreserve choices while requesting calculated-tool and managed-version changes. Update only intentionally changed command/help/JSON fixtures under the IP-319 classification contract. - validation: Temporary-repository command tests fingerprint settings before/after each command and prove the ownership matrix, including check-only legacy-upgrade reporting, ambiguous typed failure, and no scaffold reconciliation/version change from ensure. Executable help proves
hi initandhi scaffoldat the accepted routes and rejects stalehi scaffold init/setupdiscovery. - status: Complete
- log: Promoted adoption and setup to root
hi initandhi scaffold; composed the live settings authority at the CLI root; routed init, ensure, check, scaffold, and update through explicit settings operations; preserved legacy missing-settings inference inside the authority; and removed stale lifecycle routes from current CLI surfaces and normative repository docs. Setup and update derive exact expected settings bytes through authority writes while preserving choices and unknown fields. Canonical and bundled skill guidance was explicitly excluded by user instruction and remains known stale guidance outside T2. No IP-328 desired-state compiler or reconciliation work was started. - files edited/created:
apps/cli/src/index.ts;apps/cli/src/cli/{scaffold-command.ts,ensure-command.ts,ensure-command.test.ts,check-command.ts,check-command.test.ts,public-output-contract.test.ts,report-command.ts,report-command.test.ts};apps/cli/src/features/project-settings/{service.ts,live.ts};apps/cli/src/scaffold/{stage.ts,stage.test.ts,run.ts,run.test.ts,settings-selection.ts};apps/cli/src/update/{run.ts,run.test.ts};apps/cli/src/{content/stage-scaffold.ts,content/content.test.ts,context/public-context-contract.test.ts,ui/brand.ts,ui/brand.test.ts};apps/cli/test-fixtures/public-output/{command-modes.json,json-serialization.json};apps/cli/README.md;docs/{README.md,runbooks/hi-cli-scaffolding.md,reference/hi-requirements.md,reference/dp-requirements.md};apps/wiki/content/docs/project/specs/cli/IP-318-govern-project-settings-and-scaffold-state-safely/{PLAN.md,IMPLEMENTATION-NOTES.md} - backlog_item_id: IP-327
- backlog_item_url: https://linear.app/devpunks/issue/IP-327/preserve-project-setting-authority-across-every-lifecycle-command
- relation_mode: native
- assigned_skills: [
autoreview,codebase-design,effect-authoring,effect-backend-structure,effect-best-practices,effect-recoverable-actions,improve-codebase-architecture,parallel-research,quality-types,simplify,swarm-planner,tdd,turborepo] - tdd_status: required
- tdd_target:
hi checkagainst safely upgradable legacy settings changes the settings-file fingerprint or fails to report the pending upgrade through its public result. - red_command:
bun run --cwd apps/cli test -- src/cli/check-command.test.ts src/cli/ensure-command.test.ts src/cli/public-output-contract.test.ts src/scaffold/stage.test.ts src/scaffold/run.test.ts - expected_red_failure: Current direct callers lack one ownership boundary, old command routes remain, and the command-level before/after ownership matrix is not satisfied.
- green_command:
bun run --cwd apps/cli build && bun run --cwd apps/cli test -- src/features/project-settings/project-settings.test.ts src/cli/check-command.test.ts src/cli/ensure-command.test.ts src/cli/public-output-contract.test.ts src/cli/report-command.test.ts src/content/content.test.ts src/context/public-context-contract.test.ts src/scaffold/stage.test.ts src/scaffold/run.test.ts src/ui/brand.test.ts src/update/run.test.ts && bun run --cwd apps/cli check-types - reason_not_testable:
- red_evidence: The first vertical slices failed at the public seams: ensure discarded an unknown
userExtensionfield, check returned no safe-upgrade assessment, and executable command discovery lacked rootinit. After setup/update routing, the legacy-backfill tests failed because missing settings inference had not yet moved into the authority; that behavior was then recovered insideProjectSettings. - green_evidence: The complete focused lifecycle command passed 131/131 tests across 11 files. The rebuilt executable exposed root
initandscaffold, public JSON fixtures matched the intentional upgrade field and current CLI copy, setup/update preserved unknown settings fields, check remained byte-preserving, and legacy backfill/conflict behavior passed through the authority. Normative repository docs now use the root routes. Canonical and bundled skill guidance remains an explicit user-excluded stale surface.apps/clibuild and typecheck passed; targeted formatting andgit diff --checkpassed. The targeted readonly rereview is complete. - codebase_design_notes: Commands are transport/orchestration only. They call the T1 public root with explicit mutation intent and render structured results; no raw JSON/file behavior or ownership flags remain in command modules.
- review_mode: cli
- runtime_validation: not_required
- runtime_target: not_applicable
- runtime_evidence: not_applicable
- runtime_cleanup: not_applicable
T3: Compile one deterministic desired managed state
- depends_on: [T2]
- external_dependencies: [IP-326]
- location:
apps/cli/src/features/scaffold-state/{model.ts,errors.ts,compile.ts,index.ts,compile.test.ts},apps/cli/src/context/public-context-contract.test.ts,apps/cli/test-fixtures/public-output/context-outcome.json - description: After IP-326 is green, define the pure desired-state compiler over the neutral context plan, validated project settings, baseline/catalog input, and harness capability/projection results. Model files/projections, dependencies, structured fields/keys, provenance, and known degradation/omission without repository paths leaking into neutral context inputs. Do not read repository, filesystem, environment, process, conflict policy, receipt, or application state.
- validation: Table tests prove identical semantic inputs produce deeply equal state regardless of caller label (
init,check,update), input object identity, or map insertion order. Mutation of repository files, env, process cwd, or prior receipt fixtures cannot affect compilation because none enters the public interface. Supported and degraded IP-326 projections remain explicit and traceable. - status: Complete
- log: Added the pure
compileDesiredScaffoldStatefeature root after the exact absent-module RED. Review repairs now use locale-free ordering, canonicalize projection summaries and derived evidence, encode structured path segments unambiguously, preserve provenance, and reject duplicate managed identities with typed conflicts. The public context fixture explicitly locks compiler-only evidence because the runtime result does not expose the raw typed projection inputs; representative partial/failure projection integration is covered through the compiler public seam. T4 and aggregate runtime migration remain separate follow-on work; no receipt, observation, conflict policy, repository, filesystem, environment, process, or application input entered T3. - files edited/created:
apps/cli/src/features/scaffold-state/{model.ts,errors.ts,compile.ts,index.ts,compile.test.ts},apps/cli/src/context/public-context-contract.test.ts,apps/cli/test-fixtures/public-output/context-outcome.json,apps/wiki/content/docs/project/specs/cli/IP-318-govern-project-settings-and-scaffold-state-safely/{PLAN.md,IMPLEMENTATION-NOTES.md} - backlog_item_id: IP-328
- backlog_item_url: https://linear.app/devpunks/issue/IP-328/derive-one-deterministic-scaffold-plan
- relation_mode: native
- assigned_skills: [
autoreview,codebase-design,effect-authoring,effect-backend-structure,effect-best-practices,effect-recoverable-actions,improve-codebase-architecture,parallel-research,quality-types,simplify,swarm-planner,tdd,turborepo] - tdd_status: required
- tdd_target: The same semantic input fixture compiled for init/check/update yields different or unavailable desired-state results.
- red_command:
bun run --cwd apps/cli test -- src/features/scaffold-state/compile.test.ts src/context/public-context-contract.test.ts - expected_red_failure: No shared pure compiler exists; current lifecycle paths derive expected output separately and rely on repository/temporary-filesystem state.
- green_command:
bun run --cwd apps/cli test -- src/features/scaffold-state/compile.test.ts src/context/public-context-contract.test.ts && bun run --cwd apps/cli check-types - reason_not_testable:
- red_evidence: The original exact RED exited 1 because
./indexwas absent. During review repair, the exact command again exited 1 with 24/26 passing: permuted projection summary arrays changed stored and derived evidence, and structured paths with dotted segments collided. The public context contract remained 18/18 green. - green_evidence: The exact GREEN command passes 26/26 tests across the compiler and public context contract, followed by passing CLI
tsc --noEmit. Focused Oxfmt andgit diff --checkpass for all nine T3 implementation, fixture, and evidence files. - codebase_design_notes:
compileDesiredScaffoldStateis a pure deep-module seam. IP-326 capability results are explicit inputs, not adapter calls. The receipt is absent by type, preventing accidental desired-state authority. - review_mode: cli
- runtime_validation: not_required
- runtime_target: not_applicable
- runtime_evidence: not_applicable
- runtime_cleanup: not_applicable
T4: Make init, check, and update consume the shared compiler through separate stages
- depends_on: [T3]
- location:
apps/cli/src/features/scaffold-state/{observe.ts,lifecycle.ts,lifecycle.test.ts},apps/cli/src/scaffold/{stage.ts,run.ts,stage.test.ts,run.test.ts},apps/cli/src/cli/{check-command.ts,check-command.test.ts},apps/cli/src/update/{run.ts,run.test.ts} - description: Add the repository observation port and lifecycle orchestration that obtains neutral context, validated settings, baseline/catalog, and IP-326 capabilities once, then calls T3. Route init to apply the desired state, check to observe/compare without effects, and update to observe/reconcile. Keep observation and application outside the compiler and return structured presentation-neutral stage results.
- validation: One shared fixture runs all three public lifecycle entrypoints with equivalent semantic inputs. It proves the same desired state, no check writes, init application from missing managed state, update comparison from observed state, and zero receipt/context leakage into compilation.
- status: Complete
- log: Added one presentation-neutral lifecycle boundary over the T3 compiler, a repository observation model, and a desired-output bridge used by init, check, and update. Init applies the compiled desired state, check observes and compares without requiring a writable temporary directory, and update stages from the same desired state before its existing reconciliation path. Review repairs isolate child-process projection-plan state from ambient
DP_HARNESS_PROJECTION_PLAN, clean only run-owned temporary plan directories even when serialization fails, and strictly validate explicit persisted plans and canonical context before projection. Real projection summaries may legitimately reuse one trace identity across different contribution kinds; malformed context, unknown or unsafe operations, mismatched actions, and inconsistent summary traces fail instead of falling back or being accepted. T4 is implemented on convergence draft PR #87; original IP-318 draft PR #80 remains a sibling source PR. - files edited/created:
apps/cli/src/features/scaffold-state/{model.ts,compile.ts,compile.test.ts,index.ts,observe.ts,lifecycle.ts,lifecycle.test.ts,desired-output.ts,desired-output.test.ts},apps/cli/src/scaffold/{output.ts,output.test.ts,stage.ts,stage.test.ts},apps/cli/src/cli/{check-command.ts,check-command.test.ts,public-output-contract.test.ts},apps/cli/src/update/{run.ts,run.test.ts},apps/cli/src/runtime/{scripts.ts,scripts.test.ts},apps/cli/src/data/scripts/{sync-subagents.mjs,sync-subagents.test.ts,harness-projection/adapters/{claude.d.mts,codex.d.mts,cursor.d.mts,cursor.test.ts,opencode.d.mts,opencode.test.ts}},apps/cli/test-fixtures/{public-output/managed-assets.json,single-package/backlog-provider.md},apps/wiki/content/docs/project/specs/cli/IP-318-govern-project-settings-and-scaffold-state-safely/{PLAN.md,IMPLEMENTATION-NOTES.md,PHASE-HANDOFF.md},docs/{README.md,runbooks/hi-cli-scaffolding.md} - backlog_item_id: IP-328
- backlog_item_url: https://linear.app/devpunks/issue/IP-328/derive-one-deterministic-scaffold-plan
- relation_mode: native
- assigned_skills: [
autoreview,codebase-design,effect-authoring,effect-backend-structure,effect-best-practices,effect-recoverable-actions,improve-codebase-architecture,parallel-research,quality-types,simplify,swarm-planner,tdd,turborepo] - tdd_status: required
- tdd_target: Init, check, and update given the same semantic inputs expose unequal desired state or allow check to invoke a write-capable adapter.
- red_command:
bun run --cwd apps/cli test -- src/features/scaffold-state/lifecycle.test.ts src/scaffold/stage.test.ts src/scaffold/run.test.ts src/cli/check-command.test.ts src/update/run.test.ts - expected_red_failure: Existing lifecycle paths independently derive expected trees and check reuses update orchestration rather than a capability-separated compare stage.
- green_command:
bun run --cwd apps/cli test -- src/runtime/scripts.test.ts src/scaffold/output.test.ts src/data/scripts/sync-subagents.test.ts && bun run --cwd apps/cli test -- src/features/scaffold-state/lifecycle.test.ts src/scaffold/stage.test.ts src/scaffold/run.test.ts src/cli/check-command.test.ts src/update/run.test.ts && bun run --cwd apps/cli test -- src/cli/check-command.test.ts src/features/scaffold-state/lifecycle.test.ts src/features/scaffold-state/compile.test.ts src/features/scaffold-state/desired-output.test.ts src/scaffold/output.test.ts src/context/public-context-contract.test.ts src/cli/public-output-contract.test.ts src/data/scripts/harness-projection/contract.test.ts src/data/scripts/sync-subagents.test.ts && bun run --cwd apps/cli check-types && bun run --cwd apps/cli build - reason_not_testable:
- red_evidence: The exact T4 RED failed before the public lifecycle module existed. Review REDs then exposed ambient projection-plan inheritance, leaked run-owned temporary plans on serialization failure, permissive explicit-plan acceptance, malformed-context fallback, and duplicate-kind trace matching that rejected legitimate adapter output.
- green_evidence: The focused runtime/output/projection command passes 48/48 across 3 files; the exact lifecycle command passes 121/121 across 5 files; and the public/projection command passes 122/122 across 9 files. CLI typecheck and build pass.
(git diff --name-only --diff-filter=ACM; git ls-files --others --exclude-standard) | rg '\.(ts|mts|mjs|json)$' | xargs bunx oxfmt --checkpasses all 29 implementation files, andgit diff --checkpasses. Final readonly rereview:PASS — no residual HIGH/MEDIUM findings.It independently ran 66 tests across 4 files and made no edits. - codebase_design_notes: Lifecycle orchestration depends on narrow observation and desired-output seams. Check receives no applicator capability and no temporary-tree dependency. Init and update share the compiler without sharing mutation policy. Explicit projection plans are run-scoped transport artifacts: callers clear ambient state, validate the plan against canonical context, and remove only directories they own.
- review_mode: cli
- runtime_validation: not_required
- runtime_target: not_applicable
- runtime_evidence: not_applicable
- runtime_cleanup: not_applicable
T5: Plan non-destructive reconciliation at file, dependency, field, and key granularity
- depends_on: [T4]
- location:
apps/cli/src/features/scaffold-state/{reconcile.ts,reconcile.test.ts},apps/cli/src/update/{run.ts,run.test.ts} - description: Implement a pure reconciliation planner comparing T3 desired state, T4 observed repository state, and the prior successful receipt. Distinguish unchanged managed output, safe create/update/remove, user-modified managed state, stale ownership, known degradation, and invalid observation. Represent package dependencies and structured config as per-entry actions; preserve unrelated content and convert would-overwrite/remove divergence into typed conflicts.
- validation: Public reconciliation tests cover managed unchanged/change/remove, user modifications, unknown/unrelated fields, dependency version divergence, structured nested keys, unsupported harness omissions, stale receipt entries, and deterministic retry planning. Conflicts in one action do not suppress independent safe actions.
- status: Complete
- log: Added a pure, deterministic reconciliation planner across managed files, dependencies, and structured keys. Update now stages the plan from desired state, observed state, and prior successful file receipts without applying actions or advancing receipts.
- files edited/created:
apps/cli/src/features/scaffold-state/{reconcile.ts,reconcile.test.ts,index.ts,observe.ts,lifecycle.test.ts},apps/cli/src/update/{run.ts,run.test.ts}, this plan, andIMPLEMENTATION-NOTES.md - backlog_item_id: IP-329
- backlog_item_url: https://linear.app/devpunks/issue/IP-329/reconcile-managed-state-without-destroying-user-work
- relation_mode: native
- assigned_skills: [
autoreview,codebase-design,effect-authoring,effect-backend-structure,effect-best-practices,effect-recoverable-actions,improve-codebase-architecture,parallel-research,quality-types,simplify,swarm-planner,tdd,turborepo] - tdd_status: required
- tdd_target: A desired dependency/key update overwrites an observed user-modified managed entry or removes unrelated user content instead of returning a scoped conflict plus independent safe actions.
- red_command:
bun run --cwd apps/cli test -- src/features/scaffold-state/reconcile.test.ts src/update/run.test.ts - expected_red_failure: Current update builds whole-file changes and stale path removals without per-entry ownership/conflict planning.
- green_command:
bun run --cwd apps/cli test -- src/features/scaffold-state/reconcile.test.ts src/update/run.test.ts && bun run --cwd apps/cli check-types - reason_not_testable:
- red_evidence: Vertical REDs first failed for the missing planner, then independently exposed missing safe receipt-backed removal, stale-ownership conflict, dependency/structured-entry planning, invalid observation evidence, degradation/omission evidence, invalid dependency handling, and update staging. Review REDs then proved unsafe primitive/array traversal, mode wildcarding, dropped projection failures, last-write-wins desired overlap, duplicate observed/receipt collapse, permutation-sensitive desired duplicates, rejected exact symlink mode evidence, cross-family ownership overlap, and first-message-wins duplicate invalid observations.
- green_evidence: The exact T5 command passes 78/78 across
reconcile.test.tsandupdate/run.test.ts; CLI typecheck passes. T1/T2 regressions pass 65/65, T3 regressions 94/94, T4 regressions 48/48, lifecycle regressions 59/59,packages/scaffoldpasses 47/47 plus typecheck, and the CLI build bundles 1,056 modules. - codebase_design_notes: The reconciliation planner is pure policy. Desired, observed, and receipt inputs remain distinct types. One shared entry classifier emits deterministic safe actions, unchanged skips, scoped conflicts, invalid desired/observation/receipt failures, cross-family ownership failures, desired projection failures, and explicit degradation/omission evidence. Tuple identities use JSON encoding. Desired duplicates compare the full action payload, including provenance and file kind; exact duplicates deduplicate while unequal duplicates fail only their scoped identity. Whole-file ownership cannot overlap structured entries or package dependencies. Regular-file receipts require exact numeric mode evidence; symlink receipts require exact
nullmode evidence. Duplicate invalid observations produce one fixed failure independently of message order. Structured-file adapters reject traversal through primitives or arrays. Update stages the plan only; T6 retains application and truthful receipt advancement. - review_mode: cli
- runtime_validation: not_required
- runtime_target: not_applicable
- runtime_evidence: not_applicable
- runtime_cleanup: not_applicable
T6: Apply independent actions and advance only truthful receipt state
- depends_on: [T5]
- location:
apps/cli/src/features/scaffold-state/{apply.ts,receipt.ts,apply.test.ts},apps/cli/src/update/{run.ts,run.test.ts},apps/cli/src/core/models.ts,apps/cli/src/cli/{check-command.test.ts,public-output-contract.test.ts},apps/cli/test-fixtures/public-output/json-serialization.json - description: Execute the T5 action plan through injected file/structured-config/process adapters. Return one typed outcome per action: success, skip, degradation, conflict, or failure. Continue independent safe actions after unrelated conflict/failure. Build the next receipt from the prior receipt plus successful actions and known omissions/degradations only; never claim conflicted or failed actions as applied. Persist receipt last through the same result model, without transactional rollback of independent success.
- validation: Failure-injection tests prove mixed success/conflict/failure outcomes, deterministic retry, per-action ordering independent of object identity, preserved unresolved state, successful dependency/key updates, and receipt bytes that include only successful managed state plus truthful omissions. Public update JSON reports every outcome and exits according to the accepted command policy.
- status: Complete
- log: Added deterministic per-action application through injected file, dependency-process, structured-config, and receipt adapters. Update now returns typed mixed outcomes, continues independent safe work, refreshes lockfiles through the detected package manager, and persists a pure-folded truthful receipt last. The command boundary alone selects nonzero exit status for failed/partial write application. Review repairs enforce exact type-aware mode ownership, observe receipt-only dependency/key state, preserve prior on-disk receipts when the injected persistence operation rejects before writing, hash dangling symlinks through
lstat, and retain family correlation without casts. The default direct manifest write is not atomic, so low-level write failure requires receipt inspection or repair. - files edited/created:
apps/cli/src/features/scaffold-state/{apply.ts,apply.test.ts,receipt.ts,reconcile.ts,reconcile.test.ts,index.ts},apps/cli/src/scaffold/{output.ts,output.test.ts},apps/cli/src/update/{run.ts,run.test.ts},apps/cli/src/cli/{update-command.ts,public-output-contract.test.ts}, this plan, andIMPLEMENTATION-NOTES.md - backlog_item_id: IP-329
- backlog_item_url: https://linear.app/devpunks/issue/IP-329/reconcile-managed-state-without-destroying-user-work
- relation_mode: native
- assigned_skills: [
autoreview,codebase-design,effect-authoring,effect-backend-structure,effect-best-practices,effect-recoverable-actions,improve-codebase-architecture,parallel-research,quality-types,simplify,swarm-planner,tdd,turborepo] - tdd_status: required
- tdd_target: When one managed action fails and another succeeds, the current manifest replacement either claims both or prevents the independent success instead of recording truthful per-action outcomes.
- red_command:
bun run --cwd apps/cli test -- src/features/scaffold-state/apply.test.ts src/update/run.test.ts src/cli/public-output-contract.test.ts - expected_red_failure: Current update applies loops directly and replaces the whole manifest without a typed partial-outcome/partial-receipt contract.
- green_command:
bun run --cwd apps/cli test -- src/features/scaffold-state/apply.test.ts src/update/run.test.ts src/cli/check-command.test.ts src/cli/public-output-contract.test.ts && bun run --cwd apps/cli build && bun run --cwd apps/cli check-types - reason_not_testable:
- red_evidence: Initial RED failed because the applicator and receipt fold did not exist and update replaced manifest ownership directly. Review REDs then exposed mode-mismatch authorization, missing receipt-only observation, premature desired receipt staging, aggregate-layer exit mutation, absent lockfile refresh, dangling-symlink empty hashes, and unsafe generic family correlation.
- green_evidence: The exact T6 command passes 97/97 across four files after a 1,058-module build and passing CLI typecheck. Full CLI regression passes 446/446 serially;
packages/scaffoldpasses 47/47 plus typecheck; root behavior passes 4/4; wiki passes 6/6 plus typecheck; andcheck:repo, focused format, and diff checks pass. - codebase_design_notes: Applicator ports own mechanics; the action executor owns deterministic sequencing and result capture; receipt advancement is a pure mapped-family fold over prior receipt and typed outcomes. Dependency actions refresh the detected package-manager lockfile through an injected process boundary. The pre-application manifest retains prior ownership evidence, and receipt persistence is the final action. Failure remains data until the CLI command boundary chooses exit behavior.
- review_mode: cli
- runtime_validation: not_required
- runtime_target: not_applicable
- runtime_evidence: not_applicable
- runtime_cleanup: not_applicable
T7: Pass the IP-318 public-seam and manual lifecycle acceptance gate
- depends_on: [T6]
- location:
apps/cli/src/features/{project-settings,scaffold-state}/*.test.ts,apps/cli/src/cli/public-output-contract.test.ts,apps/cli/src/context/public-context-contract.test.ts,apps/cli/test-fixtures/public-output/**,behavior-contract/cli.json,apps/cli/scripts/assert-dist-commands.mjs - description: Validate the T1-T6 public contracts through a temporary-repository lifecycle spanning init, ensure, check, update preview, mixed-conflict update apply, retry, and final clean check. Verify intentional command/JSON changes, unaffected managed bytes, packaged
hi/hint, user-choice preservation, conflict visibility, independent success, receipt truth, and cleanup without adding production behavior or a new test surface. - validation: Focused CLI suite and packaged build pass. Manual run uses a unique temporary root, records before/after settings, user-edited managed file, structured config, update JSON, receipt, and retry output, then removes only that root and confirms canonical worktree bytes remain unchanged except planned implementation files.
- status: Complete
- log: Completed validation-only acceptance through the shipped packaged executable in one isolated temporary root.
hi initseeded bundled 2.6.2 state;hi ensurechanged GitHub choices to Linear backlog plus GitLab asset/repository choices; read-onlyhi check --jsonclassified the legacy omission asSafeSettingsUpgradewithout changing its settings hash. Update preview and apply reported one modified managed-file conflict and one modified structured-key conflict while completing independent safe removals and a lint-spec update, persisted truthful receipt evidence, retried byte-identically, then reached cleanhi checkandhint update --checkresults after the run-owned conflicts and provider marker were reconciled. Both packaged aliases reported 2.6.2. Canonical HEAD/tree/diff fingerprints were unchanged, and the single temporary root was removed. No production or test files changed. - files edited/created: This plan and
IMPLEMENTATION-NOTES.mdonly - backlog_item_id: IP-318
- backlog_item_url: https://linear.app/devpunks/issue/IP-318/govern-project-settings-and-scaffold-state-safely
- relation_mode: native
- assigned_skills: [
autoreview,codebase-design,effect-authoring,effect-backend-structure,effect-best-practices,effect-recoverable-actions,improve-codebase-architecture,parallel-research,quality-types,simplify,swarm-planner,tdd,turborepo] - tdd_status: not_applicable
- tdd_target: Validation-only acceptance confirms the behavioral RED/GREEN proof already owned by T1-T6 through shipped public seams and packaged output.
- red_command: not_applicable
- expected_red_failure: not_applicable
- green_command:
bun run --cwd apps/cli test && bun run --cwd apps/cli build && bun run --cwd apps/cli check-types && bun test ./scripts/behavior-contract/root-suite.test.ts && git diff --check - reason_not_testable: T7 adds no behavior or test surface; it runs and records the T1-T6 behavioral contracts plus manual acceptance and cleanup evidence.
- red_evidence:
- green_evidence: Packaged build bundled 1,058 modules; CLI typecheck and root behavior 4/4 passed; full CLI passed 446/446 with one worker after the existing projection-temp assertion passed 1/1 in isolation. Two default-concurrency runs each passed 445/446 but exposed the same cross-file temp-directory race, where another worker removed the assertion's pre-existing
hi-projection-plan-*directory.git diff --checkpassed before evidence edits. - codebase_design_notes: Validation consumes only shipped commands and existing public feature roots. It must not add tests, test-only product APIs, or inspect private helper calls.
- review_mode: cli
- runtime_validation: not_required
- runtime_target: not_applicable
- runtime_evidence: Validation root
/tmp/ip318-t7.sbgydH; isolated HOME, TMPDIR, XDG cache/config/data, and global/system Git configuration. Before settings selected GitHub for backlog/assets/repository; after settings selected Linear backlog, GitLab assets/repository, Linear project URL, andglabin required tools. Read-only legacy settings hash remained447fa84d…; the mixed apply returnedpartial, exit 1, andreceiptPersisted: true; retry preserved manifest904f96b4…, hook29aaba45…, and tooling7cd62f60…byte-for-byte with the same two conflicts and zero successes. Receipt retained hook hash6fd24a7c…and structured valuetrue, while successful lint actual/receipt hashes matched at3ccb6881…and removed file ownership disappeared. Final settings and manifest hashes were2a7935dc…and58685ce5…;hiandhintboth reached exit 0 with no changes. - runtime_cleanup: Removed only
/tmp/ip318-t7.sbgydHand confirmed it no longer existed. Canonical HEADa2f65aea…, tree1a3b5680…, and empty working-diff hashe3b0c442…matched before and after the manual run.
T8: Ingest docs, complete evidence, sync tracker context, and pass final review
- depends_on: [T7]
- location:
docs/README.md,docs/runbooks/hi-cli-scaffolding.md,apps/wiki/content/docs/cli/scaffold-lifecycle/{settings-reconfiguration.mdx,scaffold-setup.mdx,scaffold-update.mdx,scaffold-manifest.mdx,meta.json},apps/wiki/content/docs/project/runbooks/hi-cli-scaffolding.md,apps/wiki/content/docs/project/specs/cli/IP-318-govern-project-settings-and-scaffold-state-safely/{PLAN.md,IMPLEMENTATION-NOTES.md,PHASE-HANDOFF.md},apps/wiki/index.md,apps/wiki/log.md, LinearIP-318/IP-327/IP-328/IP-329 - description: Run docs-ingest-phase for changed command/settings/scaffold flows. Use the docs-scoped onboarding and writing primitives to update the root/operator runbook and the exact routed scaffold-lifecycle flow pages before concepts. Record every task's RED/GREEN/manual evidence and deviations, reconcile Linear story/epic status and links without creating task issues, then run findings-first code review plus docs review. Keep the PR draft, based on
team/stefan/refactor-cli-architecture, unmerged, and undeployed. - validation: Documentation matches shipped commands and typed outcomes; implementation notes contain task evidence and manual checklist; native hierarchy/blockers remain correct; focused formatting, wiki-safe validation, final review, and
git diff --checkpass with no blocking finding. - status: Complete
- log: Ran mixed private/internal and public docs ingest. Updated the existing settings, setup, update, manifest, root runbook, and routed runbook pages in flow-before-concept order; recorded T1-T7 proof, every review repair, deviations, manual acceptance, restored stack evidence, and tracker closeout. Public writer artifacts were intentionally skipped because this was a bounded factual correction to existing pages. Independent autoreview and parent rereview passed with no remaining HIGH/MEDIUM finding. Linear IP-328, IP-329, and IP-318 moved to Done with evidence comments; draft PR #87 remained open/draft/unmerged on the required base; the post-push stack dry-run reported
Stack is current. - files edited/created:
docs/{README.md,runbooks/hi-cli-scaffolding.md},apps/wiki/content/docs/cli/scaffold-lifecycle/{settings-reconfiguration.mdx,scaffold-setup.mdx,scaffold-update.mdx,scaffold-manifest.mdx},apps/wiki/content/docs/project/runbooks/hi-cli-scaffolding.md,apps/wiki/content/docs/project/specs/cli/IP-318-govern-project-settings-and-scaffold-state-safely/{PLAN.md,IMPLEMENTATION-NOTES.md,PHASE-HANDOFF.md},apps/wiki/{index.md,log.md} - backlog_item_id: IP-318
- backlog_item_url: https://linear.app/devpunks/issue/IP-318/govern-project-settings-and-scaffold-state-safely
- relation_mode: native
- assigned_skills: [
agent-browser,async-react-patterns,autoreview,codebase-design,design-taste-frontend,docs-ingest-phase,docs-onboarding,frontend-domain-structure,improve-codebase-architecture,next-best-practices,next-cache-components,parallel-research,quality-types,react-doctor,review-phase,simplify,tdd,vercel-composition-patterns,vercel-react-best-practices,writing-beats,writing-fragments,writing-great-skills,writing-shape] - tdd_status: not_applicable
- tdd_target: Durable implementation, manual, review, docs, tracker, and draft-PR evidence is complete and internally consistent.
- red_command: not_applicable
- expected_red_failure: not_applicable
- green_command:
bun run --cwd apps/wiki test && (cd apps/wiki && bunx fumadocs-mdx && bunx next typegen && node --input-type=module -e "await import(new URL('./bin/tsc', import.meta.resolve('@typescript/native/package.json')))" -- tsc --noEmit) && bun run --cwd apps/cli test -- --maxWorkers=1 --minWorkers=1 --no-file-parallelism && bun run --cwd apps/cli build && bun run --cwd apps/cli check-types && bun test ./scripts/behavior-contract/root-suite.test.ts && bunx oxfmt --check docs/README.md docs/runbooks/hi-cli-scaffolding.md apps/wiki/content/docs/cli/scaffold-lifecycle/settings-reconfiguration.mdx apps/wiki/content/docs/cli/scaffold-lifecycle/scaffold-setup.mdx apps/wiki/content/docs/cli/scaffold-lifecycle/scaffold-update.mdx apps/wiki/content/docs/cli/scaffold-lifecycle/scaffold-manifest.mdx apps/wiki/content/docs/cli/scaffold-lifecycle/meta.json apps/wiki/content/docs/project/runbooks/hi-cli-scaffolding.md apps/wiki/content/docs/project/specs/cli/IP-318-govern-project-settings-and-scaffold-state-safely/PLAN.md apps/wiki/content/docs/project/specs/cli/IP-318-govern-project-settings-and-scaffold-state-safely/IMPLEMENTATION-NOTES.md apps/wiki/content/docs/project/specs/cli/IP-318-govern-project-settings-and-scaffold-state-safely/PHASE-HANDOFF.md apps/wiki/index.md apps/wiki/log.md && git diff --check -- docs/README.md docs/runbooks/hi-cli-scaffolding.md apps/wiki/content/docs/cli/scaffold-lifecycle/settings-reconfiguration.mdx apps/wiki/content/docs/cli/scaffold-lifecycle/scaffold-setup.mdx apps/wiki/content/docs/cli/scaffold-lifecycle/scaffold-update.mdx apps/wiki/content/docs/cli/scaffold-lifecycle/scaffold-manifest.mdx apps/wiki/content/docs/cli/scaffold-lifecycle/meta.json apps/wiki/content/docs/project/runbooks/hi-cli-scaffolding.md apps/wiki/content/docs/project/specs/cli/IP-318-govern-project-settings-and-scaffold-state-safely/PLAN.md apps/wiki/content/docs/project/specs/cli/IP-318-govern-project-settings-and-scaffold-state-safely/IMPLEMENTATION-NOTES.md apps/wiki/content/docs/project/specs/cli/IP-318-govern-project-settings-and-scaffold-state-safely/PHASE-HANDOFF.md apps/wiki/index.md apps/wiki/log.md - reason_not_testable: Documentation, evidence, review, and tracker closeout do not introduce runtime behavior.
- red_evidence:
- green_evidence: Wiki tests pass 6/6; direct Fumadocs generation, Next route generation, and native TypeScript validation pass. Full CLI passes 446/446 with one worker; build bundles 1,058 modules; CLI typecheck and root behavior 4/4 pass. Exact targeted Oxfmt and scoped diff checks pass. The non-mutating wiki sync preflight reports existing project-owned routing drift that would remove canonical routed specs, so the mutating wrapper was intentionally skipped. Final autoreview and parent rereview pass with no remaining HIGH/MEDIUM finding. Linear closeout comments: IP-328
0697ea59-892c-42c9-b303-17ad87a48d99, IP-329033824f7-107c-4239-a5c6-a236bc8bd751, and IP-31839c3facb-2696-4ac8-8721-ce2beb5c0a8a. - codebase_design_notes: not_applicable
- review_mode: cli
- runtime_validation: not_required
- runtime_target: not_applicable
- runtime_evidence: not_applicable
- runtime_cleanup: not_applicable
Testing Strategy
- Use vertical tracer bullets: one public behavior RED, minimal GREEN, then the next task.
- Test settings through the feature root and command before/after bytes, not private decoders.
- Test desired-state semantics with pure values and explicit IP-326 capability results.
- Test observation/application ports with deterministic in-memory adapters plus focused real temporary-filesystem contracts.
- Assert structured dependency/config behavior at key granularity and preserve unrelated bytes/entries.
- Inject one action conflict and one failure while proving independent success and truthful receipt advancement.
- Preserve IP-319 classification: exact bytes for managed assets/public JSON, semantic equality for context/desired state, intentional assertions only for approved command changes.
- Keep all mutable fixtures under unique temporary roots; fingerprint canonical repo inputs and clean only run-owned resources.
- Prefer focused CLI tests and typecheck while developing. Use the behavior root guard and packaged build at T7/T8.
Validation Gates
- Plan review: an independent plan-reviewer must report no blocker before T1 starts.
- IP-327 gate: T1-T2 prove typed safe upgrades, exact field ownership, accepted command routes, and read-only check.
- Cross-epic gate: IP-326 public capability/projection evidence must be green before T3.
- IP-328 gate: T3-T4 prove one pure compiler and distinct init/check/update stages.
- IP-329 policy gate: T5 proves field/key-level safe/conflict actions without effects.
- IP-329 application gate: T6 proves typed mixed outcomes and partial truthful receipt advancement.
- Manual/public gate: T7 proves the full temporary-repository lifecycle, packaged commands, deterministic retry, and cleanup.
- Closeout gate: T8 completes docs ingest, evidence, tracker sync, findings-first review, and draft PR/base verification.
Manual Review Checklist
| Area | Action | Expected result |
|---|---|---|
| Settings authority | Init a unique temporary repo, then run ensure with changed provider/backlog choices. | Choices and calculated tools change; managed CLI/baseline versions remain unchanged by ensure. |
| Read-only check | Place a safely upgradable legacy settings file, fingerprint it, and run hi check --json. | Upgrade is reported; bytes and mtime remain unchanged. |
| Ambiguous migration | Place conflicting legacy provider evidence and run a lifecycle command. | Typed actionable failure; no guessed/discarded/re-written values. |
| Shared desired state | Capture normalized desired state from init/check/update with identical semantic inputs. | Semantically identical state and ordering from all callers. |
| User modification | Edit one managed file and one managed structured key, then preview/apply update. | Both divergent items remain intact and appear as scoped conflicts. |
| Independent success | Leave another managed item safely updateable in the same run. | Safe item applies despite conflicts; every action has a typed outcome. |
| Receipt truth | Inspect receipt after mixed update. | Successful state and known omissions/degradations appear; conflicts/failures are not claimed applied. |
| Retry | Resolve one conflict and rerun update. | Only unresolved work is planned; previously successful state stays stable. |
| Cleanup | Remove the unique temporary root and compare worktree fingerprint. | No process/temp/global state remains; only planned source/docs changes differ. |
| PR base | Inspect draft PR metadata. | Base is team/stefan/refactor-cli-architecture, never main; PR remains draft/unmerged/undeployed. |
Risks and Mitigations
- Cross-epic contracts may land with different exact names: T3 waits for IP-326 and imports only its deliberate public root; do not guess internal paths now.
- Effect v4 APIs may differ from current source: refresh official/source guidance after the parent branch pin and keep the plan at interface semantics.
- Command renames can break scripts/docs: classify as approved intentional behavior, update executable help/fixtures/runbooks together, and reject stale discovery paths.
- Exact managed-byte fixtures can freeze incidental content: keep exactness only where IP-319 classified bytes as public; use semantic equality for desired state.
- Broad
hi update --checkcan fail on unrelated baseline drift: inspect focused changed paths and use task-owned fixtures before treating broad exit 1 as task failure. - Mixed writes can create false receipts: persist receipt last from captured outcomes, and failure-inject every action family.
- Structured merging can silently widen ownership: model explicit dependency/key identities and assert unrelated content survives.
- Sequential tasks overlap lifecycle files: one implementation worker at a time; parent validates between tasks.
- Linear status was stale during delivery: T8 reconciled accepted evidence after repository, review, PR, and stack proof completed.
Unresolved Questions
None. Product decisions are closed. Exact symbol names follow the parent IP-320/IP-326 implementations at execution time and are controlled implementation tuning, not open requirements.
Backlog Sync
- Read live IP-318/IP-327/IP-328/IP-329 and cross-epic IP-326 descriptions, comments, hierarchy, and relations on 2026-07-16.
- Existing epic/story hierarchy is native and correct.
- Existing blocker chain is native and correct: IP-327 -> IP-328 -> IP-329, plus IP-326 -> IP-328.
- No new issue per Tn task is allowed or needed.
- No provider mutation occurred during plan creation. T8 reconciled IP-328 at
2026-07-20T01:02:45Z, IP-329 at2026-07-20T01:02:51Z, and IP-318 at2026-07-20T01:02:52Zafter implementation evidence existed.
Planned Review and Docs Ingest
- Before implementation: independent
plan-reviewerchecks dependency ordering, the external IP-326 gate, unsafe write overlap, public-seam RED targets, exact commands, scoped skills, manual cleanup, and PR base intent. - During implementation: parent validates every worker task before advancing the dependency graph.
- After T7:
review-phaseperforms findings-first standards/spec review; blockers return to the owning task. - T8 runs private/internal
docs-ingest-phase, writes flow documentation before concepts, updates source bookkeeping and runbooks, and records the no-UI-evidence rationale. - No browser/UI gate is required: this epic changes CLI/domain/filesystem behavior only.