CLI Settings Reconfiguration Plan
CLI Settings Reconfiguration Plan
Initial Situation
hi scaffold init embeds backlog and repository prompts in apps/cli/src/scaffold/stage.ts, derives assetProviderSlug from the backlog provider, and has no backlog project URL. .devpunks/settings.json is normalized through apps/cli/src/core/tools.ts. The bundled write-backlog skill does not consult settings before provider materialization. hi update was run first and reported the current stable baseline with zero managed or stale files.
Solution Shape
Create one deep settings-selection module whose small interface accepts prompt/default dependencies and returns the four operator-owned settings. Both init and a top-level hi ensure command call this seam. Keep wiki selection init-only. Extend settings normalization with optional legacy-compatible backlogProjectUrl, then require a valid trimmed HTTP(S) URL only at the interactive write boundary. Update the upstream shared write-backlog source, push it, synchronize it into Harness, and prove a scaffolded consumer receives URL-aware guidance.
Resolved Decision Ledger
- Command: top-level
hi ensure; distinguish it fromhi tools ensure. - Settings key:
backlogProjectUrl. - Legacy reads: URL remains optional so old settings stay readable.
- Interactive writes: URL is required and validated as absolute HTTP(S).
- Missing settings: fail with
hi scaffold initguidance; do not bootstrap implicitly. - Existing settings: current values become defaults and accepting them is idempotent.
- Asset provider: independently selectable; no longer derived from backlog.
- Tool reconciliation: identifiers in
repositoryManagerToolsare manager-owned. Remove every manager-owned identifier from the old flat list, then add the selected manager's identifiers; preserve all other tools; de-duplicate and sort. A manually added manager-tool identifier cannot be distinguished and follows this rule. - Provider-specific URL parsing/project creation: out of scope.
- Backlog sync: none; no owning tracker story was supplied, and the configured URL field does not exist yet.
Codebase Findings
- Picker and init settings write:
apps/cli/src/scaffold/stage.ts. - Settings contract/read/write and tool inference:
apps/cli/src/core/tools.ts. - Root command registration:
apps/cli/src/index.ts. - Settings preservation seams:
apps/cli/src/scaffold/run.ts,apps/cli/src/update/run.ts. - Canonical shared skill:
/Users/stefan/Desktop/repos/wearedevpunks-skills/skills/agnostic/requirements/write-backlog. - Bundled consumer surface:
apps/cli/skills/agnostic/requirements/write-backlog.
Dependency Graph
T1 -> T2 -> T3 -> T4Sequential implementation is required because all tasks touch the same settings contract or its generated consumers. One worker owns the full slice; parent validates and reviews.
Tasks
T1: Settings selector and hi ensure
- depends_on: []
- location:
apps/cli/src/core/tools.ts, new shared selector module,apps/cli/src/cli/ensure-command.ts,apps/cli/src/index.ts, colocated tests - description: Add legacy-compatible
backlogProjectUrl; test-drive the shared four-field selector and top-level settings-only command, including defaults, URL validation, missing settings, independent asset selection, idempotency, help output, and manager-tool reconciliation. Fixtures cover GitHub→GitLab remove/add, preservation of non-manager tools, and de-duplication. - validation: Public command tests prove only settings change and all migration/preservation cases.
- status: Complete
- log: 2026-07-13 RED: corrected the planned runner to the repository Vitest command after direct
bun testbypassed workspace configuration; Vitest failed because./ensure-commanddid not exist. GREEN: 19 focused tests passed. Added the deep four-field selector seam, legacy-compatible URL normalization, settings-only command, root registration, and manager-tool reconciliation. Review RED: switching GitHub to GitLab removed an unrelatedaztool (1 of 4 command tests failed). GREEN: reconciliation now removes only the previous manager's required tools, adds the selected manager's tools, and preserves all others; 5 command tests pass, including repeated canonical-settings byte idempotency coverage. - files edited/created:
apps/cli/src/cli/ensure-command.ts,apps/cli/src/cli/ensure-command.test.ts,apps/cli/src/scaffold/settings-selection.ts,apps/cli/src/core/tools.ts,apps/cli/src/index.ts - backlog_item_id:
- backlog_item_url:
- relation_mode: none
- assigned_skills: [
autoreview,codebase-design,effect-authoring,effect-best-practices,improve-codebase-architecture,parallel-research,quality-types,simplify,swarm-planner,tdd,turborepo] - tdd_status: required
- tdd_target: Running
hi ensurethrough the public command seam rewrites only settings with independently selected providers and a validated project URL; root/command help exposes it whilehi tools ensureremains distinct. - red_command:
bun run --cwd apps/cli test -- src/cli/ensure-command.test.ts - expected_red_failure: The command/module does not exist and no settings-only reconfiguration behavior is registered.
- green_command:
bun run --cwd apps/cli test -- src/cli/ensure-command.test.ts src/core/tools.test.ts - reason_not_testable:
- red_evidence: Vitest failed the suite with
Cannot find module './ensure-command'at the public command test import; 0 tests collected, exit 1. - green_evidence: Vitest passed 2 files and 19 tests, exit 0.
- codebase_design_notes: The shared selector is the deep module seam; prompt adapters and defaults stay behind one result interface used by two callers.
- review_mode: cli
T2: Reuse selector from init and preserve URL across scaffold/update
- depends_on: [T1]
- location:
apps/cli/src/scaffold/stage.ts,apps/cli/src/scaffold/stage.test.ts,apps/cli/src/scaffold/run.test.ts,apps/cli/src/update/run.test.ts - description: Replace embedded init provider selection with the shared selector while retaining init-only wiki selection. Prove init writes independent asset provider and URL, setup preserves it, check is read-only, and apply preserves it.
- validation: Focused public scaffold/update regressions pass.
- status: Complete
- log: 2026-07-13 RED: 1 of 53 stage/update tests failed because init wrote
assetProviderSlug: linearinstead of independently selectedmondayand omittedbacklogProjectUrl. GREEN: init now calls the shared selector before its init-only wiki prompt; setup, check, and update preservation assertions pass. Review RED: invalid init URL guidance pointed tohi ensure(1 of 19 stage tests failed). GREEN: callers supply their own retry command, so init points tohi scaffold initand ensure points tohi ensure; all 19 stage tests pass. - files edited/created:
apps/cli/src/scaffold/stage.ts,apps/cli/src/scaffold/stage.test.ts,apps/cli/src/scaffold/run.test.ts,apps/cli/src/update/run.test.ts,apps/cli/src/testing/test-prompt.ts - backlog_item_id:
- backlog_item_url:
- relation_mode: none
- assigned_skills: [
autoreview,codebase-design,effect-authoring,effect-best-practices,improve-codebase-architecture,parallel-research,quality-types,simplify,swarm-planner,tdd,turborepo] - tdd_status: required
- tdd_target:
hi scaffold initand update public seams retain the selectedbacklogProjectUrland independent asset provider. - red_command:
bun run --cwd apps/cli test -- src/scaffold/stage.test.ts src/update/run.test.ts - expected_red_failure: Init still derives the asset provider and does not prompt/write the backlog project URL.
- green_command:
bun run --cwd apps/cli test -- src/scaffold/stage.test.ts src/scaffold/run.test.ts src/update/run.test.ts - reason_not_testable:
- red_evidence: Vitest ran 53 tests; the new init settings assertion failed with expected
assetProviderSlug: mondayandbacklogProjectUrl, received derivedassetProviderSlug: linearand no URL; exit 1. - green_evidence: Vitest passed 3 files and 69 tests, exit 0.
- codebase_design_notes: Init becomes a second adapter over the selector seam; settings normalization remains the single persistence boundary.
- review_mode: cli
T3: Make write-backlog consume configured destination
- depends_on: [T2]
- location:
/Users/stefan/Desktop/repos/wearedevpunks-skills/skills/agnostic/requirements/write-backlog/**, synchronized Harness skill/catalog surfaces, content/scaffold tests - description: First add a failing scaffold-consumer assertion that reads generated
.agents/skills/write-backlog/SKILL.mdand proves settings are read before provider work, both keys are authoritative, missing/invalid URL stops withhi ensure, and discovery/guessing is forbidden. Then update the upstream skill, push it, runbun run --cwd apps/cli sync:skills, compare upstream/bundled content, and make the consumer assertion green. - validation: Upstream and synchronized content agree; scaffold consumer smoke sees URL-aware guidance.
- status: Complete
- log: 2026-07-13 RED: bundled and generated-consumer assertions failed 2 of 38 tests because the skill omitted
.devpunks/settings.json. Updated canonical upstream first, committed and pushedadd6bb4, then ran the canonical CLI sync. GREEN: upstream and bundled files compare byte-for-byte; bundled and scaffolded consumer assertions pass. - files edited/created:
/Users/stefan/Desktop/repos/wearedevpunks-skills/skills/agnostic/requirements/write-backlog/SKILL.md,apps/cli/skills/agnostic/requirements/write-backlog/SKILL.md,apps/cli/src/content/content.test.ts,apps/cli/src/scaffold/stage.test.ts - backlog_item_id:
- backlog_item_url:
- relation_mode: none
- assigned_skills: [
autoreview,codebase-design,parallel-research,quality-types,simplify,tdd] - tdd_status: required
- tdd_target: A scaffolded consumer receives
write-backlogguidance that resolves its destination exclusively from settings before provider calls, with bytes/content aligned across upstream and bundled sources. - red_command:
bun run --cwd apps/cli test -- src/content/content.test.ts src/scaffold/stage.test.ts - expected_red_failure: Current bundled/scaffolded skill omits
backlogProjectUrlandhi ensurefallback guidance. - green_command:
bun run --cwd apps/cli test -- src/content/content.test.ts src/scaffold/stage.test.ts - reason_not_testable:
- red_evidence: Vitest failed the bundled and generated consumer assertions on missing
.devpunks/settings.json; 2 failed and 36 passed, exit 1. - green_evidence: Vitest passed 2 files and 38 tests;
cmpconfirmed upstream and bundledSKILL.mdbytes match; upstream main push advanced toadd6bb4. - codebase_design_notes:
.devpunks/settings.jsonis the destination-authority interface; provider assets are adapters and must not rediscover the target. - review_mode: cli
T4: Operator docs and end-to-end proof
- depends_on: [T3]
- location:
docs/README.md,docs/runbooks/hi-cli-scaffolding.md, routed wiki CLI guidance plusapps/wiki/index.md,apps/wiki/log.md, relevantmeta.json/ingest metadata,CHANGELOG.md, plan/implementation notes - description: Run
docs-ingest-phase; document command scope and naming distinction, update routed operational knowledge/bookkeeping and pending changelog, build the CLI, drive a temp-repohi ensuresmoke through the built artifact, and record evidence. - validation: Focused suite, typecheck/build, built help, temp-repo file-tree/hash assertions, local built update check, docs bookkeeping, and diff check pass.
- status: Complete
- log: 2026-07-13 Completed private/internal docs ingest, operator docs, routed flow/navigation/bookkeeping, and changelog. Built CLI help distinguishes top-level settings
ensurefromtools ensure. Built interactive fixture trimmed the URL and left the sentinel unchanged. Harness settings now point at the existing HARNESS-INTELLIGENCE Linear project URL already recorded in project backlog documentation. Generated Harness skill content was aligned without changing the committed remote-stable manifest authority or its canonical Desktop repository paths. The final remote-stable update check reports only the expected unpublished local feature drift inwrite-backlogand settings. - files edited/created:
docs/README.md,docs/runbooks/hi-cli-scaffolding.md,apps/wiki/content/docs/cli/index.mdx,apps/wiki/content/docs/cli/scaffold-lifecycle/settings-reconfiguration.mdx,apps/wiki/content/docs/cli/scaffold-lifecycle/meta.json,apps/wiki/content/docs/project/runbooks/hi-cli-scaffolding.md,apps/wiki/index.md,apps/wiki/log.md,CHANGELOG.md,.devpunks/settings.json,.agents/skills/write-backlog/SKILL.md, spec folder bookkeeping - backlog_item_id:
- backlog_item_url:
- relation_mode: none
- 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,simplify,tdd,vercel-composition-patterns,vercel-react-best-practices,writing-beats,writing-fragments,writing-great-skills,writing-shape] - tdd_status: not_applicable
- tdd_target: Documentation and built-artifact validation only after behavior is covered in T1-T3.
- red_command:
- expected_red_failure:
- green_command:
bun run --cwd apps/cli check-types && bun run --cwd apps/cli build && node apps/cli/dist/index.js --help && node apps/cli/dist/index.js ensure --help && git diff --check - reason_not_testable: Docs and closeout evidence do not introduce new runtime behavior.
- red_evidence:
- green_evidence: CLI typecheck and build passed; focused suite passed 7 files/111 tests; built root,
ensure, andtools ensurehelp passed; built interactive temp fixture stored the trimmed URL and preserved the only non-settings file hash; final remote-stable update check preserved manifest authority and classified the two expected unpublished changes (write-backlog, settings), with no stale files or baseline drift; upstream/bundled/Harness skill bytes match; focused Oxlint on new production modules andgit diff --checkpassed. Autoreview RED: barehiguide omitted top-levelhi ensureand described init as backlog-only (brand test failed 1 of 1). GREEN: guide lists and describes settings-onlyhi ensure, distinguisheshi tools ensure, and describes init as selecting repository settings; brand test and full focused suite pass. - codebase_design_notes: not_applicable
- review_mode: cli
Execution Waves
| Wave | Tasks | Start condition |
|---|---|---|
| 1 | T1 | Spec accepted |
| 2 | T2 | T1 green |
| 3 | T3 | T2 green |
| 4 | T4 | T3 synchronized and green |
Validation Gates
- Each behavior task records real RED before production edits and GREEN afterward.
- Focused CLI command, core settings, scaffold, update, and content tests pass.
bun run --cwd apps/cli check-typesandbun run --cwd apps/cli buildpass.- Built
hi ensurechanges only.devpunks/settings.jsonin a temporary initialized consumer. hi update --checkremains clean or any expected local feature drift is classified precisely.git diff --checkpasses; final readonly review has no accepted findings.
The built-artifact smoke creates a temporary repo with known settings and a sentinel file, snapshots find output plus hashes, pipes deterministic prompt answers into node apps/cli/dist/index.js ensure, asserts the trimmed URL and provider/tool transition in settings, and verifies the sentinel and all non-settings hashes are unchanged. It then runs node apps/cli/dist/index.js --help, node apps/cli/dist/index.js ensure --help, node apps/cli/dist/index.js tools ensure --help, and node apps/cli/dist/index.js update --check --json in that fixture.
Risks and Mitigations
- Legacy settings become unreadable: keep URL optional at read normalization; test missing-field fixtures.
- Manager switches leave stale tools: reconcile known manager-owned tools explicitly and preserve other requirements.
- Init prompt regressions: test the public prompt sequence and keep wiki selection outside the shared module.
- Generated skill drift: edit/push upstream first, sync through the canonical script, and compare source/bundle/scaffold output.
- Broad archived-fixture failures obscure signal: use focused tests and classify unrelated
.devpunks/pre-existing-skillsnoise separately.
Unresolved Questions
None. The request, reviewed spec, codebase evidence, and backward-compatibility constraints close the planning branches.