autonomous-sdlc-harness 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +7 -0
  3. package/README.md +24 -0
  4. package/dist/cli.js +194 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/config.js +561 -0
  7. package/dist/commands/config.js.map +1 -0
  8. package/dist/commands/daemon.js +791 -0
  9. package/dist/commands/daemon.js.map +1 -0
  10. package/dist/commands/doctor.js +336 -0
  11. package/dist/commands/doctor.js.map +1 -0
  12. package/dist/commands/init.js +2023 -0
  13. package/dist/commands/init.js.map +1 -0
  14. package/dist/commands/registry.js +42 -0
  15. package/dist/commands/registry.js.map +1 -0
  16. package/dist/config/check.js +505 -0
  17. package/dist/config/check.js.map +1 -0
  18. package/dist/config/io.js +177 -0
  19. package/dist/config/io.js.map +1 -0
  20. package/dist/config/model.js +406 -0
  21. package/dist/config/model.js.map +1 -0
  22. package/dist/core/errors.js +71 -0
  23. package/dist/core/errors.js.map +1 -0
  24. package/dist/core/git.js +537 -0
  25. package/dist/core/git.js.map +1 -0
  26. package/dist/core/json.js +125 -0
  27. package/dist/core/json.js.map +1 -0
  28. package/dist/core/layerCoverage.js +141 -0
  29. package/dist/core/layerCoverage.js.map +1 -0
  30. package/dist/core/layerGapRemedy.js +62 -0
  31. package/dist/core/layerGapRemedy.js.map +1 -0
  32. package/dist/core/nameList.js +23 -0
  33. package/dist/core/nameList.js.map +1 -0
  34. package/dist/core/paths.js +153 -0
  35. package/dist/core/paths.js.map +1 -0
  36. package/dist/core/prompt.js +206 -0
  37. package/dist/core/prompt.js.map +1 -0
  38. package/dist/core/repoPaths.js +55 -0
  39. package/dist/core/repoPaths.js.map +1 -0
  40. package/dist/core/report.js +150 -0
  41. package/dist/core/report.js.map +1 -0
  42. package/dist/core/templating.js +88 -0
  43. package/dist/core/templating.js.map +1 -0
  44. package/dist/core/writer.js +479 -0
  45. package/dist/core/writer.js.map +1 -0
  46. package/dist/daemon/backend.js +180 -0
  47. package/dist/daemon/backend.js.map +1 -0
  48. package/dist/daemon/units.js +380 -0
  49. package/dist/daemon/units.js.map +1 -0
  50. package/dist/detect/nestedApplication.js +79 -0
  51. package/dist/detect/nestedApplication.js.map +1 -0
  52. package/dist/detect/presets.js +2033 -0
  53. package/dist/detect/presets.js.map +1 -0
  54. package/dist/detect/signals.js +1368 -0
  55. package/dist/detect/signals.js.map +1 -0
  56. package/dist/doctor/checks.js +3530 -0
  57. package/dist/doctor/checks.js.map +1 -0
  58. package/dist/generators/claudeContext.js +588 -0
  59. package/dist/generators/claudeContext.js.map +1 -0
  60. package/dist/generators/githooks.js +446 -0
  61. package/dist/generators/githooks.js.map +1 -0
  62. package/dist/generators/harnessConfig.js +632 -0
  63. package/dist/generators/harnessConfig.js.map +1 -0
  64. package/dist/generators/notifications.js +191 -0
  65. package/dist/generators/notifications.js.map +1 -0
  66. package/dist/generators/outerLoopScripts.js +165 -0
  67. package/dist/generators/outerLoopScripts.js.map +1 -0
  68. package/dist/generators/permissionProfile.js +1172 -0
  69. package/dist/generators/permissionProfile.js.map +1 -0
  70. package/dist/generators/projectSettings.js +322 -0
  71. package/dist/generators/projectSettings.js.map +1 -0
  72. package/dist/generators/repoRoot.js +417 -0
  73. package/dist/generators/repoRoot.js.map +1 -0
  74. package/dist/generators/scripts.js +557 -0
  75. package/dist/generators/scripts.js.map +1 -0
  76. package/dist/generators/stateDir.js +221 -0
  77. package/dist/generators/stateDir.js.map +1 -0
  78. package/dist/machine/paths.js +111 -0
  79. package/dist/machine/paths.js.map +1 -0
  80. package/dist/machine/plugins.js +224 -0
  81. package/dist/machine/plugins.js.map +1 -0
  82. package/dist/machine/registry.js +330 -0
  83. package/dist/machine/registry.js.map +1 -0
  84. package/package.json +23 -0
  85. package/scripts/README.md +13 -0
  86. package/scripts/daemon/launchd.plist.template +59 -0
  87. package/scripts/daemon/systemd.service.template +58 -0
  88. package/templates/README.md +15 -0
  89. package/templates/claude/CLAUDE.md +54 -0
  90. package/templates/claude/README.md +5 -0
  91. package/templates/claude/context/api.md +29 -0
  92. package/templates/claude/context/conventions.md +23 -0
  93. package/templates/claude/context/data-layer.md +28 -0
  94. package/templates/claude/context/data-storage.md +29 -0
  95. package/templates/claude/context/docs-catalog.md +29 -0
  96. package/templates/claude/context/domain.md +28 -0
  97. package/templates/claude/context/layer.md +20 -0
  98. package/templates/claude/context/module.md +30 -0
  99. package/templates/claude/context/package.md +29 -0
  100. package/templates/claude/context/presentation.md +32 -0
  101. package/templates/claude/context/state-slices.md +28 -0
  102. package/templates/claude/context/tests.md +28 -0
  103. package/templates/claude/harness-task-offer.md +58 -0
  104. package/templates/claude/push-notify.env.example +21 -0
  105. package/templates/claude/qa-accounts.env.example +38 -0
  106. package/templates/claude/qa_test_scenarios.md +110 -0
  107. package/templates/claude/settings.autonomous.json +93 -0
  108. package/templates/claude/settings.autonomous.qa.json +36 -0
  109. package/templates/githooks/README.md +3 -0
  110. package/templates/githooks/pre-push +72 -0
  111. package/templates/repo/README.md +3 -0
  112. package/templates/repo/gitattributes +16 -0
  113. package/templates/repo/gitignore +61 -0
  114. package/templates/repo/gitignore.qa +25 -0
  115. package/templates/repo/mcp.json +17 -0
  116. package/templates/scripts/README.md +5 -0
  117. package/templates/scripts/autonomous-format-stream.sh +95 -0
  118. package/templates/scripts/autonomous-notify.sh +337 -0
  119. package/templates/scripts/autonomous-watcher.sh +3087 -0
  120. package/templates/scripts/cleanup-merged-worktrees.sh +327 -0
  121. package/templates/scripts/commit-on-branch.sh +288 -0
  122. package/templates/scripts/create-worktree.sh +360 -0
  123. package/templates/scripts/deploy.sh +47 -0
  124. package/templates/scripts/lib/harness-run-lib.sh +1481 -0
  125. package/templates/scripts/push-branch.sh +140 -0
  126. package/templates/scripts/refresh-branch.sh +244 -0
  127. package/templates/scripts/restart-watcher.sh +401 -0
  128. package/templates/scripts/scratch-run.sh +302 -0
  129. package/templates/scripts/setup-worktree.sh +262 -0
  130. package/templates/scripts/start-dev-server.sh +99 -0
  131. package/templates/scripts/test.sh +50 -0
  132. package/templates/scripts/typecheck.sh +50 -0
  133. package/templates/state-dir/README-root.md +13 -0
  134. package/templates/state-dir/README.md +9 -0
  135. package/templates/state-dir/architecture_branch_review_point_reviews/README.md +9 -0
  136. package/templates/state-dir/architecture_branch_reviews/README.md +9 -0
  137. package/templates/state-dir/architecture_reviews/README.md +9 -0
  138. package/templates/state-dir/architecture_user_review_reviews/README.md +9 -0
  139. package/templates/state-dir/autonomous_inbox/README.md +9 -0
  140. package/templates/state-dir/autonomous_logs/README.md +9 -0
  141. package/templates/state-dir/branch_statistics/README.md +9 -0
  142. package/templates/state-dir/business_parity_branch_review_point_reviews/README.md +9 -0
  143. package/templates/state-dir/business_parity_branch_reviews/README.md +9 -0
  144. package/templates/state-dir/business_parity_reviews/README.md +9 -0
  145. package/templates/state-dir/business_parity_user_review_reviews/README.md +9 -0
  146. package/templates/state-dir/clarification_digests/README.md +9 -0
  147. package/templates/state-dir/clarifications/README.md +9 -0
  148. package/templates/state-dir/code_reviews/README.md +9 -0
  149. package/templates/state-dir/dispatch_additions/README.md +19 -0
  150. package/templates/state-dir/docs_catalog/README.md +9 -0
  151. package/templates/state-dir/flow_progress/README.md +9 -0
  152. package/templates/state-dir/improvement_observations/README.md +19 -0
  153. package/templates/state-dir/improvement_suggestions.md +29 -0
  154. package/templates/state-dir/lessons.md +23 -0
  155. package/templates/state-dir/qa_review_point_reviews/README.md +9 -0
  156. package/templates/state-dir/qa_reviews/README.md +9 -0
  157. package/templates/state-dir/review_plan_point_reviews/README.md +9 -0
  158. package/templates/state-dir/review_plan_reviews/README.md +9 -0
  159. package/templates/state-dir/scratch/README.md +11 -0
  160. package/templates/state-dir/skeptic_review_plan_reviews/README.md +9 -0
  161. package/templates/state-dir/skeptic_review_point_reviews/README.md +9 -0
  162. package/templates/state-dir/skeptic_reviews/README.md +9 -0
  163. package/templates/state-dir/story_plans/README.md +9 -0
  164. package/templates/state-dir/task_plan_point_reviews/README.md +9 -0
  165. package/templates/state-dir/task_plan_reviews/README.md +9 -0
  166. package/templates/state-dir/task_plans/README.md +9 -0
  167. package/templates/state-dir/task_prompts/README.md +9 -0
  168. package/templates/state-dir/ui_test_plan_reviews/README.md +9 -0
  169. package/templates/state-dir/ui_test_plans/README.md +9 -0
  170. package/templates/state-dir/user_review_fix_plan_point_reviews/README.md +9 -0
  171. package/templates/state-dir/user_reviews/README.md +9 -0
@@ -0,0 +1,588 @@
1
+ /**
2
+ * Generator: the always-loaded project file, the conventions stubs behind it, and the two
3
+ * `*.env.example` companions an adopter copies and completes.
4
+ *
5
+ * **The rule this module exists to enforce: which stubs are written, and which rows the routing
6
+ * table carries, are both read off `layers[]` — never off a list kept here.** `layers[].conventions`
7
+ * is "the document holding this layer's rules" (`schemas/harness.config.schema.json`), and the
8
+ * orchestrator assigns every task to exactly one layer, so a fixed file list here would put a
9
+ * skeleton at a path no layer points at while leaving the path one *does* point at empty. A
10
+ * generated table that disagrees with the configuration it was generated from is worse than no
11
+ * table: an agent follows the pointer rather than the config.
12
+ *
13
+ * ## Three non-obvious choices, and where each comes from
14
+ *
15
+ * 1. **The templates live at `templates/claude/…`, without the dot, and `init` adds it.** They are
16
+ * templates for *someone else's* configuration, so the dot belongs at the adopter's end: `init`
17
+ * adds it — here via `CLAUDE_DIR`, and in the sibling generators that declare their own — and no
18
+ * stored template path carries it. Not because a dotted path here would register them as live
19
+ * assets: that reason was withdrawn as measurably false (`cli/templates/claude/README.md`,
20
+ * `cli/templates/README.md`). This is the generator where that distinction becomes load-bearing
21
+ * rather than decorative.
22
+ * 2. **Every file here is `create-if-absent`, and the analyze command is why.** These are skeletons
23
+ * that a later pass fills in from the adopted repository's real code, and the adopter edits them
24
+ * afterwards; a second `init` that rewrote one would undo both. That is the write engine's own
25
+ * row for this artifact (`core/writer.ts`), and `--force` still takes a `.bak` first.
26
+ * 3. **The two `.env.example` files are written beside the file they tell you to create** — at
27
+ * `<configured path>.example` — rather than at a fixed name. Their whole content is "copy me to
28
+ * the path `pushEnvPath` / `qa.credentialsPath` names"; written anywhere else, that instruction
29
+ * points across the tree. With the paths `init` itself seeds, both land in `.claude/`, which is
30
+ * where the template tree says a `claude/` template goes.
31
+ *
32
+ * ## What this generator deliberately does not do
33
+ *
34
+ * - **It does not restate the project-command wrappers.** `commands.*` in `harness.config.json` is
35
+ * the canonical home for those invocations, and the config, the wrapper files and the permission
36
+ * profile are already three views of one string (`generators/scripts.ts`); an always-loaded file
37
+ * repeating them would be a fourth, drifting the moment `scriptsDir` moves.
38
+ * - **It does not invent credential key names.** The two example files carry harness-generic keys —
39
+ * `HARNESS_PUSH_*`, `HARNESS_QA_<n>_*` — and say so in their own header comments, so an adopter
40
+ * carrying settings over from another runner renames the keys rather than the reader.
41
+ */
42
+ import { existsSync, readFileSync } from 'node:fs';
43
+ import { join, posix } from 'node:path';
44
+ import { DEFAULTS } from '../config/model.js';
45
+ import { defaultProjectName, readTemplate } from '../core/paths.js';
46
+ import { normalizeRepoPathStrict } from '../core/repoPaths.js';
47
+ import { renderTemplate } from '../core/templating.js';
48
+ import { SHARED_CONVENTIONS_PATH } from '../detect/presets.js';
49
+ import { PUSH_ENV_PATH, QA_CREDENTIALS_PATH } from './harnessConfig.js';
50
+ import { PLUGIN_NAME } from './projectSettings.js';
51
+ /** The adopter-side directory this whole template subtree lands in. The dot is `init`-side only. */
52
+ const CLAUDE_DIR = '.claude';
53
+ /**
54
+ * The always-loaded project file, relative to the repository root.
55
+ *
56
+ * Exported because two readers outside this module address the same file: `init` reads it before the
57
+ * plan is applied, to resolve the analyze offer and to decide which of its closing wordings is true,
58
+ * and `doctor`'s `setup-analysis` check reads it for the {@link SETUP_PENDING_OPEN} banner. Both
59
+ * import this rather than re-spelling `.claude/CLAUDE.md`, for the reason the markers below are
60
+ * exported: a second copy of a literal is a copy that can drift.
61
+ */
62
+ export const CLAUDE_MD_PATH = `${CLAUDE_DIR}/CLAUDE.md`;
63
+ /**
64
+ * The project's test-scenario rules, relative to the repository root — written only when the
65
+ * interactive test phase is on.
66
+ *
67
+ * **The basename is carried over from the instruction corpus unchanged, and renaming it here is a
68
+ * breaking change.** The shipped QA assets — the test instructions, and the agents that plan and run
69
+ * the interactive phase — dereference this document by that exact name rather than through a config
70
+ * key, so a different name here leaves every one of them pointing at a file nothing writes. It is
71
+ * `create-if-absent` like every other `.claude/` artifact: the skeleton is the adopter's from the
72
+ * moment it lands, and the rules they fill in are the only copy.
73
+ */
74
+ export const QA_SCENARIOS_PATH = `${CLAUDE_DIR}/qa_test_scenarios.md`;
75
+ /**
76
+ * The change-request offer dialogue, relative to the repository root — planned on every run, whatever the
77
+ * configured phases are, and created where it is absent.
78
+ *
79
+ * **The basename is dereferenced by name**, from the always-loaded project file's
80
+ * `## Where a change request runs` section, so renaming it here leaves that pointer aimed at a file
81
+ * nothing writes and silently disables the offer. Exported because `doctor` addresses the same file
82
+ * rather than re-spelling it.
83
+ */
84
+ export const TASK_OFFER_PATH = `${CLAUDE_DIR}/harness-task-offer.md`;
85
+ /** The templates' subdirectory under `cli/templates/`, addressed as {@link readTemplate} wants it. */
86
+ const TEMPLATE_DIR = 'claude';
87
+ /** The context stubs' subdirectory inside {@link TEMPLATE_DIR}. */
88
+ const CONTEXT_TEMPLATE_DIR = 'context';
89
+ /**
90
+ * The stubs that have a skeleton of their own, keyed by the **basename** a layer's `conventions`
91
+ * path ends in. Each name is also its template's file name under `templates/claude/context/`, so a
92
+ * stub is added by dropping one template in beside its siblings and adding its name here.
93
+ *
94
+ * A configured conventions path matching none of these gets {@link GENERIC_STUB_TEMPLATE} instead:
95
+ * the layer still needs a document at the path the config promises, and a generic skeleton naming
96
+ * the layer is more use to its implementer than a missing file.
97
+ *
98
+ * **The set is not a list of what `init` generates, and is deliberately larger than one.** Two
99
+ * groups:
100
+ *
101
+ * - **Reached by a preset.** `conventions.md` (every preset's `general` layer), `data-layer.md`,
102
+ * `domain.md`, `presentation.md` (`layered-clean-arch`), `api.md` (`api-service`) and
103
+ * `package.md` (`python-package`), `module.md` (every preset whose layer profile is a conventional
104
+ * source root — `cmake-cpp` points both of its rows at it), and `tests.md` — the document every preset's **test** layer points at, reached by
105
+ * `flutter`, `jvm`, `android-gradle`, `apple-native`, `rust-cargo`, `dotnet`, `php-composer`,
106
+ * `ruby-bundler`, `python-package`, `cmake-cpp`, `layered-clean-arch` and `api-service` whenever
107
+ * the conventional test root of that preset's toolchain exists — the basenames
108
+ * `detect/presets.ts` can produce. Every one of
109
+ * them must be here and must have a template: a preset's own layer falling through to the generic
110
+ * skeleton is the whole point of the preset lost, and `test/init.test.mjs` asserts the pairing
111
+ * over each preset rather than leaving it to inspection.
112
+ * - **Reachable only by hand.** `data-storage.md`, `docs-catalog.md` and `state-slices.md` are
113
+ * skeletons for three concerns no preset detects — local persistence, a documentation catalog,
114
+ * shared application state. Nothing `init` generates points at them, and the one route that reads
115
+ * one is an adopter pointing a `layers[].conventions` at that exact basename and re-running
116
+ * `init`. A path a `/harness-analyze` layer-profile revision newly names does **not** reach them:
117
+ * that command never re-runs `init`, so `conventions-writer` composes the document with no file
118
+ * behind it. They are kept rather than deleted because writing one of those documents from
119
+ * nothing is the expensive part, and they are named here so a later reader does not take them for
120
+ * dead templates.
121
+ */
122
+ const DEDICATED_STUBS = new Set([
123
+ 'api.md',
124
+ 'conventions.md',
125
+ 'data-layer.md',
126
+ 'data-storage.md',
127
+ 'docs-catalog.md',
128
+ 'domain.md',
129
+ 'module.md',
130
+ 'package.md',
131
+ 'presentation.md',
132
+ 'state-slices.md',
133
+ 'tests.md',
134
+ ]);
135
+ /** The skeleton rendered for a layer whose conventions basename is in none of those above. */
136
+ const GENERIC_STUB_TEMPLATE = 'layer.md';
137
+ /**
138
+ * The two halves of the **untouched-skeleton test**, which is how anything in this tree answers
139
+ * "has anybody filled this document in yet" — the marker every shipped skeleton carries as its last
140
+ * line, and the guidance block every shipped skeleton carries in its body.
141
+ *
142
+ * **They are read together, always, and the marker alone decides nothing.** Each skeleton's footer
143
+ * tells a hand-writer to *replace everything above* it, so an adopter who wrote their rules by hand
144
+ * has removed the guidance block whether or not they thought to delete a trailing HTML comment.
145
+ * Testing the marker alone would report that finished document as unfilled forever, and the only
146
+ * remedy on offer would be the analyze command that adopter declined — which is the path this
147
+ * harness deliberately keeps open.
148
+ *
149
+ * Read by: `doctor`'s `setup-analysis` check, `init`'s "is anything left to fill" question, and the
150
+ * analyze command's decision about whether it may write a target without asking (it clears the
151
+ * marker when it writes). The literal strings also live in every skeleton under
152
+ * `templates/claude/context/` — `ls cli/templates/claude/context/` enumerates them — which is
153
+ * where they are produced: a template and these constants disagreeing makes every consumer report
154
+ * every document as filled.
155
+ */
156
+ export const UNFILLED_STUB_MARKER = '<!-- harness:unfilled -->';
157
+ /** The other half of the two-part test in {@link UNFILLED_STUB_MARKER}; never applied on its own. */
158
+ export const SKELETON_GUIDANCE_MARKER = '**What belongs here**';
159
+ /**
160
+ * The **untouched-skeleton test** as one predicate over one document's text: both halves above
161
+ * present, read together and never apart.
162
+ *
163
+ * Exported so a consumer that already holds the text applies the conjunction rather than re-spelling
164
+ * it — `init`'s pre-plan read does, and so does the `.bak` decision in {@link writeClaudeContext}
165
+ * below. It deliberately answers about **text only**: what an unreadable file means differs by call
166
+ * site — a document `init` is about to create counts as untouched there, and a `.bak` that is not
167
+ * there protects nothing here — so each caller decides that for itself.
168
+ */
169
+ export function isUntouchedSkeletonText(content) {
170
+ return content.includes(UNFILLED_STUB_MARKER) && content.includes(SKELETON_GUIDANCE_MARKER);
171
+ }
172
+ /**
173
+ * The analyze targets that are **not** layer names: the layer profile itself, the always-loaded
174
+ * project file, and the shared cross-layer document that is generated whether or not a layer points
175
+ * at it (`docs/analyze.md` §1).
176
+ *
177
+ * Read by: the invocation this generator renders into each stub footer, and `init`'s closing pointer.
178
+ * The config schema's `name` pattern admits all three, so a layer may legitimately carry one — that
179
+ * layer loses the one-word invocation to the reserved meaning, visibly rather than silently, and is
180
+ * still covered by the no-argument pass.
181
+ */
182
+ export const RESERVED_ANALYZE_TARGETS = ['project', 'conventions', 'layers'];
183
+ /** The command each stub footer points at, argument appended. */
184
+ const ANALYZE_COMMAND = '/harness-analyze';
185
+ /**
186
+ * The delimiters of the **setup-pending banner** the generated project file carries under its
187
+ * heading: the record of what the adopter answered `autonomous-sdlc-harness init`'s analyze offer
188
+ * (`docs/analyze.md` §9), written into the one file every session in that repository loads without
189
+ * being asked.
190
+ *
191
+ * Read by two consumers outside this module, both on these exact literals: `doctor`'s
192
+ * `setup-analysis` check detects the open marker and reports the setup as unfinished, and the
193
+ * analyze command deletes the block between the two inclusive as its last act.
194
+ *
195
+ * **The banner is not a guaranteed record of the answer on a re-run.** {@link CLAUDE_MD_PATH} is
196
+ * enqueued `create-if-absent`, with `WriteRequest.forceOverride: 'never'` on the one case
197
+ * {@link keepsIdenticalProjectFile} computes, so there are three outcomes and not two. *Created*: the
198
+ * banner is in the file. *Kept* — an unforced re-run over a file that is already there, or a forced
199
+ * one over a file already byte-identical to the text this run renders — nothing is written into it;
200
+ * the unforced route says so in a note of {@link writeClaudeContext}'s own and the forced one in
201
+ * `init`'s closing sentence, and that report is what carries the answer on either.
202
+ * *Overwritten under `--force`*: the
203
+ * whole file is regenerated from the template after its single `.bak`, so the banner is
204
+ * **re-inserted** and `doctor`'s `setup-analysis` warning re-opens until the command is run again or
205
+ * the block is deleted by hand. The standing readers of what is still unfilled are that check and
206
+ * {@link UNFILLED_STUB_MARKER}'s two-part test — never this banner.
207
+ */
208
+ export const SETUP_PENDING_OPEN = '<!-- harness:setup-pending -->';
209
+ /** The banner's closing delimiter: the block {@link SETUP_PENDING_OPEN} documents ends here. */
210
+ export const SETUP_PENDING_CLOSE = '<!-- /harness:setup-pending -->';
211
+ /**
212
+ * Where the command named in both wordings comes from — a **fact about this repository's state**, not
213
+ * an instruction to install anything.
214
+ *
215
+ * Without it the reader who reaches the wrong answer is the adopter who opens a session before the
216
+ * plugin resolves — a clone that never ran `init`, a runner pointed elsewhere — and meets a banner
217
+ * naming a command that is not there, with nothing in the block saying what would have to be true for
218
+ * it to exist. Naming no marketplace and no install step keeps it a fact: `init` already merged the
219
+ * plugin key into the settings file this clause names, so the state it reports is one the same run
220
+ * left behind.
221
+ */
222
+ const PLUGIN_ORIGIN_CLAUSE = `\`${ANALYZE_COMMAND}\` is a command of the harness plugin, which \`npx autonomous-sdlc-harness init\` enabled for this repository in \`${CLAUDE_DIR}/settings.json\`, so it exists in a session that resolves that plugin.`;
223
+ /**
224
+ * The banner's body, one blockquote per answer.
225
+ *
226
+ * **Each wording ends by stating its own disposal** (`docs/analyze.md` §10): the command removes the
227
+ * block, or the adopter deletes it once these sections are written. This file is loaded on every turn
228
+ * of every session in that repository and no later unforced run revises the block, so a wording
229
+ * without that sentence leaves the adopter who *declined* carrying "setup is not finished" — and
230
+ * `doctor`'s matching warning — with the only route out being the command they turned down.
231
+ *
232
+ * Both wordings carry {@link PLUGIN_ORIGIN_CLAUSE}, and it sits **before** each disposal sentence so
233
+ * neither ends on anything else: the decliner who changes their mind reaches for the same command as
234
+ * the accepter, so a clause on one arm only would leave the other reader with the wrong answer.
235
+ *
236
+ * Neither wording says when the pass will run, neither presents the command as the only route, and
237
+ * each states the repository's setup state rather than addressing an order to whoever reads it next.
238
+ */
239
+ const SETUP_PENDING_BODY = {
240
+ accepted: `> **Setup is not finished.** The sections below are skeletons, and \`${ANALYZE_COMMAND}\` was accepted at setup: running it is this session's first action. ${PLUGIN_ORIGIN_CLAUSE} The command removes this block when it has run — or the block can be deleted by hand once these sections are written.`,
241
+ declined: `> **Setup is not finished.** The sections below are skeletons, and the analysis was declined at setup: they are yours to write by hand, and \`${ANALYZE_COMMAND}\` still fills them if you change your mind. ${PLUGIN_ORIGIN_CLAUSE} In either case, the block can be deleted by hand once these sections are written.`,
242
+ };
243
+ /** The delimited block rendered into the template's `{{setupBanner}}` slot. */
244
+ function setupBanner(offer) {
245
+ return `${SETUP_PENDING_OPEN}\n${SETUP_PENDING_BODY[offer]}\n${SETUP_PENDING_CLOSE}`;
246
+ }
247
+ /** The ledger the routing table links to, at the root of the configured `stateDir`. */
248
+ const LESSONS_LEDGER = 'lessons.md';
249
+ /** Suffix distinguishing the committed example from the machine-local file it is copied to. */
250
+ const EXAMPLE_SUFFIX = '.example';
251
+ /**
252
+ * A link from `.claude/CLAUDE.md` to a repo-relative target — `context/data-layer.md` for a
253
+ * conventions file in the usual place, `../sdlc-harness/lessons.md` for a ledger outside it.
254
+ *
255
+ * Relative rather than repo-relative because the link is read from the file it sits in, and a
256
+ * conventions path may legitimately point anywhere in the repository.
257
+ */
258
+ function linkFromClaudeDir(repoRelative) {
259
+ const link = posix.relative(CLAUDE_DIR, repoRelative);
260
+ return link === '' ? repoRelative : link;
261
+ }
262
+ /** `a`, `a and b`, `a, b and c` — for a description naming the layers that share one document. */
263
+ function joinPhrases(parts) {
264
+ if (parts.length <= 1)
265
+ return parts[0] ?? '';
266
+ return `${parts.slice(0, -1).join(', ')} and ${parts[parts.length - 1]}`;
267
+ }
268
+ /**
269
+ * The conventions documents to write, deduplicated by path and in the order the routing table
270
+ * lists them: the shared cross-layer document first, then one entry per distinct
271
+ * `layers[].conventions` value in `layers[]` order.
272
+ *
273
+ * **The shared document is always present, even when no layer points at it.** It holds the rules
274
+ * that span every layer — the flow between them, where a new responsibility goes, the testing bar
275
+ * — so every other stub is written on the assumption that it exists, and `CLAUDE.md` gives it a
276
+ * row whatever the layer list looks like. Where a layer *does* point at it (every preset's
277
+ * `general` layer does), that layer joins this entry rather than creating a second one.
278
+ */
279
+ function collectStubs(config) {
280
+ const byPath = new Map();
281
+ const sharedPath = normalizeRepoPathStrict(SHARED_CONVENTIONS_PATH);
282
+ byPath.set(sharedPath, { path: sharedPath, layers: [] });
283
+ for (const layer of config.layers) {
284
+ const path = normalizeRepoPathStrict(layer.conventions);
285
+ const entry = byPath.get(path);
286
+ if (entry === undefined)
287
+ byPath.set(path, { path, layers: [layer] });
288
+ else
289
+ entry.layers.push(layer);
290
+ }
291
+ return [...byPath.values()].map(({ path, layers }) => {
292
+ const basename = posix.basename(path);
293
+ const dedicated = DEDICATED_STUBS.has(basename);
294
+ return {
295
+ path,
296
+ template: `${CONTEXT_TEMPLATE_DIR}/${dedicated ? basename : GENERIC_STUB_TEMPLATE}`,
297
+ dedicated,
298
+ layers,
299
+ };
300
+ });
301
+ }
302
+ /** The file's text, or `undefined` when there is nothing readable at that path. */
303
+ function readIfPossible(path) {
304
+ try {
305
+ return readFileSync(path, 'utf8');
306
+ }
307
+ catch {
308
+ return undefined;
309
+ }
310
+ }
311
+ /**
312
+ * Whether a forced run must **keep** this conventions document, because replacing it would destroy
313
+ * the analysis rather than back it up.
314
+ *
315
+ * The engine's `.bak` is single-generation — overwritten, never chained (`core/writer.ts`) — so a
316
+ * *second* forced run over an already-skeletonised corpus replaces a `.bak` holding the filled
317
+ * document with one holding the skeleton, and no copy of the analysis is left anywhere. Both
318
+ * conjuncts below are what keeps this to that case:
319
+ *
320
+ * - **The `.bak` exists and is not itself an untouched skeleton.** Without it there is nothing to
321
+ * protect: a first forced run writes the filled document into the `.bak` and loses nothing.
322
+ * - **The document on disk exists and *is* an untouched skeleton.** Without it a forced run could
323
+ * never put a *filled* document back to a skeleton, which is a legitimate thing to want — and on
324
+ * that run the `.bak` this write produces holds the filled document, so nothing is lost.
325
+ *
326
+ * Any read that fails means no override and the ordinary forced behaviour: this is a protection
327
+ * layered on top of the existing backup, not a gate that may refuse a run.
328
+ */
329
+ function keepsRescuedBackup(repoRoot, repoRelative) {
330
+ const target = join(repoRoot, repoRelative);
331
+ const backup = readIfPossible(`${target}.bak`);
332
+ if (backup === undefined || isUntouchedSkeletonText(backup))
333
+ return false;
334
+ const current = readIfPossible(target);
335
+ return current !== undefined && isUntouchedSkeletonText(current);
336
+ }
337
+ /**
338
+ * Whether a forced run must **keep** the always-loaded project file, because regenerating it would
339
+ * put nothing in the `.bak` and destroy whatever is already there.
340
+ *
341
+ * **The test is byte-identity with the text this run would write, and it is the right one for this
342
+ * file specifically.** It carries neither {@link UNFILLED_STUB_MARKER} nor
343
+ * {@link SKELETON_GUIDANCE_MARKER}, so {@link isUntouchedSkeletonText} — the two-part test
344
+ * {@link keepsRescuedBackup} applies to a conventions document — answers nothing about it. Equality
345
+ * with the rendered text is the exact statement of both halves of the loss: the `.bak` this write
346
+ * would produce receives nothing the template does not already carry, and the `.bak` already there —
347
+ * single-generation, overwritten rather than chained (`core/writer.ts`) — is destroyed to make room
348
+ * for it.
349
+ *
350
+ * A read that fails means no override and the ordinary forced behaviour, as in
351
+ * {@link keepsRescuedBackup}: this protects a backup, it never refuses a run.
352
+ */
353
+ function keepsIdenticalProjectFile(repoRoot, rendered) {
354
+ return readIfPossible(join(repoRoot, CLAUDE_MD_PATH)) === rendered;
355
+ }
356
+ /** The routing table's `When working on…` cell for the shared cross-layer document. */
357
+ function sharedConventionsDescription(layers) {
358
+ const base = '**Any implementation, review or planning** — the rules that hold in every layer';
359
+ if (layers.length === 0)
360
+ return base;
361
+ const names = joinPhrases(layers.map((layer) => `\`${layer.name}\``));
362
+ return `${base}, and the ${names} ${layers.length === 1 ? "layer's" : "layers'"} own rules`;
363
+ }
364
+ /** The routing table's `When working on…` cell for one layer's document. */
365
+ function layerDescription(layers) {
366
+ const names = joinPhrases(layers.map((layer) => `\`${layer.name}\``));
367
+ const paths = [...new Set(layers.map((layer) => (layer.path === '.' ? 'the repository root' : `\`${layer.path}\``)))];
368
+ return `The ${names} ${layers.length === 1 ? 'layer' : 'layers'} — ${joinPhrases(paths)}`;
369
+ }
370
+ /** One row of the routing table: a description, and a link that is also its own label. */
371
+ function routingRow(description, link) {
372
+ return `| ${description} | [\`${link}\`](${link}) |`;
373
+ }
374
+ /**
375
+ * The routing table's body — one row per conventions document, then the lessons ledger.
376
+ *
377
+ * Built from {@link collectStubs}' own list rather than from a second walk of `layers[]`, so a
378
+ * document that is written always has a row and a row never points at a document that is not.
379
+ */
380
+ function routingRows(stubs, sharedPath, stateDir) {
381
+ const rows = stubs.map((stub) => routingRow(stub.path === sharedPath ? sharedConventionsDescription(stub.layers) : layerDescription(stub.layers), linkFromClaudeDir(stub.path)));
382
+ rows.push(routingRow('**Planning or reviewing at branch level** — the lessons ledger: one-line rules distilled from defects that got past every automated gate and were caught by a human', linkFromClaudeDir(posix.join(stateDir, LESSONS_LEDGER))));
383
+ return rows.join('\n');
384
+ }
385
+ /**
386
+ * Render a context template through {@link renderTemplate}.
387
+ *
388
+ * **`assertNoneSurvive` is on**, and deliberately: every value substituted here is a path, a layer
389
+ * name, a manifest-mirrored slug or generated markup, none of which has any business carrying
390
+ * `{{…}}`. One that did would ship a half-rendered always-loaded file — the one file every session
391
+ * reads without being asked.
392
+ */
393
+ function render(template, values) {
394
+ return renderTemplate(readTemplate(`${TEMPLATE_DIR}/${template}`), values, {
395
+ describe: `the context template ${template}`,
396
+ assertNoneSurvive: true,
397
+ });
398
+ }
399
+ /**
400
+ * The invocation one stub's footer tells its reader to run, and the warning a reserved name earns.
401
+ *
402
+ * The vocabulary is the **layer name** rather than the document's path (`docs/analyze.md` §1): a
403
+ * path vocabulary cannot express the two targets that name no file. Three cases, in order:
404
+ *
405
+ * - **No layer points here.** Only the shared cross-layer document reaches this, and its target is
406
+ * the reserved word `conventions` — the name that exists precisely because it is generated
407
+ * whether or not a layer names it.
408
+ * - **The first layer's name is reserved.** The bare command, plus a warning: the one-word
409
+ * invocation is gone, the document is not — the no-argument pass still reaches it.
410
+ * - **Otherwise**, the first layer's name. Where several layers share a document, the first is the
411
+ * one the generic-skeleton warning above already names.
412
+ */
413
+ function analyzeInvocation(layerNames, stubPath, warnings) {
414
+ const target = layerNames[0];
415
+ if (target === undefined)
416
+ return `${ANALYZE_COMMAND} conventions`;
417
+ if (RESERVED_ANALYZE_TARGETS.includes(target)) {
418
+ warnings.push(`the layer \`${target}\` is named for a reserved analyze target, which addresses something else — \`${target}\` means ${reservedMeaning(target)} — so ${stubPath} is reached by \`${ANALYZE_COMMAND}\` with no argument, or by renaming the layer`);
419
+ return ANALYZE_COMMAND;
420
+ }
421
+ return `${ANALYZE_COMMAND} ${target}`;
422
+ }
423
+ /** What each reserved word addresses, for the collision warning above. */
424
+ function reservedMeaning(target) {
425
+ if (target === 'project')
426
+ return 'the always-loaded project file';
427
+ if (target === 'conventions')
428
+ return 'the shared cross-layer document';
429
+ return 'the layer profile itself';
430
+ }
431
+ /**
432
+ * Enqueue the always-loaded project file, one conventions stub per configured document, and the
433
+ * `*.env.example` companions — every one of them `create-if-absent`.
434
+ *
435
+ * Selection, and why each rule is what it is:
436
+ *
437
+ * - **`CLAUDE.md` always.** It is the file the agent runner loads without being asked, and the only
438
+ * place the read-on-demand rule for everything else is written down.
439
+ * - **The {@link TASK_OFFER_PATH} dialogue always**, because the always-loaded file's fence points
440
+ * at it by name, and an absent target silently disables the offer that pointer describes.
441
+ * - **One stub per distinct `layers[].conventions` path**, plus the shared cross-layer document
442
+ * whether or not a layer names it. A configured path with no document behind it is a pointer an
443
+ * implementer follows to nothing.
444
+ * - **`push-notify.env.example` always**, because the push settings are read whatever the phases
445
+ * are, and **`qa-accounts.env.example` plus the {@link QA_SCENARIOS_PATH} skeleton only when
446
+ * `phases.qa`** — an adopter who never runs the interactive test phase has no accounts to put in
447
+ * the one and no scenarios to write in the other, and an empty credentials example is a file that
448
+ * looks like a step someone forgot to finish.
449
+ *
450
+ * Nothing here writes: the generator plans, and `init` applies the plan once. Its filesystem reads
451
+ * are of three kinds, and each decides a note, a per-request flag or a reported fact rather than any
452
+ * content. Whether the always-loaded file is already there, which decides the kept-file note — an
453
+ * unforced run keeps that file, so the setup-pending banner cannot reach it and the run says so, and
454
+ * whether its `.bak` sibling was already there, which decides
455
+ * {@link ClaudeContextResult.claudeMdBackupExisted}. On
456
+ * a forced run only, that file's own text against the text rendered here, which decides
457
+ * {@link keepsIdenticalProjectFile} and {@link ClaudeContextResult.claudeMdBackupWouldCarryContent}.
458
+ * And, on a forced run only, each conventions document and its `.bak` sibling, which decide
459
+ * {@link keepsRescuedBackup} and the note below it. Those last two kinds are reads rather than a
460
+ * policy change
461
+ * because the answer is a fact about **this** tree at **this** moment: the corpus keeps the
462
+ * `create-if-absent` row it has always had, and a class-wide `--force` exemption like the ledgers'
463
+ * would also stop the forced regeneration of a filled corpus, which is a thing an adopter may
464
+ * legitimately want.
465
+ */
466
+ export function writeClaudeContext({ repoRoot, config, plan, analyzeOffer = 'accepted', force = false, dryRun = false, }) {
467
+ const warnings = [];
468
+ const notes = [];
469
+ const envExamples = [];
470
+ // Trailing separator removed for the token, which is substituted into a `<root>/…/lessons.md`
471
+ // sentence where a doubled slash reads as a typo; the ledger link is built with `posix.join`,
472
+ // which normalises it either way.
473
+ const stateDir = (config.stateDir ?? DEFAULTS.stateDir).replace(/\/+$/, '');
474
+ const sharedPath = normalizeRepoPathStrict(SHARED_CONVENTIONS_PATH);
475
+ const stubs = collectStubs(config);
476
+ const claudeMdExisted = existsSync(join(repoRoot, CLAUDE_MD_PATH));
477
+ // Read before the plan, like every other fact reported from here: the keep's wording turns on
478
+ // whether a `.bak` was there when the run started, and the write engine may create one below.
479
+ const claudeMdBackupExisted = existsSync(join(repoRoot, `${CLAUDE_MD_PATH}.bak`));
480
+ // Rendered into a local rather than inline, because the identity test below compares the file on
481
+ // disk against this exact text: the answer is what decides the per-request override and the fact
482
+ // `init` words its closing sentence from.
483
+ const claudeMdContent = render('CLAUDE.md', {
484
+ projectName: config.projectName ?? defaultProjectName(repoRoot),
485
+ setupBanner: setupBanner(analyzeOffer),
486
+ routingRows: routingRows(stubs, sharedPath, stateDir),
487
+ stateDir,
488
+ });
489
+ const keepClaudeMd = force && keepsIdenticalProjectFile(repoRoot, claudeMdContent);
490
+ plan.add({
491
+ path: join(repoRoot, CLAUDE_MD_PATH),
492
+ policy: 'create-if-absent',
493
+ ...(keepClaudeMd ? { forceOverride: 'never' } : {}),
494
+ content: claudeMdContent,
495
+ label: 'project context file',
496
+ });
497
+ // Planned beside the file that points at it: the two make up one feature, and gating this one on a
498
+ // phase would ship that pointer with no target.
499
+ plan.add({
500
+ path: join(repoRoot, TASK_OFFER_PATH),
501
+ policy: 'create-if-absent',
502
+ content: render('harness-task-offer.md', { pluginName: PLUGIN_NAME }),
503
+ label: 'change-request offer rules',
504
+ });
505
+ if (claudeMdExisted && !force) {
506
+ notes.push(`${CLAUDE_MD_PATH} was already there and ${dryRun ? 'would be kept' : 'was kept'} as it stands, so the setup-pending banner ${dryRun ? 'would not be' : 'was not'} written into it: run \`npx autonomous-sdlc-harness doctor\` at any time for what is still unfilled`);
507
+ }
508
+ const written = [];
509
+ const keptForBackup = [];
510
+ for (const stub of stubs) {
511
+ const layerNames = stub.layers.map((layer) => layer.name);
512
+ if (!stub.dedicated && stub.layers.length > 1) {
513
+ warnings.push(`layers ${joinPhrases(layerNames)} all point at ${stub.path}, which has no dedicated skeleton, so the generic layer stub was written once for ${layerNames[0]}: give each layer its own conventions document, or the rules of one are what every implementer of the others reads`);
514
+ }
515
+ const keep = force && keepsRescuedBackup(repoRoot, stub.path);
516
+ if (keep)
517
+ keptForBackup.push(stub.path);
518
+ plan.add({
519
+ path: join(repoRoot, stub.path),
520
+ policy: 'create-if-absent',
521
+ // The one per-request exception to the run's `--force`, and it is computed from the tree
522
+ // rather than fixed by this artifact's class: the policy, content and label are what they
523
+ // have always been, and an ordinary forced run still replaces the document after a `.bak`.
524
+ ...(keep ? { forceOverride: 'never' } : {}),
525
+ content: render(stub.template, {
526
+ layerName: layerNames[0] ?? 'general',
527
+ analyzeInvocation: analyzeInvocation(layerNames, stub.path, warnings),
528
+ }),
529
+ label: `conventions stub ${stub.path}`,
530
+ });
531
+ written.push({ path: stub.path, dedicated: stub.dedicated, layers: layerNames });
532
+ }
533
+ if (keptForBackup.length > 0) {
534
+ // `init`'s `analyzeRecordSentence` needs no edit to stay truthful beside this note, and this is
535
+ // why: its `putBack` clause is keyed on `filledConventions` — the documents that were **not**
536
+ // untouched skeletons when the run started — and a document kept here is by construction one
537
+ // that was. So a kept document never appears in that list, and the run cannot claim to have put
538
+ // back a document it left alone. On a mixed corpus the two lines are complementary: `putBack`
539
+ // names what this run skeletonised, this note names what it kept and why.
540
+ const one = keptForBackup.length === 1;
541
+ notes.push(`${joinPhrases(keptForBackup)} ${dryRun ? 'would be kept' : one ? 'was kept' : 'were kept'} as ${one ? 'it stands' : 'they stand'} under --force: ${one ? 'it is' : 'they are'} already ${one ? 'a skeleton' : 'skeletons'}, and ${one ? 'its' : 'their'} .bak ${one ? 'sibling holds' : 'siblings hold'} the filled analysis an earlier forced run rescued — the engine's .bak is single-generation, so regenerating ${one ? 'it' : 'them'} would overwrite that analysis with a skeleton and leave no copy of it: restore ${one ? `${keptForBackup[0]}.bak` : 'those .bak files'} to get the analysis back, or run \`${ANALYZE_COMMAND}\` again to rebuild it`);
542
+ }
543
+ const pushExample = `${normalizeRepoPathStrict(config.pushEnvPath ?? PUSH_ENV_PATH)}${EXAMPLE_SUFFIX}`;
544
+ plan.add({
545
+ path: join(repoRoot, pushExample),
546
+ policy: 'create-if-absent',
547
+ content: render('push-notify.env.example', {
548
+ pushEnvPath: normalizeRepoPathStrict(config.pushEnvPath ?? PUSH_ENV_PATH),
549
+ }),
550
+ label: 'push-notification settings example',
551
+ });
552
+ envExamples.push(pushExample);
553
+ if (config.phases?.qa === true) {
554
+ const credentialsPath = normalizeRepoPathStrict(config.qa?.credentialsPath ?? QA_CREDENTIALS_PATH);
555
+ const qaExample = `${credentialsPath}${EXAMPLE_SUFFIX}`;
556
+ plan.add({
557
+ path: join(repoRoot, qaExample),
558
+ policy: 'create-if-absent',
559
+ content: render('qa-accounts.env.example', { credentialsPath }),
560
+ label: 'test-account credentials example',
561
+ });
562
+ envExamples.push(qaExample);
563
+ plan.add({
564
+ path: join(repoRoot, QA_SCENARIOS_PATH),
565
+ policy: 'create-if-absent',
566
+ content: render('qa_test_scenarios.md', { credentialsPath }),
567
+ label: 'QA test-scenario rules',
568
+ });
569
+ notes.push(`${QA_SCENARIOS_PATH} is a skeleton for this project's own test-scenario rules, and yours to edit from here on: fill in its banner sections, keep account-specific values in ${credentialsPath}, and a re-run will leave your copy alone`);
570
+ }
571
+ else {
572
+ notes.push('no test-account example and no test-scenario rules were written, because phases.qa is off and both belong to the interactive test phase: turn the phase on in harness.config.json and re-run init to add them');
573
+ }
574
+ const generic = written.filter((stub) => !stub.dedicated);
575
+ if (generic.length > 0) {
576
+ notes.push(`${generic.length} ${generic.length === 1 ? 'layer has' : 'layers have'} no dedicated skeleton, so the generic layer stub was written for ${joinPhrases(generic.map((stub) => stub.path))}`);
577
+ }
578
+ return {
579
+ claudeMd: CLAUDE_MD_PATH,
580
+ claudeMdBackupWouldCarryContent: claudeMdExisted && force && !keepClaudeMd,
581
+ claudeMdBackupExisted: keepClaudeMd && claudeMdBackupExisted,
582
+ stubs: written,
583
+ envExamples,
584
+ warnings,
585
+ notes,
586
+ };
587
+ }
588
+ //# sourceMappingURL=claudeContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeContext.js","sourceRoot":"","sources":["../../src/generators/claudeContext.ts"],"names":[],"mappings":"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"}