Harness Intelligence Wiki
SpecsCLIIP-324 V4-Only Repository Cutover

Implementation Notes: V4-Only Repository Cutover

Implementation Notes: V4-Only Repository Cutover

Execution Mode

Parallel epic delivery with disjoint worker ownership, coordinated on the convergence branch. T8 used one sequential implementation worker and one root-owned repeat validator; the validator itself kept complete runs sequential and used concurrency only for the separate package/consumer isolation stress.

Current Checkpoint

The completed implementation is 83d0311aadd7cc93a5f5393902fb0d97645eaefb on team/stefan/m7-m9-effect-v4-convergence in draft PR #87. T3–T9 are green. The exact root behavior contract passed 15/15 tasks, the CLI passed 743/743 tests, and GitHub behavior-contract run 29849467229, job 88698354582, passed in 5m27s. The documentation closeout head 865f2a4c7679327f8187193be333f5c92dab85ce also passed GitHub behavior-contract run 29850340492, job 88701316002, in 5m06s.

Live Linear verification returned IP-317 through IP-346 as exactly 30/30 Done after closing IP-345, then IP-346, then IP-324. The post-push stack preview preserved the exact fan-out and required a sync only for #87's generated stack block. stack sync applied that metadata update; the following status and dry-run reported the exact fan-out current. PR #87 remains draft, open, unmerged, and undeployed. No merge, release, or deployment is claimed. The documentation-only SHAs do not replace the implementation SHA above.

Historical T1/T2 task detail remains on PR #83/source notes. It is retained as provenance, not as worktree/rebase guidance for this branch.

T3–T6 Evidence

GateResultEvidence
Static Effect v4 migrationPassbun run validate:effect-v4 passed 94/94 tests with 1,434 assertions, twice after validator repairs. It covers dependency manifests, domain boundaries, typed failures, configuration boundaries, and migration closeout.
CLI full behaviorPassCLI typecheck and build passed; the final full CLI suite passed 67 files and 743 tests.
Root testPassEffect 94/94, root behavior suite 4/4, and the uncached Turbo test/browser/runtime-product wave 15/15 passed; root bun run test exited 0.
Root static checkPassbun run check passed 12/12 participating workspaces. Test-source Oxlint findings were reduced from 1,717 to zero; touched production lint was zero.
Build surfacePassDirect non-mutating wiki next build generated 912 pages. The non-wiki root Turbo build passed 4/4 tasks with NEXT_PUBLIC_SERVER_URL=https://harness-api.localhost. Together these cover the complete root build surface without invoking wiki sync.
Packaged CLIPassbun run validate:packaged-product built and packed the actual npm package, installed its tarball in isolation, exercised both hi and hint seams, verified package residue, and passed CLI public-output/renderer 60/60.
Package authorityPassapps/cli/package.json has only react-devtools-core in runtime dependencies. effect, @effect/platform-bun, internal workspaces, types, test, lint, and build tools remain devDependencies; API retains its required Effect runtime dependencies.
Packaged APIPassThe packaged runtime starts from dist/index.mjs, proves exact child-process provenance, verifies baseline authority and fail-closed disagreement behavior, and cleans owned runtime state.
Renderer/catalog/operator/browserPassCLI renderer/catalog checks passed; backoffice Playwright passed 8/8; wiki behavior passed 6/6; relevant typechecks passed.
ResiduePassTarball/install, API process, renderer/catalog, browser, wiki, and temporary state checks reported no run-owned residue.
Direct wiki validationPassfumadocs-mdx, next typegen, native TypeScript --noEmit, and direct next build passed without the mutating sync wrapper.

Validator Repairs

The aggregate validator initially exposed six stale contract assumptions. The repair kept product behavior unchanged and aligned tests with the converged boundaries:

  • CLI scaffold orchestration imports pack selection through the public feature root.
  • The dependency contract preserves CLI npm authority: only react-devtools-core ships as a runtime dependency; Effect/internal workspaces stay build-time development dependencies.
  • Typed-failure contracts point at the split context-compilation, scaffold-application, unknown-pack, report configuration/response, and API provider-unavailable declarations.
  • Migration-closeout historical HEAD bytes and hashes were restored for 15 immutable managed/public/auth authorities. Path-exact lint and format exclusions prevent mechanical rewrites without redefining authority; the final CLI build regenerated the same historical bundled identity.

The repaired Effect validator passed 94/94 twice. Root behavior and packaged-product contracts also lock both root script entries: validate:effect-v4 and validate:packaged-product.

T7 Installed Consumer Evidence

bun run validate:consumer-repositories now builds and packs the CLI once, installs the actual tarball offline with its exact local production dependency, and drives the installed hi and hint binaries through three isolated consumer repositories. Fresh init recorded 199 managed files and verified 191 non-project-authored hashes. Repeated scaffold reached a fixed point with 235 managed files and 228 verified hashes. The existing-repository scenario detected a modified managed script, preserved its user bytes, completed independent safe actions, converged on retry, returned no-op on the repeated update, and passed a final clean check while preserving an unmanaged file.

The npm tarball contains the NestJS bundled .gitignore with SHA-256 d1a3b15bb12948cfbd82acdd54889efc5d1263809550cb4d379863bbc1cc2f82. npm installation physically renames it to .npmignore; the bundled loader verifies a manifest-scoped alias, computes the immutable baseline digest under the logical .gitignore identity, and consumer materialization restores .gitignore with byte equality and no .npmignore residue. Ambiguous, mismatched, missing, and unlisted aliases fail closed. The bundled baseline identity remains 8243214a805c3107cf52fcb6623a11219eb6e9c68add89d286c9a09cc926584a.

Focused action-aware reconciliation proves a safe file removal succeeds while an independent conflict remains byte-identical. The full update plus alias suites passed 75/75; CLI build, typecheck, lint/format, package-surface assertion, the 94/94 Effect-v4 gate, consumer contract 3/3, and packaged-product consumer integration 4/4 passed. The final consumer validator removed its owned temporary root.

Review repair removed both shared apps/cli/dist mutation seams. Each consumer-validator invocation copies CLI source into its own temporary build workspace, builds there, then copies the declared npm surface into a separate owned package root and adds the nested .npmignore only there. Two simultaneous full validators passed with identical package SHA-256 values, removed distinct owned roots, and left the shared dist digest unchanged at 945cb4ebd84ac97754427d7fd384e19abbc5f76a80792b59a3f8c03b6bec64c1. Two simultaneous package-surface checks also passed with no shared .npmignore before or after either run. Interactive init uses Node child-process streams instead of /usr/bin/expect, accepts explicit success and partial states only when the exit code agrees, and the update scenario requires a scaffold-conflict-preserved degradation for the exact modified path. The focused validator contract passed 8/8, the canonical update plus alias suites passed 75/75, the installed consumer report passed all three scenarios and removed its owned root, and the packaged-product integration passed 4/4.

T8 Repeatability and Cleanup Evidence

bun run validate:cutover-repeat exited 0 after one earlier invocation of the complete T8 matrix. Each of two sequential complete runs executed root test, root check, direct wiki generation and build, the filtered non-wiki Turbo build, validate:packaged-product, and a caller-owned validate:consumer-repositories lifecycle. That evidence is superseded by the repairs below.

The replacement matrix exited 0 at HEAD 5e1637f939818e43b69a8a5262c3de012e54518c. Its source authority was dirty-patch SHA-256 633b1614c0081cd52d7dda086cb241c2fd62f279c2b9d4fe26914e7695faf806, covering 56,308 tracked patch bytes and 6 untracked paths. The two complete normalized evidence digests matched at 739c91c0ae08234d6cd7611ffbfda8eed19aa14b1f4355b349d12a546162fe0d; the two concurrent stress digests matched at dbbed7e6af71a7a1bdf63b9444045743503343e5f86770a4f15cce1c78fd7bac.

All packaged-product, consumer, and stress lifecycles observed archive SHA-256 cc49bfd06a303ee9f6cf4c5a1a991404c1641de0567c3df77b7032f381d1361. The archive is observational. Authoritative installed package identity was @punks/cli@2.6.2 with 664 canonical entries and installed-tree SHA-256 991c96fbcf2e7a0d2b26733704e53944783523e61c47b3fa2319eba48f7f2cb9. Bundled .gitignore remained d1a3b15bb12948cfbd82acdd54889efc5d1263809550cb4d379863bbc1cc2f82.

The first replacement attempt failed closed because the live and isolated CLI builds embedded different root-relative module comments in dist/index.js; archive and canonical installed-tree digests both differed. --minify-whitespace removes only that generated path-comment variance. Narrow live/isolated builds then matched byte-for-byte, and independent packaged/consumer installs matched at 664 entries with canonical SHA-256 d8363a16249095ad6ded5560a65889f409d0fa66d252974442e586ce73cd4720. Raw archive SHA remains observational evidence; name, version, and installed path/type/mode/content authority are the cross-validator contract.

A later replacement attempt failed at the second complete run's wiki typecheck because the old fumadocs-mdx then next typegen order left .source/server.ts empty. The corrected direct order is next typegen, fumadocs-mdx, explicit generated-source assertion, native TypeScript with --noEmit --incremental false, then next build.

That correction exposed a separate upstream generation race. Ten unpatched normal-threadpool runs produced ten distinct raw server.ts and browser.ts hashes even though their content-path sets were identical; Tinyglobby returns asynchronous crawl order and Fumadocs mutates shared eager import IDs from concurrent collection generation. The repository-owned Bun patch for fumadocs-mdx@14.3.2 sorts every resolved path list and serializes eager mutation in call order. Package and lock authority both record the patch. Ten patched normal-threadpool runs produced one hash per required module: browser 4500be1eae944ceb850e6a58c9ed4bf013972383494c539c309ef22e47b7bd41, dynamic ff15e542ede91e2735f07e523795be409b450f814c0163c59ed1f6baee4da8cf, server 571af1cdecc307df69e579a5e840fc1d448db41e151c3fa79ecbb70d6777d0b9, and source config 11485a42ad492ef5bcf3e773b54248e53f5a530d7451922c11f5c20a04028d5f.

Two exact corrected wiki sequences then passed generation, native non-incremental typecheck, and 912-page Next build. Both recorded the same sorted four-entry raw generated-source digest, fd36d0636ae488eaa5acb37823cf0f4bf6846e0f16452d387312a847be2fe422, while tracked wiki content authority remained unchanged.

The validator recorded every directly spawned PID and its exit state; all exited 0 without timeout. Each consumer report exposed its exact pre-cleanup owned path, inode-revalidated removal action, and empty post-cleanup path set. Complete runs and concurrent stress runs independently reported empty post-cleanup paths, processes, and services. The fifth lifecycle acquired its owned root, raised the exact expected CutoverRepeatInjectedFailure tag, awaited removal, and reported the same empty post-cleanup state. The outer session refused broad recursive recovery, removed only an empty identity-revalidated session root, and ended with no owned residue.

The matrix recorded root-test semantic digest 049a9ddf178a634891ac197672c16d89afde34bda4f7f233325349095a863cfa: Effect-v4 94/94 with 1,434 assertions, focused repeat/consumer/root coverage 31/31 with 214 assertions, Turbo 15/15, CLI 742, API 101, and backoffice browser 8/8. Root static checks were 12/12 with digest ac831b387d0c053847a0452ef4e528864774942431532c135d7ae3fb72d2da3b. The four raw generated modules matched at aggregate fd36d0636ae488eaa5acb37823cf0f4bf6846e0f16452d387312a847be2fe422; both wiki builds produced 912 pages and 5 routes. Every complete run spawned 10 bounded commands and all exited 0. Complete, stress, injected-failure, and outer-session post-cleanup path, process, and service sets were empty. Adversarial coverage includes concurrent failure aggregation, source-authority boundary checks, leaf-only normalization, atomic quarantine identity checks, and descendant process-group cleanup.

Final Linux CI and Machine-Output Repairs

The first pushed checkpoints exposed clean-Linux behavior that local installed tools and warm services did not reproduce. The bounded repairs preserved product semantics and strengthened the final gate:

  • 4f889652 requires both acquired device/inode identity and an exact random marker before removing a quarantined run-owned directory. This prevents copied provenance or Linux inode reuse from authorizing deletion.
  • 29e95047 captures the exact Linux Portless shell leader so descendant cleanup and readiness observe the process that owns the lifecycle.
  • 4e65bb07 warms the canonical /login?next=%2F route after API/app readiness; browser startup no longer assumes a listening socket means the first protected route is ready.
  • 02b3bd11 gives the cold auth lifecycle 60 seconds while preserving its two real Bun harness lifecycles and finalizers.
  • 44495407 serializes the root Turbo behavior contract at concurrency 1, removing cross-task Portless/browser socket churn while preserving all 15 task commands and dependencies.
  • 83d0311a keeps JSON stdout as one document by suppressing external required-tool bootstrap streams in JSON scaffold, update, and tools-ensure modes. Human/default modes continue inheriting install progress. The clean-PATH regression omits stack, supplies a fake Bun banner, and still parses the exact structured failure document.

The historical T8 matrix recorded CLI 742 before the final regression was added. Final implementation authority is CLI 743/743 plus the authoritative GitHub run below.

Final Authoritative Gate

  • Implementation SHA: 83d0311aadd7cc93a5f5393902fb0d97645eaefb.
  • Local exact root gate: 15/15 tasks green.
  • Local full CLI suite: 67 files, 743/743 tests green.
  • Independent final CLI review: no accepted or actionable findings; focused stream-policy coverage passed 194/194, CLI typecheck/check passed, and git diff --check was clean before commit.
  • GitHub behavior-contract: run 29849467229, job 88698354582, green in 5m27s.
  • Documentation-head behavior-contract: run 29850340492, job 88701316002, green in 5m06s at 865f2a4c7679327f8187193be333f5c92dab85ce.
  • Linear: IP-317 through IP-346 refetched live as 30/30 Done.
  • Stack: PR #76 parent; PRs #77–#83 and #87 sibling children based on team/stefan/refactor-cli-architecture; the required sync changed only #87's generated stack block, and the following status/dry-run reported the exact fan-out current.
  • Publication boundary: PR #87 draft, open, unmerged, and undeployed; no release or deployment.

Wiki Sync Recovery Evidence

An invalid wrapper-level typecheck invoked the project-owned wiki sync script. Validation stopped, and all 182 affected paths were restored from the repository snapshot using path-exact patches. The recovery authority was /var/folders/y8/fw7tz9gn7yx645tf162zwlnr0000gp/T/tmp.m4QpiapOvw plus the captured run/session provenance. The 13 files already dirty before that invocation were reconstructed and independently verified against the pre-run SHA-256 snapshot: 13/13 matched, with no missing or extra pre-existing wiki changes.

Pre-existing wiki sourceSHA-256 after recovery
IP-317/IMPLEMENTATION-NOTES.md97e52bb5afcab4c1157a389b5d4ce602de3ea47f45f5b0b7dd1d351c1001c782
IP-318/IMPLEMENTATION-NOTES.md81075265cf5e0bddad419a8cdc3f5814c4a005ff942d77d430d36267adb6d1cc
issue-67/IMPLEMENTATION-NOTES.md3471f60a8577727ad11063006edd651b27be1090f13fa67c19a84ae531cde6bc
issue-67/PLAN.mdf3d841cb2a44ae78770acfebef20defec71c540ba952dae3426772e2e3932af5
issue-67/SPEC.md8adc5d7d7862b6ad087daefc4ec2c1f9f4e6c900c215a229658595eef386d860
issue-68/IMPLEMENTATION-NOTES.md4cd035f5ac4eeb444e9d7951d9d0f1a6a6f5eb6f729262c482ea79e152b40fcf
issue-68/PLAN.md11bfea0a4da55cb63ee2322f685cc3ca344bdefcb4d9c1a9229b63566593e3e1
issue-68/SPEC.mdf048b74ece072c0c261d67ad270606738c2b6c74a417dc10c7e87779b56f9159
issue-69/IMPLEMENTATION-NOTES.mddc78874669c1e08e234170e005afc310a4f970d53954973dc706452555734122
issue-69/PLAN.md6d545368932fdfb3a97a77581891dfb86f0f54671f1c76d5f9aacb1008f27398
settings-reconfiguration/IMPLEMENTATION-NOTES.md196f67ba87d749376529aa97dee49534831aecccc6b2ae5bd888b139e9d13acd
settings-reconfiguration/PLAN.md6002fb66c5868d439a3cdfce24376f1cd0390973c649043035b55f0dcfc5d66a
settings-reconfiguration/SPEC.md2d1203760f14b101ad8b1a25963fa2917f5046bc4c9b674ed89765b3c1ebea46

The safe direct wiki gates passed again after exact recovery. The sync wrapper is not part of this checkpoint's validation commands.

Stack and Publication Boundary

The final live topology has PR #76 as the stack parent and PRs #77–#83 plus #87 as sibling children based on team/stefan/refactor-cli-architecture. PR #87 does not contain or linearize #77–#83. The post-push previews preserved this fan-out and required stack sync only to update #87's generated stack block. No branch, base, or head SHA changed. The following stack status and stack sync --dry-run returned the exact fan-out and current state.

At the final stack checkpoint, each local ref matched its origin ref and live PR head. The live PR bases matched the recorded fan-out:

PRBranchLocal SHAOrigin SHALive PR head SHALive PR base
#76team/stefan/refactor-cli-architecture71af6c8249ea05ec46519471bc56da772f80d06171af6c8249ea05ec46519471bc56da772f80d06171af6c8249ea05ec46519471bc56da772f80d061main
#77team/stefan/ip-317-context-planfacf1ba10a1caec39e1602dfb23e28c0e1669a03facf1ba10a1caec39e1602dfb23e28c0e1669a03facf1ba10a1caec39e1602dfb23e28c0e1669a03team/stefan/refactor-cli-architecture
#78team/stefan/ip-322-operator-skill7b14739996d5b297088f0ff102bebb6e3c8f7eb77b14739996d5b297088f0ff102bebb6e3c8f7eb77b14739996d5b297088f0ff102bebb6e3c8f7eb7team/stefan/refactor-cli-architecture
#79team/stefan/ip-320-effect-v4-boundaries5c96dfd109a60285dca77ceb8093367e23e333565c96dfd109a60285dca77ceb8093367e23e333565c96dfd109a60285dca77ceb8093367e23e33356team/stefan/refactor-cli-architecture
#80team/stefan/ip-318-settings-stateb302005fb55791b6225a946e54931ab6638a33ccb302005fb55791b6225a946e54931ab6638a33ccb302005fb55791b6225a946e54931ab6638a33ccteam/stefan/refactor-cli-architecture
#81team/stefan/ip-321-cli-presentationfc30dd72954f080c66c85cd892a66a964d950169fc30dd72954f080c66c85cd892a66a964d950169fc30dd72954f080c66c85cd892a66a964d950169team/stefan/refactor-cli-architecture
#82team/stefan/ip-323-baseline-authorityf24dad1893e14a856d6aef7b86e438aabad83c8bf24dad1893e14a856d6aef7b86e438aabad83c8bf24dad1893e14a856d6aef7b86e438aabad83c8bteam/stefan/refactor-cli-architecture
#83team/stefan/ip-324-v4-cutoverb487fd83dbbf296132310be3bb1dab0041fc6c40b487fd83dbbf296132310be3bb1dab0041fc6c40b487fd83dbbf296132310be3bb1dab0041fc6c40team/stefan/refactor-cli-architecture
#87team/stefan/m7-m9-effect-v4-convergence865f2a4c7679327f8187193be333f5c92dab85ce865f2a4c7679327f8187193be333f5c92dab85ce865f2a4c7679327f8187193be333f5c92dab85ceteam/stefan/refactor-cli-architecture

PR #87 is draft, open, and unmerged. Merge, release, deployment, retargeting, force-push, and any future convergence PR remain outside this delivery closeout.

Manual Review Checklist

AreaCheckHow to performExpected result
Effect migrationRun the static migration gate.Run bun run validate:effect-v4.All 94 tests pass; dependency, boundary, typed-failure, config, and closeout contracts stay green.
Packaged CLIVerify the actual npm tarball seam.Run bun run validate:packaged-product and inspect the package-surface step.Isolated tarball install exercises both hi and hint; renderer/catalog and residue checks pass.
Consumer reposVerify installed CLI transitions.Run bun run validate:consumer-repositories and inspect its JSON report.Fresh init, repeated scaffold, conflict-preserving update, final clean check, exact alias bytes, and owned-root cleanup pass.
RepeatabilityRepeat the complete cutover gate.Run bun run validate:cutover-repeat and inspect its JSON report.Two full runs and two stress runs match within their own comparison domains; the injected failure and every owned lifecycle end with empty residue.
Packaged APIVerify provenance and fail-closed authority.Inspect the packaged runtime-product output.API starts from dist/index.mjs, records exact process provenance, rejects authority disagreement, and cleans owned state.
Operator surfacesVerify renderer and browser behavior.Inspect CLI renderer/catalog, backoffice Playwright, and wiki results.CLI is 60/60, backoffice is 8/8, wiki is 6/6, and relevant typechecks pass.
RepositoryRun aggregate local gates.Run root test/check and the direct build decomposition documented above.Tests, 12/12 checks, and every build surface pass without wiki sync.
Wiki safetyVerify routed source directly.Run Fumadocs generation, Next typegen, native TypeScript, and direct Next build.All gates pass; no project-source projection or sync wrapper runs.
RecoveryCompare the pre-run wiki snapshot.Recompute the 13 recorded SHA-256 values and inspect the affected-path set.13/13 pre-existing files match; intentional IP-324 docs are the only additions to that snapshot.
Closeout boundaryVerify the live delivery boundary.Inspect PR #87, Linear IP-317–IP-346, and the recorded post-sync stack dry-run.PR #87 is draft/open/unmerged, Linear is 30/30 Done, and the exact sibling fan-out is current after the metadata-only sync.

Remaining Work

  • No delivery implementation remains. Maintainer review of the draft whole-delivery PR is the explicit boundary. Merge, release, and deployment are separate decisions.

On this page