autonomous-sdlc-harness 0.2.0 → 0.4.1
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.
- package/README.md +2 -2
- package/dist/cli.js +0 -0
- package/dist/commands/docs.js +2 -1
- package/dist/commands/docs.js.map +1 -1
- package/dist/commands/doctor.js +56 -6
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.js +107 -20
- package/dist/commands/init.js.map +1 -1
- package/dist/config/check.js +11 -4
- package/dist/config/check.js.map +1 -1
- package/dist/config/model.js +25 -0
- package/dist/config/model.js.map +1 -1
- package/dist/core/defaultBranchPush.js +26 -0
- package/dist/core/defaultBranchPush.js.map +1 -0
- package/dist/core/git.js +61 -0
- package/dist/core/git.js.map +1 -1
- package/dist/core/paths.js +22 -2
- package/dist/core/paths.js.map +1 -1
- package/dist/core/prompt.js +6 -2
- package/dist/core/prompt.js.map +1 -1
- package/dist/core/writer.js +2 -0
- package/dist/core/writer.js.map +1 -1
- package/dist/doctor/checks.js +482 -73
- package/dist/doctor/checks.js.map +1 -1
- package/dist/generators/githubWorkflows.js +66 -0
- package/dist/generators/githubWorkflows.js.map +1 -0
- package/dist/generators/notifications.js +105 -19
- package/dist/generators/notifications.js.map +1 -1
- package/dist/generators/outerLoopScripts.js +17 -3
- package/dist/generators/outerLoopScripts.js.map +1 -1
- package/dist/generators/permissionProfile.js +141 -21
- package/dist/generators/permissionProfile.js.map +1 -1
- package/dist/generators/projectSettings.js +2 -1
- package/dist/generators/projectSettings.js.map +1 -1
- package/dist/generators/repoRoot.js +23 -4
- package/dist/generators/repoRoot.js.map +1 -1
- package/dist/generators/stateDir.js +9 -3
- package/dist/generators/stateDir.js.map +1 -1
- package/dist/machine/paths.js +4 -1
- package/dist/machine/paths.js.map +1 -1
- package/dist/remote/githubActions.js +86 -0
- package/dist/remote/githubActions.js.map +1 -0
- package/dist/retrieval/queryLog.js +6 -4
- package/dist/retrieval/queryLog.js.map +1 -1
- package/dist/retrieval/runtime.js +46 -33
- package/dist/retrieval/runtime.js.map +1 -1
- package/dist/retrieval/search.js +21 -10
- package/dist/retrieval/search.js.map +1 -1
- package/dist/retrieval/server.js +1 -1
- package/dist/retrieval/setup.js +2 -1
- package/dist/retrieval/setup.js.map +1 -1
- package/package.json +2 -2
- package/templates/README.md +3 -2
- package/templates/claude/context/conventions.md +1 -1
- package/templates/claude/context/layer.md +1 -1
- package/templates/claude/push-notify.env.example +7 -2
- package/templates/claude/settings.autonomous.json +1 -1
- package/templates/github/workflows/harness-resume.yml +124 -0
- package/templates/github/workflows/harness-run.yml +446 -0
- package/templates/repo/gitignore +11 -1
- package/templates/scripts/README.md +1 -1
- package/templates/scripts/autonomous-watcher.sh +1296 -169
- package/templates/scripts/flow-walker.sh +629 -0
- package/templates/scripts/flows/task_plan_writing.graph.json +192 -0
- package/templates/scripts/lib/flow-walker-gates.sh +165 -0
- package/templates/scripts/lib/harness-run-lib.sh +595 -18
- package/templates/scripts/remote-run.sh +1784 -0
- package/templates/scripts/restart-watcher.sh +21 -1
- package/templates/scripts/run-test-suite.sh +182 -0
- package/templates/scripts/scratch-run.sh +2 -1
- package/templates/state-dir/README-root.md +1 -1
- package/templates/state-dir/autonomous_logs/README.md +2 -2
- package/templates/state-dir/improvement_observations/README.md +2 -0
- package/templates/state-dir/scratch/README.md +1 -1
- package/templates/state-dir/test_fix_plan_reviews/README.md +9 -0
- package/templates/state-dir/test_fix_plans/README.md +9 -0
- package/templates/state-dir/test_fix_point_reviews/README.md +9 -0
- package/templates/state-dir/test_run_logs/README.md +11 -0
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Node `>=20.11.0`. Licence Apache-2.0 — `LICENSE` and `NOTICE` ship beside this
|
|
|
12
12
|
|
|
13
13
|
The npm package that carries the harness's **outer loop** — `init`, `doctor`, `config` and `daemon` — and `docs`, the opt-in docs-retrieval search over the docs catalog and conventions documents. The process assets those runs execute — agents, slash commands, hooks, instructions and samples — are not here; they ship as the sibling `plugin/` Claude Code plugin. This package exists at all because a plugin cannot write a repository's `settings.json`, and getting that permission profile right is the highest-friction part of adoption. Installing that plugin is a step of its own, separate from installing this package — see the harness root [`README.md`](https://github.com/firu-daniel/autonomous-sdlc-harness/blob/main/README.md) `## Quick start` for the lettered sequence an adopter runs.
|
|
14
14
|
|
|
15
|
-
**What the five subcommands do.** `init` wires an adopting repository in one deterministic pass: it detects the stack, then writes the configuration, the wrapper scripts, the run-artifact tree, the conventions stubs, the permission profile, the committable project settings, the repository-root files and the pre-push hook — creating what is absent and keeping what the adopter has edited. `doctor` re-checks a wired repository — git and worktrees, that the configured default branch still resolves, the daemon backend, the configuration, the state directory, the ignore rules, which notification settings file the notifier resolves, whether this checkout is in the machine-local registry of installed daemons, the plugin wiring
|
|
15
|
+
**What the five subcommands do.** `init` wires an adopting repository in one deterministic pass: it detects the stack, then writes the configuration, the wrapper scripts, the run-artifact tree, the conventions stubs, the permission profile, the committable project settings, the repository-root files and the pre-push hook — creating what is absent and keeping what the adopter has edited — plus, when `execution.target` is `github-actions`, the two remote-execution workflows `.github/workflows/harness-run.yml` and `.github/workflows/harness-resume.yml`. `doctor` re-checks a wired repository — git and worktrees, that the configured default branch still resolves, the daemon backend, the configuration, the state directory, the ignore rules, which notification settings file the notifier resolves, whether this checkout is in the machine-local registry of installed daemons, the plugin wiring, the permission profile and, offline, the remote-execution setup, which it also asks GitHub about under `--check-github` — and reports every finding, with the exit status as the contract; the remote-execution design is in [`docs/remote-execution.md`](https://github.com/firu-daniel/autonomous-sdlc-harness/blob/main/docs/remote-execution.md); [`docs/cli.md`](https://github.com/firu-daniel/autonomous-sdlc-harness/blob/main/docs/cli.md) §7 is the enumerated list and the severity each check carries. `config` reads and updates one dotted key of `harness.config.json` at a time, refusing a key the file may not carry and backing the file up before each write. `daemon` installs, starts and stops this repository's run daemon on whichever service manager the host has, and lists the repositories on this machine one has been installed for. `docs` builds and queries a local search index over `docs.root` and the conventions documents, and serves it over stdio MCP as `search_docs` when `docs.retrieval` is on. It is **off by default** and opt-in: measured once against agent navigation on a real 1,960-chunk catalog, its verdict was **withdrawn**, and it is kept opt-in by maintainer decision — [`docs/retrieval-eval-results.md`](https://github.com/firu-daniel/autonomous-sdlc-harness/blob/main/docs/retrieval-eval-results.md) → *The decision, applied to the real catalog*; the verb is in [`docs/cli.md`](https://github.com/firu-daniel/autonomous-sdlc-harness/blob/main/docs/cli.md) and the design in [`docs/retrieval.md`](https://github.com/firu-daniel/autonomous-sdlc-harness/blob/main/docs/retrieval.md).
|
|
16
16
|
|
|
17
17
|
Five decisions are recorded here so they are not re-litigated later:
|
|
18
18
|
|
|
@@ -22,4 +22,4 @@ Five decisions are recorded here so they are not re-litigated later:
|
|
|
22
22
|
- **Never shell out to `rm -rf`.** A user-level `permissions.deny` rule on it is realistic, deny is evaluated before any allow and cannot be overridden, so a teardown implemented as a shelled-out `rm -rf` is silently blocked with no useful error. Use Node's in-process `fs.rm` for every removal.
|
|
23
23
|
- **The run watcher's path is derived from `scriptsDir`, not a config key of its own.** `init` writes the watcher into the configured scripts directory with the rest of the outer-loop set, so `daemon` resolves it as `<repoRoot>/<scriptsDir>/autonomous-watcher.sh`: `scriptsDir` is the one key that moves it, and a second key naming the same location could only ever disagree with it. That also keeps the unit's `ExecStart` inside the repository its `WorkingDirectory` names — a CLI run through `npx` lives in a cache directory that can be evicted under a long-running service. `--watcher` overrides the resolution for developing against a watcher that is not the written one. (This decision replaces an earlier package-relative one; `scripts/README.md` records why.)
|
|
24
24
|
|
|
25
|
-
TypeScript in `src/` compiles with `tsc` to `dist/`, which is what `bin` points at; `templates/` holds generator templates and is deliberately outside the compiler's `include`. Two families live there: the **wrapper** scripts `init` renders from a detected command line, and the **outer-loop** shell assets — the run watcher, its restart wrapper, the notifier and its stream formatter, the commit / push / branch-refresh / worktree / cleanup wrappers, the docs-retrieval server launcher and the library they share — which `init` copies verbatim into the same `scriptsDir` because each reads `harness.config.json` at run time. `scripts/` keeps only the daemon unit templates the `daemon` subcommand renders into the account's home directory; it is likewise uncompiled and carried into the published tarball by `files` alongside `templates/` (`scripts/README.md` records why the outer-loop set is not there). A watcher that is missing — deleted, or left behind when `scriptsDir` moved — is a `doctor` warning and a `daemon install` refusal, repaired by re-running `init`.
|
|
25
|
+
TypeScript in `src/` compiles with `tsc` to `dist/`, which is what `bin` points at; `templates/` holds generator templates and is deliberately outside the compiler's `include`. Two script families live there: the **wrapper** scripts `init` renders from a detected command line, and the **outer-loop** shell assets — the run watcher, its restart wrapper, the notifier and its stream formatter, the commit / push / branch-refresh / worktree / cleanup wrappers, the scratch runner, the remote-run client (`remote-run.sh`, which sends a remote run's dispatch, pause, warm-up and stop to GitHub and syncs its state back on demand), the flow walker (`flow-walker.sh`) and its gate library (`lib/flow-walker-gates.sh`), the test-suite runner (`run-test-suite.sh`), the docs-retrieval server launcher and the library they share — which `init` copies verbatim into the same `scriptsDir` because each reads `harness.config.json` at run time, with the planning flow's graph beside them under `flows/`. `templates/github/` holds the two workflows, `harness-run.yml` and `harness-resume.yml`, which `init` writes under `.github/workflows/` only when remote execution is on (`execution.target` is `github-actions`). `scripts/` keeps only the daemon unit templates the `daemon` subcommand renders into the account's home directory; it is likewise uncompiled and carried into the published tarball by `files` alongside `templates/` (`scripts/README.md` records why the outer-loop set is not there). A watcher that is missing — deleted, or left behind when `scriptsDir` moved — is a `doctor` warning and a `daemon install` refusal, repaired by re-running `init`.
|
package/dist/cli.js
CHANGED
|
File without changes
|
package/dist/commands/docs.js
CHANGED
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
import { requireConfig } from '../config/io.js';
|
|
17
17
|
import { EXIT, HarnessError } from '../core/errors.js';
|
|
18
18
|
import { resolveRepoRoot } from '../core/git.js';
|
|
19
|
+
import { ownManifestString } from '../core/paths.js';
|
|
19
20
|
import { DEFAULT_RESULTS, MAX_RESULTS, renderResults, SEARCH_MODES, searchDocs, } from '../retrieval/search.js';
|
|
20
21
|
import { EMBEDDING_MODEL, fetchModels, modelFilesPresent, RERANK_MODEL, RETRIEVAL_STUB_ENV, stubModelsSelected, } from '../retrieval/models.js';
|
|
21
|
-
import {
|
|
22
|
+
import { retrievalModelCacheDir } from '../retrieval/runtime.js';
|
|
22
23
|
import { serveDocs } from '../retrieval/server.js';
|
|
23
24
|
import { openRetrieval } from '../retrieval/session.js';
|
|
24
25
|
const SUMMARY = 'Search the docs catalog and conventions: build the index, query it, serve it over MCP';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../../src/commands/docs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EACL,eAAe,EACf,WAAW,EACX,aAAa,EACb,YAAY,EACZ,UAAU,GAEX,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../../src/commands/docs.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -38,9 +38,11 @@
|
|
|
38
38
|
* - **A default run sends nothing.** The `notifications` check is a pure read of whichever settings
|
|
39
39
|
* file the notifier resolves; everything here with network reach is behind a flag —
|
|
40
40
|
* {@link TEST_NOTIFICATION_FLAG}, a delivery, which no default run and no `--dry-run` run makes,
|
|
41
|
-
* and {@link CHECK_REGISTRY_FLAG}
|
|
42
|
-
* suppressed by `--dry-run`. A POST fired by every `doctor` — in CI, from an `&&` chain, from the
|
|
41
|
+
* and {@link CHECK_REGISTRY_FLAG} and {@link CHECK_GITHUB_FLAG}, reads that change nothing anywhere
|
|
42
|
+
* and so are not suppressed by `--dry-run`. A POST fired by every `doctor` — in CI, from an `&&` chain, from the
|
|
43
43
|
* run daemon before it starts a run — would cost the command every property above.
|
|
44
|
+
* {@link REMOTE_JOB_FLAG} reaches no network either: it changes three profile checks' grades, and what `plugin-permissions` grades,
|
|
45
|
+
* and nothing else.
|
|
44
46
|
*/
|
|
45
47
|
import { spawnSync } from 'node:child_process';
|
|
46
48
|
import { existsSync } from 'node:fs';
|
|
@@ -64,13 +66,35 @@ const TEST_NOTIFICATION_FLAG = '--test-notification';
|
|
|
64
66
|
* air-gapped finds out at the first interactive-test dispatch instead. This flag asks now.
|
|
65
67
|
*/
|
|
66
68
|
const CHECK_REGISTRY_FLAG = '--check-registry';
|
|
69
|
+
/**
|
|
70
|
+
* An option this command takes of its own: it turns on the `remote-github` check's `gh` queries and
|
|
71
|
+
* changes no other check.
|
|
72
|
+
*
|
|
73
|
+
* Off by default for {@link CHECK_REGISTRY_FLAG}'s reason: a default run answers the same in CI,
|
|
74
|
+
* offline and in an `&&` chain, and asking GitHub is a network round trip per question.
|
|
75
|
+
*/
|
|
76
|
+
const CHECK_GITHUB_FLAG = '--check-github';
|
|
77
|
+
/**
|
|
78
|
+
* An option this command takes of its own: it grades the permission profile for a remote job, where
|
|
79
|
+
* `profile-paths`, `profile-tracked` and `plugin-permissions` fail instead of warning and the
|
|
80
|
+
* profile's `additionalDirectories` must carry every plugin root.
|
|
81
|
+
*
|
|
82
|
+
* A flag rather than a probe of the job's environment, so an operator's own shell cannot trip it by
|
|
83
|
+
* inheriting a variable; the remote workflow's preflight passes it.
|
|
84
|
+
*/
|
|
85
|
+
const REMOTE_JOB_FLAG = '--remote-job';
|
|
67
86
|
/**
|
|
68
87
|
* Every option this command takes of its own, in the order `--help` lists them.
|
|
69
88
|
*
|
|
70
89
|
* Declared as the list rather than spelled into the refusal message, so the message a mistyped flag
|
|
71
90
|
* gets names whatever the command actually accepts and cannot fall behind it.
|
|
72
91
|
*/
|
|
73
|
-
const OWN_FLAGS = Object.freeze([
|
|
92
|
+
const OWN_FLAGS = Object.freeze([
|
|
93
|
+
TEST_NOTIFICATION_FLAG,
|
|
94
|
+
CHECK_REGISTRY_FLAG,
|
|
95
|
+
CHECK_GITHUB_FLAG,
|
|
96
|
+
REMOTE_JOB_FLAG,
|
|
97
|
+
]);
|
|
74
98
|
/**
|
|
75
99
|
* The event word the test send carries.
|
|
76
100
|
*
|
|
@@ -110,6 +134,10 @@ const DOCTOR_USAGE = Object.freeze([
|
|
|
110
134
|
' autonomous-notify.sh, after the report',
|
|
111
135
|
` ${CHECK_REGISTRY_FLAG} Ask the registry whether each pinned MCP server package can be`,
|
|
112
136
|
' fetched, inside the browser-wiring check',
|
|
137
|
+
` ${CHECK_GITHUB_FLAG} Ask GitHub, through gh, whether the remote-execution setup is`,
|
|
138
|
+
' complete, inside the remote-github check',
|
|
139
|
+
` ${REMOTE_JOB_FLAG} Grade the permission profile for a remote job, where an unusable one`,
|
|
140
|
+
' fails rather than warns',
|
|
113
141
|
'',
|
|
114
142
|
'A default run sends nothing: the notifications check reads which settings file the notifier',
|
|
115
143
|
`resolves and prints no value from it, and only ${TEST_NOTIFICATION_FLAG} delivers a message. The`,
|
|
@@ -127,6 +155,18 @@ const DOCTOR_USAGE = Object.freeze([
|
|
|
127
155
|
'nothing — and one that cannot be reached warns. It never changes the exit status, and --dry-run',
|
|
128
156
|
'does not suppress it: a metadata read changes nothing, here or anywhere else.',
|
|
129
157
|
'',
|
|
158
|
+
`${CHECK_GITHUB_FLAG} is off by default for the same reason. With it on and execution.target`,
|
|
159
|
+
'github-actions, remote-github asks gh whether it is authenticated, whether GitHub knows',
|
|
160
|
+
'harness-run.yml and harness-resume.yml, which secret names are set (names only, never values) and',
|
|
161
|
+
'which runner HARNESS_RUNNER selects. A call that times out or cannot reach GitHub warns rather than',
|
|
162
|
+
'fails. Every call is a read, so --dry-run does not suppress it either.',
|
|
163
|
+
'',
|
|
164
|
+
`${REMOTE_JOB_FLAG} turns three warnings into failures: profile-paths, when no rule in the profile`,
|
|
165
|
+
'covers this checkout; profile-tracked, when the profile is committed at HEAD; and plugin-permissions,',
|
|
166
|
+
'when an entry a plugin root needs is missing or no plugin root resolves. It also requires every plugin',
|
|
167
|
+
'root in permissions.additionalDirectories. The remote workflow passes it, so its preflight stops before',
|
|
168
|
+
'a session that would park. It reaches no network.',
|
|
169
|
+
'',
|
|
130
170
|
'Exit status is the contract — branch on it rather than on the report text:',
|
|
131
171
|
' 0 no check failed: every check passed, or the only findings were warnings',
|
|
132
172
|
' 1 at least one check failed',
|
|
@@ -160,6 +200,8 @@ const DOCTOR_USAGE = Object.freeze([
|
|
|
160
200
|
function parseOptions(argv) {
|
|
161
201
|
let testNotification = false;
|
|
162
202
|
let checkRegistry = false;
|
|
203
|
+
let checkGithub = false;
|
|
204
|
+
let remoteJob = false;
|
|
163
205
|
for (const token of argv) {
|
|
164
206
|
if (token === TEST_NOTIFICATION_FLAG) {
|
|
165
207
|
testNotification = true;
|
|
@@ -169,11 +211,19 @@ function parseOptions(argv) {
|
|
|
169
211
|
checkRegistry = true;
|
|
170
212
|
continue;
|
|
171
213
|
}
|
|
214
|
+
if (token === CHECK_GITHUB_FLAG) {
|
|
215
|
+
checkGithub = true;
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (token === REMOTE_JOB_FLAG) {
|
|
219
|
+
remoteJob = true;
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
172
222
|
throw new HarnessError(token.startsWith('-')
|
|
173
|
-
? `doctor: unknown option ${JSON.stringify(token)} — the options doctor takes of its own are ${OWN_FLAGS.join('
|
|
223
|
+
? `doctor: unknown option ${JSON.stringify(token)} — the options doctor takes of its own are ${OWN_FLAGS.join(', ')}; run \`npx autonomous-sdlc-harness doctor --help\` for them and for the global options it accepts`
|
|
174
224
|
: `doctor: unexpected argument ${JSON.stringify(token)} — doctor takes no arguments, and checks the repository containing the current directory (or --cwd)`);
|
|
175
225
|
}
|
|
176
|
-
return { testNotification, checkRegistry };
|
|
226
|
+
return { testNotification, checkRegistry, checkGithub, remoteJob };
|
|
177
227
|
}
|
|
178
228
|
/** `Summary: 9 pass, 3 warn, 0 fail — exit 0 (no check failed; warnings do not fail the command)`. */
|
|
179
229
|
function summaryLine(pass, warn, fail) {
|
|
@@ -300,7 +350,7 @@ function sendTestNotification(ctx, checks) {
|
|
|
300
350
|
*/
|
|
301
351
|
async function run(ctx) {
|
|
302
352
|
const options = parseOptions(ctx.argv);
|
|
303
|
-
const checks = buildCheckContext(ctx.cwd, options.checkRegistry);
|
|
353
|
+
const checks = buildCheckContext(ctx.cwd, options.checkRegistry, options.checkGithub, options.remoteJob);
|
|
304
354
|
const results = runChecks(checks);
|
|
305
355
|
const width = Math.max(...results.map((result) => result.id.length));
|
|
306
356
|
ctx.report.step(`checks (${ctx.cwd})`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/init.js
CHANGED
|
@@ -92,6 +92,7 @@ import { join, relative, resolve } from 'node:path';
|
|
|
92
92
|
import { formatProblem } from '../config/check.js';
|
|
93
93
|
import { configExists, loadConfig } from '../config/io.js';
|
|
94
94
|
import { answersNone, asQaDriver, browserWiringApplies, CONFIG_FILENAME, DEFAULTS, isPlaceholder, qaDriverChoices, retrievalApplies, STATE_DIR_DOT_PATTERN, } from '../config/model.js';
|
|
95
|
+
import { defaultBranchPushCommand, defaultBranchPushReason, WORKFLOW_SCOPE_COMMAND, WORKFLOW_SCOPE_REASON, } from '../core/defaultBranchPush.js';
|
|
95
96
|
import { EXIT, HarnessError } from '../core/errors.js';
|
|
96
97
|
import { commitAll, hasCommits, initRepository, probeRepoRoot } from '../core/git.js';
|
|
97
98
|
import { readJsonFile } from '../core/json.js';
|
|
@@ -100,7 +101,7 @@ import { layerGapRemedy, recordedVerdictClause } from '../core/layerGapRemedy.js
|
|
|
100
101
|
import { nameList } from '../core/nameList.js';
|
|
101
102
|
import { insideRepo, packageRoot } from '../core/paths.js';
|
|
102
103
|
import { ANALYZE_COMMAND } from '../core/pluginIdentity.js';
|
|
103
|
-
import { askLine, askYesNo, canPrompt } from '../core/prompt.js';
|
|
104
|
+
import { askLine, askYesNo, canPrompt, REPROMPT_LIMIT } from '../core/prompt.js';
|
|
104
105
|
import { normalizeRepoDir, normalizeRepoPathStrict } from '../core/repoPaths.js';
|
|
105
106
|
import { WritePlan } from '../core/writer.js';
|
|
106
107
|
import { findNestedApplicationDir } from '../detect/nestedApplication.js';
|
|
@@ -108,14 +109,16 @@ import { buildPreset, commandSourceClaim, searchedRoots, SHARED_CONVENTIONS_PATH
|
|
|
108
109
|
import { detectPreset, parsePresetName, FLAT_FALLBACK_SIGNAL_ID, FORCED_SIGNAL_ID, } from '../detect/signals.js';
|
|
109
110
|
import { writeClaudeContext, CLAUDE_MD_PATH, RESERVED_ANALYZE_TARGETS, SETUP_PENDING_OPEN, isUntouchedSkeletonText, } from '../generators/claudeContext.js';
|
|
110
111
|
import { pointHooksPath, writeGitHooks } from '../generators/githooks.js';
|
|
112
|
+
import { writeGithubWorkflows } from '../generators/githubWorkflows.js';
|
|
111
113
|
import { writeHarnessConfig } from '../generators/harnessConfig.js';
|
|
112
|
-
import { writeNotifications,
|
|
114
|
+
import { writeNotifications, PUSH_DESTINATION_FORMS, PUSH_DESTINATION_PLACEHOLDER, resolvePushDestination, UNRECOGNISED_DESTINATION_NOTE, } from '../generators/notifications.js';
|
|
113
115
|
import { writeOuterLoopScripts } from '../generators/outerLoopScripts.js';
|
|
114
|
-
import { writePermissionProfile } from '../generators/permissionProfile.js';
|
|
116
|
+
import { PLUGIN_ROOT_ENTRIES_FLAG, pluginRootEntriesNote, writePermissionProfile, } from '../generators/permissionProfile.js';
|
|
115
117
|
import { writeProjectSettings, MARKETPLACE_FLAG, MARKETPLACE_NAME, MARKETPLACES_KEY, SETTINGS_PATH, SLUG_SHAPE, } from '../generators/projectSettings.js';
|
|
116
118
|
import { writeRepoRootFiles, MCP_PATH } from '../generators/repoRoot.js';
|
|
117
119
|
import { configKeyPath, configuredCommand, wrapperCommandLine, wrapperPath, writeWrapperScripts, WRAPPER_SCRIPTS, } from '../generators/scripts.js';
|
|
118
120
|
import { writeStateDir } from '../generators/stateDir.js';
|
|
121
|
+
import { API_KEY_SECRET, GIT_TOKEN_SECRET, OAUTH_TOKEN_SECRET, PUSH_URL_SECRET, RUNNER_VARIABLE, } from '../remote/githubActions.js';
|
|
119
122
|
import { setUpRetrieval } from '../retrieval/setup.js';
|
|
120
123
|
/** The command's one-line summary, in the usage block and at the head of its own `--help`. */
|
|
121
124
|
const SUMMARY = 'Wire a repository: config, scripts, state tree, permission profile, project settings, conventions stubs';
|
|
@@ -163,6 +166,8 @@ const DAEMON_INSTALL_COMMAND = `${CLI} daemon install`;
|
|
|
163
166
|
* `browserWiringApplies` holds (`doctor/checks.ts`'s browser-wiring check, `commands/doctor.ts`).
|
|
164
167
|
*/
|
|
165
168
|
const DOCTOR_CHECK_REGISTRY_COMMAND = `${DOCTOR_COMMAND} --check-registry`;
|
|
169
|
+
/** The online check of GitHub-side setup, named last in the remote-execution block ({@link reportGithubSteps}). */
|
|
170
|
+
const DOCTOR_CHECK_GITHUB_COMMAND = `${DOCTOR_COMMAND} --check-github`;
|
|
166
171
|
/**
|
|
167
172
|
* How `.mcp.json` launches those servers, as the sentence names it.
|
|
168
173
|
*
|
|
@@ -296,8 +301,9 @@ function initOptions(rows, ..._rowsMissingFor) {
|
|
|
296
301
|
* then the two that decide what is detected, then the values written into the config, then the three
|
|
297
302
|
* phase toggles with their own inputs beside them, then the onboarding slug, then the pair that
|
|
298
303
|
* answers the offer to analyze this repository — which decides the wording the generated
|
|
299
|
-
* always-loaded file carries —
|
|
300
|
-
* unattended run finishes, which is the one pair that writes nothing into the repository at all
|
|
304
|
+
* always-loaded file carries — then the pair that decides whether this account gets told when an
|
|
305
|
+
* unattended run finishes, which is the one pair that writes nothing into the repository at all, and
|
|
306
|
+
* last the switch that adds this machine's plugin-root entries to a freshly generated profile.
|
|
301
307
|
*
|
|
302
308
|
* The first two sit together, and ahead of everything else, because they are the rows whose subject
|
|
303
309
|
* is the **shape of the run** rather than a value in the generated file: one settles what `init` is
|
|
@@ -452,8 +458,14 @@ const INIT_OPTIONS = initOptions([
|
|
|
452
458
|
key: 'pushUrl',
|
|
453
459
|
flag: PUSH_URL_FLAG,
|
|
454
460
|
kind: 'value',
|
|
455
|
-
placeholder:
|
|
456
|
-
summary: '
|
|
461
|
+
placeholder: PUSH_DESTINATION_PLACEHOLDER,
|
|
462
|
+
summary: 'Where notifications are posted: an ntfy topic name, or the full http:// or https:// URL of any endpoint that accepts a POST (with --notifications)',
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
key: 'pluginRootEntries',
|
|
466
|
+
flag: PLUGIN_ROOT_ENTRIES_FLAG,
|
|
467
|
+
kind: 'switch',
|
|
468
|
+
summary: "Include this machine's plugin-root permission entries when the profile is generated (for a remote job)",
|
|
457
469
|
},
|
|
458
470
|
]);
|
|
459
471
|
/**
|
|
@@ -631,6 +643,13 @@ function parseInitFlags(argv) {
|
|
|
631
643
|
const typed = switches.get('docsRetrieval') ?? DOCS_RETRIEVAL_FLAG;
|
|
632
644
|
throw new HarnessError(`init: ${typed} needs --docs: retrieval searches the documentation corpus the docs phase maintains, so it is legal only with that phase on`);
|
|
633
645
|
}
|
|
646
|
+
// Checked here for the reason `qaDriver` is, whether or not --notifications was given: a bad value
|
|
647
|
+
// must not cost an adopter a repository this run created. The value is withheld from the message,
|
|
648
|
+
// unlike {@link parseQaDriver}'s, because a push destination is a credential and stderr is logged.
|
|
649
|
+
const pushUrl = values.get('pushUrl');
|
|
650
|
+
if (pushUrl !== undefined && resolvePushDestination(pushUrl).kind === 'unrecognised') {
|
|
651
|
+
throw new HarnessError(`init: ${PUSH_URL_FLAG} takes ${PUSH_DESTINATION_FORMS}; the value given is neither, so nothing was written. It is not repeated here, because a push destination is a credential — check it and pass it again`);
|
|
652
|
+
}
|
|
634
653
|
return {
|
|
635
654
|
...Object.fromEntries([...values]),
|
|
636
655
|
...(qaDriver === undefined ? {} : { qaDriver: parseQaDriver(qaDriver) }),
|
|
@@ -643,6 +662,7 @@ function parseInitFlags(argv) {
|
|
|
643
662
|
docs: switches.has('docs'),
|
|
644
663
|
docsRetrieval: switches.has('docsRetrieval'),
|
|
645
664
|
parity: switches.has('parity'),
|
|
665
|
+
pluginRootEntries: switches.has('pluginRootEntries'),
|
|
646
666
|
};
|
|
647
667
|
}
|
|
648
668
|
/** The `name` of a JSON manifest, or `undefined` when there is no readable one with a name. */
|
|
@@ -1114,14 +1134,15 @@ function resolveAnalyzeOffer(ctx, flags, repoRoot, config) {
|
|
|
1114
1134
|
*
|
|
1115
1135
|
* The two questions are asked in order and the second only inside the first's yes, because an
|
|
1116
1136
|
* endpoint is meaningless without the opt-in and the opt-in writes nothing without an endpoint. The
|
|
1117
|
-
* endpoint question carries no default
|
|
1118
|
-
*
|
|
1119
|
-
* machine-local file would shadow a repository-side one that already has values
|
|
1120
|
-
* (`generators/notifications.ts`, choice 1)
|
|
1137
|
+
* endpoint question carries no default, and {@link askPushDestination} ends in one of three outcomes:
|
|
1138
|
+
* `undefined`, which routes the run to the generator's guided-setup note rather than to a file —
|
|
1139
|
+
* writing an empty machine-local file would shadow a repository-side one that already has values
|
|
1140
|
+
* (`generators/notifications.ts`, choice 1); a recognised destination, passed on as typed; or, after
|
|
1141
|
+
* the re-asks run out, the last unrecognised answer, on which the generator writes nothing and warns.
|
|
1121
1142
|
*
|
|
1122
1143
|
* A `--push-url` passed **without** the opt-in is left in place rather than dropped here: the
|
|
1123
1144
|
* generator owns what that means and warns about it, as it owns every other line about the artifact
|
|
1124
|
-
* it writes.
|
|
1145
|
+
* it writes. The flag always wins over asking.
|
|
1125
1146
|
*/
|
|
1126
1147
|
function resolveNotifications(ctx, flags) {
|
|
1127
1148
|
const promptCtx = { flags: ctx.flags, report: ctx.report };
|
|
@@ -1132,15 +1153,27 @@ function resolveNotifications(ctx, flags) {
|
|
|
1132
1153
|
flag: NOTIFICATIONS_FLAG,
|
|
1133
1154
|
flagHint: 'to set them up without being asked',
|
|
1134
1155
|
}, promptCtx);
|
|
1135
|
-
const pushUrl = flags.pushUrl ??
|
|
1136
|
-
(enabled
|
|
1137
|
-
? askLine({
|
|
1138
|
-
question: `Where should notifications be posted? (any endpoint that accepts a POST, e.g. ${GUIDED_ENDPOINT_EXAMPLE})`,
|
|
1139
|
-
flag: PUSH_URL_FLAG,
|
|
1140
|
-
}, promptCtx)
|
|
1141
|
-
: undefined);
|
|
1156
|
+
const pushUrl = flags.pushUrl ?? (enabled ? askPushDestination(promptCtx) : undefined);
|
|
1142
1157
|
return pushUrl === undefined ? { enabled } : { enabled, pushUrl };
|
|
1143
1158
|
}
|
|
1159
|
+
/**
|
|
1160
|
+
* Ask for the push destination, re-asking an unrecognised answer up to `REPROMPT_LIMIT` times. Loops
|
|
1161
|
+
* over `askLine` rather than reading the terminal, so `core/prompt.ts` stays the one way to ask.
|
|
1162
|
+
* Returns `undefined` for no answer, a recognised answer as typed, or the last unrecognised one.
|
|
1163
|
+
*/
|
|
1164
|
+
function askPushDestination(promptCtx) {
|
|
1165
|
+
let answer;
|
|
1166
|
+
for (let attempt = 0; attempt <= REPROMPT_LIMIT; attempt += 1) {
|
|
1167
|
+
answer = askLine({
|
|
1168
|
+
question: `Where should notifications be posted? Type ${PUSH_DESTINATION_FORMS}.`,
|
|
1169
|
+
flag: PUSH_URL_FLAG,
|
|
1170
|
+
}, promptCtx);
|
|
1171
|
+
if (answer === undefined || resolvePushDestination(answer).kind !== 'unrecognised')
|
|
1172
|
+
return answer;
|
|
1173
|
+
promptCtx.report.info(UNRECOGNISED_DESTINATION_NOTE);
|
|
1174
|
+
}
|
|
1175
|
+
return answer;
|
|
1176
|
+
}
|
|
1144
1177
|
/** What detection concluded, as one line the summary can carry. */
|
|
1145
1178
|
function detectionLine(detection) {
|
|
1146
1179
|
if (detection.matchedSignal === FORCED_SIGNAL_ID) {
|
|
@@ -1722,6 +1755,9 @@ async function run(ctx) {
|
|
|
1722
1755
|
// exist (`generators/outerLoopScripts.ts`).
|
|
1723
1756
|
const outerLoop = writeOuterLoopScripts({ repoRoot, config: effective, plan });
|
|
1724
1757
|
notes.push(...outerLoop.notes);
|
|
1758
|
+
// After the scripts, which the workflows run, and before the permission profile. Enqueues nothing
|
|
1759
|
+
// unless `execution.target` is `github-actions` (`generators/githubWorkflows.ts`).
|
|
1760
|
+
const workflows = writeGithubWorkflows({ repoRoot, config: effective, plan });
|
|
1725
1761
|
const state = writeStateDir({ repoRoot, config: effective, plan });
|
|
1726
1762
|
notes.push(...state.notes);
|
|
1727
1763
|
// The third of the four questions this run puts, and settled here because its answer is an
|
|
@@ -1766,6 +1802,7 @@ async function run(ctx) {
|
|
|
1766
1802
|
// The run's `--dry-run`, which changes that report's tense and nothing else — the same contract
|
|
1767
1803
|
// the project-file generator above keeps.
|
|
1768
1804
|
dryRun: ctx.flags.dryRun,
|
|
1805
|
+
pluginRootEntries: flags.pluginRootEntries === true,
|
|
1769
1806
|
});
|
|
1770
1807
|
warnings.push(...permissions.warnings);
|
|
1771
1808
|
notes.push(...permissions.notes);
|
|
@@ -1801,7 +1838,11 @@ async function run(ctx) {
|
|
|
1801
1838
|
warnings.push(...hooks.warnings);
|
|
1802
1839
|
notes.push(...hooks.notes);
|
|
1803
1840
|
ctx.report.step(ctx.flags.dryRun ? 'files (dry run — nothing is written)' : 'files');
|
|
1804
|
-
plan.apply({ repoRoot, report: ctx.report, dryRun: ctx.flags.dryRun, force: ctx.flags.force });
|
|
1841
|
+
const applied = plan.apply({ repoRoot, report: ctx.report, dryRun: ctx.flags.dryRun, force: ctx.flags.force });
|
|
1842
|
+
const profileWrite = applied.find((result) => result.path === permissions.path);
|
|
1843
|
+
const pluginRootNote = profileWrite === undefined ? undefined : pluginRootEntriesNote(permissions.pluginRootEntries, profileWrite.effect);
|
|
1844
|
+
if (pluginRootNote !== undefined)
|
|
1845
|
+
notes.push(pluginRootNote);
|
|
1805
1846
|
// After the plan, deliberately: this is the one git-configuration write, and pointing
|
|
1806
1847
|
// `core.hooksPath` at a directory whose hook has not landed yet would enable nothing.
|
|
1807
1848
|
const hooksPath = pointHooksPath({ repoRoot, githooksDir: hooks.githooksDir, dryRun: ctx.flags.dryRun });
|
|
@@ -1835,8 +1876,54 @@ async function run(ctx) {
|
|
|
1835
1876
|
// browser wiring at all. Taken from the one predicate the two generators that write that wiring
|
|
1836
1877
|
// read, never re-spelled here (`config/model.ts`).
|
|
1837
1878
|
browserWiringApplies(effective));
|
|
1879
|
+
// Only the workflows this run created or replaced: a kept one is the adopter's already, and telling
|
|
1880
|
+
// them to commit it again is false on every unforced re-run and in every remote job's `init`.
|
|
1881
|
+
const freshWorkflows = workflows.workflows
|
|
1882
|
+
.filter(({ absolute }) => {
|
|
1883
|
+
const result = applied.find((r) => r.path === absolute);
|
|
1884
|
+
return result !== undefined && result.effect !== 'kept';
|
|
1885
|
+
})
|
|
1886
|
+
.map(({ repoPath }) => repoPath);
|
|
1887
|
+
if (freshWorkflows.length > 0)
|
|
1888
|
+
reportGithubSteps(ctx, effective.defaultBranch, ctx.flags.dryRun, freshWorkflows);
|
|
1838
1889
|
return EXIT.OK;
|
|
1839
1890
|
}
|
|
1891
|
+
/**
|
|
1892
|
+
* The GitHub-side steps only the adopter can take, printed when this run created or replaced at least
|
|
1893
|
+
* one of the two workflows; `workflowPaths` names those, repo-relative.
|
|
1894
|
+
*
|
|
1895
|
+
* Commands stand on their own lines so each can be pasted. The push comes first because GitHub
|
|
1896
|
+
* dispatches a `workflow_dispatch` workflow only once it exists on the default branch. It skips the
|
|
1897
|
+
* hook because the `pre-push` hook this run wired refuses every push to the default branch, and the
|
|
1898
|
+
* `workflow`-scope step precedes it because a `gh` token without that scope cannot push a workflow
|
|
1899
|
+
* file over HTTPS. Both commands and both reasons are `core/defaultBranchPush.ts`'s, spelled nowhere here.
|
|
1900
|
+
*/
|
|
1901
|
+
function reportGithubSteps(ctx, defaultBranch, dryRun, workflowPaths) {
|
|
1902
|
+
const wrote = dryRun ? 'would write' : 'wrote';
|
|
1903
|
+
const command = (line) => ctx.report.info(` ${line}`);
|
|
1904
|
+
ctx.report.step('remote execution');
|
|
1905
|
+
ctx.report.info(`1. This run ${wrote} ${workflowPaths.join(' and ')}. Commit and push ${workflowPaths.length === 1 ? 'it' : 'both'} to GitHub's default branch (assumed \`${defaultBranch}\` below) — a workflow_dispatch workflow can be dispatched only once it exists there. ${WORKFLOW_SCOPE_REASON} ${defaultBranchPushReason(defaultBranch)}`);
|
|
1906
|
+
command(`git add ${workflowPaths.join(' ')}`);
|
|
1907
|
+
command('git commit -m "Add the harness workflows"');
|
|
1908
|
+
command(WORKFLOW_SCOPE_COMMAND);
|
|
1909
|
+
command(defaultBranchPushCommand(defaultBranch));
|
|
1910
|
+
ctx.report.info('');
|
|
1911
|
+
ctx.report.info(`2. Set one credential secret: ${OAUTH_TOKEN_SECRET} for subscription billing, or ${API_KEY_SECRET} for API billing. When both are set, billing follows ${API_KEY_SECRET}:`);
|
|
1912
|
+
command(`gh secret set ${OAUTH_TOKEN_SECRET}`);
|
|
1913
|
+
command(`gh secret set ${API_KEY_SECRET}`);
|
|
1914
|
+
ctx.report.info('');
|
|
1915
|
+
ctx.report.info(`3. Optionally set ${PUSH_URL_SECRET} to receive push notifications from the job, and ${GIT_TOKEN_SECRET} — a personal or App token — so the job's pushes trigger your own CI, which pushes made with the job's built-in token never do:`);
|
|
1916
|
+
command(`gh secret set ${PUSH_URL_SECRET}`);
|
|
1917
|
+
command(`gh secret set ${GIT_TOKEN_SECRET}`);
|
|
1918
|
+
ctx.report.info('');
|
|
1919
|
+
ctx.report.info(`4. Optionally set the repository variable ${RUNNER_VARIABLE} to run on a self-hosted runner label instead of ubuntu-latest:`);
|
|
1920
|
+
command(`gh variable set ${RUNNER_VARIABLE} --body <runner-label>`);
|
|
1921
|
+
ctx.report.info('');
|
|
1922
|
+
ctx.report.info('5. Then verify the GitHub side:');
|
|
1923
|
+
command(DOCTOR_CHECK_GITHUB_COMMAND);
|
|
1924
|
+
ctx.report.info('');
|
|
1925
|
+
ctx.report.info('Runner choices, costs, billing and security: the harness documentation, docs/remote-execution.md — Remote execution on GitHub Actions.');
|
|
1926
|
+
}
|
|
1840
1927
|
/**
|
|
1841
1928
|
* The caveats, after the action log: the informational lines first, then the ones needing attention.
|
|
1842
1929
|
*
|