autonomous-sdlc-harness 0.1.0 → 0.4.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.
- package/README.md +4 -3
- package/dist/cli.js +0 -0
- package/dist/commands/docs.js +220 -0
- package/dist/commands/docs.js.map +1 -0
- package/dist/commands/doctor.js +32 -11
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.js +240 -64
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/registry.js +2 -0
- package/dist/commands/registry.js.map +1 -1
- package/dist/config/check.js +36 -9
- package/dist/config/check.js.map +1 -1
- package/dist/config/model.js +43 -1
- package/dist/config/model.js.map +1 -1
- package/dist/core/git.js +29 -0
- package/dist/core/git.js.map +1 -1
- package/dist/core/layerGapRemedy.js +3 -2
- package/dist/core/layerGapRemedy.js.map +1 -1
- package/dist/core/paths.js +22 -2
- package/dist/core/paths.js.map +1 -1
- package/dist/core/pluginIdentity.js +33 -0
- package/dist/core/pluginIdentity.js.map +1 -0
- package/dist/core/prompt.js +6 -2
- package/dist/core/prompt.js.map +1 -1
- package/dist/core/report.js +9 -0
- package/dist/core/report.js.map +1 -1
- package/dist/core/writer.js +24 -5
- package/dist/core/writer.js.map +1 -1
- package/dist/detect/presets.js +35 -26
- package/dist/detect/presets.js.map +1 -1
- package/dist/detect/signals.js +13 -9
- package/dist/detect/signals.js.map +1 -1
- package/dist/doctor/checks.js +483 -38
- package/dist/doctor/checks.js.map +1 -1
- package/dist/generators/claudeContext.js +4 -5
- package/dist/generators/claudeContext.js.map +1 -1
- package/dist/generators/githubWorkflows.js +66 -0
- package/dist/generators/githubWorkflows.js.map +1 -0
- package/dist/generators/harnessConfig.js +13 -5
- package/dist/generators/harnessConfig.js.map +1 -1
- package/dist/generators/notifications.js +105 -19
- package/dist/generators/notifications.js.map +1 -1
- package/dist/generators/outerLoopScripts.js +30 -3
- package/dist/generators/outerLoopScripts.js.map +1 -1
- package/dist/generators/permissionProfile.js +152 -21
- package/dist/generators/permissionProfile.js.map +1 -1
- package/dist/generators/projectSettings.js +5 -15
- package/dist/generators/projectSettings.js.map +1 -1
- package/dist/generators/repoRoot.js +148 -25
- package/dist/generators/repoRoot.js.map +1 -1
- package/dist/generators/scripts.js +4 -1
- package/dist/generators/scripts.js.map +1 -1
- package/dist/generators/stateDir.js +9 -3
- package/dist/generators/stateDir.js.map +1 -1
- package/dist/machine/paths.js +19 -4
- package/dist/machine/paths.js.map +1 -1
- package/dist/machine/plugins.js +2 -1
- package/dist/machine/plugins.js.map +1 -1
- package/dist/remote/githubActions.js +86 -0
- package/dist/remote/githubActions.js.map +1 -0
- package/dist/retrieval/chunk.js +158 -0
- package/dist/retrieval/chunk.js.map +1 -0
- package/dist/retrieval/corpus.js +75 -0
- package/dist/retrieval/corpus.js.map +1 -0
- package/dist/retrieval/models.js +175 -0
- package/dist/retrieval/models.js.map +1 -0
- package/dist/retrieval/queryLog.js +70 -0
- package/dist/retrieval/queryLog.js.map +1 -0
- package/dist/retrieval/refresh.js +55 -0
- package/dist/retrieval/refresh.js.map +1 -0
- package/dist/retrieval/runtime.js +161 -0
- package/dist/retrieval/runtime.js.map +1 -0
- package/dist/retrieval/search.js +129 -0
- package/dist/retrieval/search.js.map +1 -0
- package/dist/retrieval/server.js +197 -0
- package/dist/retrieval/server.js.map +1 -0
- package/dist/retrieval/session.js +41 -0
- package/dist/retrieval/session.js.map +1 -0
- package/dist/retrieval/setup.js +121 -0
- package/dist/retrieval/setup.js.map +1 -0
- package/dist/retrieval/store.js +170 -0
- package/dist/retrieval/store.js.map +1 -0
- package/package.json +22 -3
- package/templates/README.md +3 -2
- package/templates/claude/CLAUDE.md +4 -4
- package/templates/claude/README.md +3 -1
- 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/claude/settings.autonomous.retrieval.json +9 -0
- package/templates/github/workflows/harness-resume.yml +124 -0
- package/templates/github/workflows/harness-run.yml +446 -0
- package/templates/repo/README.md +2 -0
- package/templates/repo/gitignore +6 -0
- package/templates/repo/gitignore.retrieval +2 -0
- package/templates/repo/mcp.retrieval.json +11 -0
- package/templates/scripts/README.md +1 -1
- package/templates/scripts/autonomous-notify.sh +10 -4
- package/templates/scripts/autonomous-watcher.sh +1445 -221
- package/templates/scripts/cleanup-merged-worktrees.sh +126 -8
- package/templates/scripts/docs-search-server.sh +64 -0
- 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 +452 -21
- package/templates/scripts/remote-run.sh +1785 -0
- package/templates/scripts/restart-watcher.sh +24 -3
- 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 +1 -1
- package/templates/state-dir/business_parity_reviews/README.md +1 -1
- package/templates/state-dir/clarification_digests/README.md +1 -1
- package/templates/state-dir/clarifications/README.md +4 -4
- 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
|
@@ -5,13 +5,14 @@ npx autonomous-sdlc-harness init # wire a repositor
|
|
|
5
5
|
npx autonomous-sdlc-harness doctor # re-check a wired one; the exit status is the contract
|
|
6
6
|
npx autonomous-sdlc-harness config list | get <key> | set <key> <value>
|
|
7
7
|
npx autonomous-sdlc-harness daemon <install|start|stop|list>
|
|
8
|
+
npx autonomous-sdlc-harness docs <index|search <query>|serve|fetch-models> # opt-in; needs docs.retrieval on
|
|
8
9
|
```
|
|
9
10
|
|
|
10
11
|
Node `>=20.11.0`. Licence Apache-2.0 — `LICENSE` and `NOTICE` ship beside this file. Every command takes `-h`, `-v`, `--dry-run`, `--force`, `--quiet` (progress narration only — results, warnings and failures still print), `--non-interactive` and `--cwd <path>`, and exits `0` (did what it was asked), `1` (a refusal or a failed check, `doctor` FAIL included) or `2` (an internal fault). What each command writes, the `init` re-run contract, the stack-detection table, the enumerated `doctor` checks and the failure modes the generated permission profile encodes are in [`docs/cli.md`](https://github.com/firu-daniel/autonomous-sdlc-harness/blob/main/docs/cli.md) — which the published tarball does not carry, so every repository link on this page is an absolute URL.
|
|
11
12
|
|
|
12
|
-
The npm package that carries the harness's **outer loop** — `init`, `doctor`, `config` and `daemon
|
|
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.
|
|
13
14
|
|
|
14
|
-
**What the
|
|
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).
|
|
15
16
|
|
|
16
17
|
Five decisions are recorded here so they are not re-litigated later:
|
|
17
18
|
|
|
@@ -21,4 +22,4 @@ Five decisions are recorded here so they are not re-litigated later:
|
|
|
21
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.
|
|
22
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.)
|
|
23
24
|
|
|
24
|
-
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 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
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command: `docs` — search the docs catalog and the conventions documents: build the index, query it,
|
|
3
|
+
* serve it over MCP, and fetch the models it runs on. Its sub-verbs are `index`, `search`, `serve` and
|
|
4
|
+
* `fetch-models`.
|
|
5
|
+
*
|
|
6
|
+
* **The rule this module exists to enforce: the sub-verb table is the one declaration of the
|
|
7
|
+
* sub-verbs.** The usage lines, the refusal naming the legal sub-verbs and the dispatch all read
|
|
8
|
+
* {@link SUB_VERBS}, so a sub-verb added there cannot be missing from any of them. Every sub-verb that
|
|
9
|
+
* reads the index opens it through `retrieval/session.ts` → `openRetrieval`, which owns the refusals
|
|
10
|
+
* that precede any load.
|
|
11
|
+
*
|
|
12
|
+
* **`--dry-run` never persists the index.** The global flag promises that nothing is written, and the
|
|
13
|
+
* only thing a sub-verb writes is the per-checkout index: `index` and `search` build it in memory, the
|
|
14
|
+
* same path as `--in-memory`, and `serve` refuses the flag before opening anything.
|
|
15
|
+
*/
|
|
16
|
+
import { requireConfig } from '../config/io.js';
|
|
17
|
+
import { EXIT, HarnessError } from '../core/errors.js';
|
|
18
|
+
import { resolveRepoRoot } from '../core/git.js';
|
|
19
|
+
import { ownManifestString } from '../core/paths.js';
|
|
20
|
+
import { DEFAULT_RESULTS, MAX_RESULTS, renderResults, SEARCH_MODES, searchDocs, } from '../retrieval/search.js';
|
|
21
|
+
import { EMBEDDING_MODEL, fetchModels, modelFilesPresent, RERANK_MODEL, RETRIEVAL_STUB_ENV, stubModelsSelected, } from '../retrieval/models.js';
|
|
22
|
+
import { retrievalModelCacheDir } from '../retrieval/runtime.js';
|
|
23
|
+
import { serveDocs } from '../retrieval/server.js';
|
|
24
|
+
import { openRetrieval } from '../retrieval/session.js';
|
|
25
|
+
const SUMMARY = 'Search the docs catalog and conventions: build the index, query it, serve it over MCP';
|
|
26
|
+
const CLI = 'npx autonomous-sdlc-harness';
|
|
27
|
+
const IN_MEMORY_FLAG = '--in-memory';
|
|
28
|
+
/** The refusal suffix every bad invocation carries. */
|
|
29
|
+
function helpHint() {
|
|
30
|
+
return `run \`${CLI} docs --help\` for the usage`;
|
|
31
|
+
}
|
|
32
|
+
/** The boolean flags `args` sets, refusing any token not in `allowed`. */
|
|
33
|
+
function parseFlags(verb, args, allowed) {
|
|
34
|
+
const set = new Set();
|
|
35
|
+
for (const token of args) {
|
|
36
|
+
if (!allowed.includes(token)) {
|
|
37
|
+
const what = token.startsWith('-') ? 'unknown option' : 'unexpected argument';
|
|
38
|
+
throw new HarnessError(`docs ${verb}: ${what} ${JSON.stringify(token)}; ${helpHint()}`);
|
|
39
|
+
}
|
|
40
|
+
set.add(token);
|
|
41
|
+
}
|
|
42
|
+
return set;
|
|
43
|
+
}
|
|
44
|
+
/** `docs index [--in-memory]`: refresh the checkout's index, or build one in memory. */
|
|
45
|
+
async function index(ctx, args) {
|
|
46
|
+
const flags = parseFlags('index', args, [IN_MEMORY_FLAG]);
|
|
47
|
+
const repoRoot = resolveRepoRoot(ctx.cwd);
|
|
48
|
+
const config = requireConfig(repoRoot);
|
|
49
|
+
const session = await openRetrieval({ repoRoot, config, inMemory: flags.has(IN_MEMORY_FLAG) || ctx.flags.dryRun });
|
|
50
|
+
try {
|
|
51
|
+
const result = await session.refresh();
|
|
52
|
+
for (const warning of result.warnings)
|
|
53
|
+
ctx.report.warn(warning);
|
|
54
|
+
ctx.report.result(`docs index: ${result.files} files, ${result.chunks} chunks; embedded ${result.embedded}, unchanged ${result.unchanged}, deleted ${result.deleted}${result.rebuilt ? '; rebuilt for a new embedder' : ''}`);
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
await session.close();
|
|
58
|
+
}
|
|
59
|
+
return EXIT.OK;
|
|
60
|
+
}
|
|
61
|
+
const K_FLAG = '--k';
|
|
62
|
+
const MODE_FLAG = '--mode';
|
|
63
|
+
const DEFAULT_MODE = 'fused-rerank';
|
|
64
|
+
/**
|
|
65
|
+
* `docs search <query> [--k <n>] [--mode <mode>]`: refresh the checkout's index, then answer the query.
|
|
66
|
+
* An abstention exits 0; it is an answer, not an error.
|
|
67
|
+
*/
|
|
68
|
+
async function search(ctx, args) {
|
|
69
|
+
const modes = SEARCH_MODES.join(', ');
|
|
70
|
+
let query;
|
|
71
|
+
let k = DEFAULT_RESULTS;
|
|
72
|
+
let mode = DEFAULT_MODE;
|
|
73
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
74
|
+
const token = args[i] ?? '';
|
|
75
|
+
if (token === K_FLAG || token === MODE_FLAG) {
|
|
76
|
+
const value = args[i + 1];
|
|
77
|
+
if (value === undefined)
|
|
78
|
+
throw new HarnessError(`docs search: ${token} needs a value; ${helpHint()}`);
|
|
79
|
+
i += 1;
|
|
80
|
+
if (token === K_FLAG) {
|
|
81
|
+
if (!/^[0-9]+$/.test(value)) {
|
|
82
|
+
throw new HarnessError(`docs search: ${K_FLAG} takes a whole number, not ${JSON.stringify(value)}; ${helpHint()}`);
|
|
83
|
+
}
|
|
84
|
+
k = Number(value);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
const found = SEARCH_MODES.find((candidate) => candidate === value);
|
|
88
|
+
if (found === undefined) {
|
|
89
|
+
throw new HarnessError(`docs search: unknown mode ${JSON.stringify(value)}; expected ${modes}; ${helpHint()}`);
|
|
90
|
+
}
|
|
91
|
+
mode = found;
|
|
92
|
+
}
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (token.startsWith('-') || query !== undefined) {
|
|
96
|
+
const what = token.startsWith('-') ? 'unknown option' : 'unexpected argument';
|
|
97
|
+
throw new HarnessError(`docs search: ${what} ${JSON.stringify(token)}; ${helpHint()}`);
|
|
98
|
+
}
|
|
99
|
+
query = token;
|
|
100
|
+
}
|
|
101
|
+
if (query === undefined || query.trim() === '') {
|
|
102
|
+
throw new HarnessError(`docs search: no query given; ${helpHint()}`);
|
|
103
|
+
}
|
|
104
|
+
const repoRoot = resolveRepoRoot(ctx.cwd);
|
|
105
|
+
const config = requireConfig(repoRoot);
|
|
106
|
+
const session = await openRetrieval({ repoRoot, config, inMemory: ctx.flags.dryRun });
|
|
107
|
+
try {
|
|
108
|
+
const refreshed = await session.refresh();
|
|
109
|
+
for (const warning of refreshed.warnings)
|
|
110
|
+
ctx.report.warn(warning);
|
|
111
|
+
const result = await searchDocs({
|
|
112
|
+
store: session.store,
|
|
113
|
+
embedder: session.embedder,
|
|
114
|
+
reranker: session.reranker,
|
|
115
|
+
query,
|
|
116
|
+
k,
|
|
117
|
+
mode,
|
|
118
|
+
});
|
|
119
|
+
ctx.report.result(renderResults(result));
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
await session.close();
|
|
123
|
+
}
|
|
124
|
+
return EXIT.OK;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* `docs serve`: the stdio MCP server, through `retrieval/server.ts` → `serveDocs`. **Nothing but the
|
|
128
|
+
* transport may write to stdout** — a stray byte corrupts the JSON-RPC stream and an agent sees a tool
|
|
129
|
+
* that never loads — so this sub-verb writes no `result` line and sends every warning to stderr
|
|
130
|
+
* through `report.warn`. A refusal before the transport starts exits non-zero with its message on
|
|
131
|
+
* stderr.
|
|
132
|
+
*/
|
|
133
|
+
async function serve(ctx, args) {
|
|
134
|
+
parseFlags('serve', args, []);
|
|
135
|
+
if (ctx.flags.dryRun) {
|
|
136
|
+
throw new HarnessError(`docs serve: --dry-run is not supported, because a server persists the index it refreshes; ${helpHint()}`);
|
|
137
|
+
}
|
|
138
|
+
const repoRoot = resolveRepoRoot(ctx.cwd);
|
|
139
|
+
const config = requireConfig(repoRoot);
|
|
140
|
+
await serveDocs({ repoRoot, config, version: ownManifestString('version'), report: ctx.report });
|
|
141
|
+
return EXIT.OK;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* `docs fetch-models`: download both models into the shared model cache. **The one command that reaches
|
|
145
|
+
* the network.** `init` runs it at setup time (`retrieval/setup.ts`), and a person may run it by hand.
|
|
146
|
+
* It refuses under {@link RETRIEVAL_STUB_ENV} before loading anything, because a stub run must never
|
|
147
|
+
* download.
|
|
148
|
+
*/
|
|
149
|
+
async function fetchModelsVerb(ctx, args) {
|
|
150
|
+
parseFlags('fetch-models', args, []);
|
|
151
|
+
if (stubModelsSelected()) {
|
|
152
|
+
throw new HarnessError(`docs fetch-models: refusing to download while ${RETRIEVAL_STUB_ENV} is set, because a stub run never downloads; unset it to fetch the real models`);
|
|
153
|
+
}
|
|
154
|
+
await fetchModels();
|
|
155
|
+
const dir = retrievalModelCacheDir();
|
|
156
|
+
const { present, missing } = modelFilesPresent(dir);
|
|
157
|
+
if (!present) {
|
|
158
|
+
throw new HarnessError(`docs fetch-models: the download finished but ${dir} is missing ${missing.join(', ')}`);
|
|
159
|
+
}
|
|
160
|
+
ctx.report.result(`docs fetch-models: ${EMBEDDING_MODEL} and ${RERANK_MODEL} cached in ${dir}`);
|
|
161
|
+
return EXIT.OK;
|
|
162
|
+
}
|
|
163
|
+
const SUB_VERBS = [
|
|
164
|
+
{
|
|
165
|
+
name: 'index',
|
|
166
|
+
synopsis: `index [${IN_MEMORY_FLAG}]`,
|
|
167
|
+
summary: `Refresh this checkout's index; ${IN_MEMORY_FLAG} builds one in memory and writes nothing`,
|
|
168
|
+
run: index,
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
name: 'search',
|
|
172
|
+
synopsis: `search <query> [${K_FLAG} <n>] [${MODE_FLAG} <${SEARCH_MODES.join('|')}>]`,
|
|
173
|
+
summary: `Refresh the index and search it; ${K_FLAG} defaults to ${DEFAULT_RESULTS} (at most ${MAX_RESULTS}), ${MODE_FLAG} to ${DEFAULT_MODE}`,
|
|
174
|
+
run: search,
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
name: 'serve',
|
|
178
|
+
synopsis: 'serve',
|
|
179
|
+
summary: 'Serve search_docs over stdio MCP; stdout carries the protocol and nothing else',
|
|
180
|
+
run: serve,
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: 'fetch-models',
|
|
184
|
+
synopsis: 'fetch-models',
|
|
185
|
+
summary: 'Download both models into the shared model cache; the one sub-verb that reaches the network',
|
|
186
|
+
run: fetchModelsVerb,
|
|
187
|
+
},
|
|
188
|
+
];
|
|
189
|
+
function usage() {
|
|
190
|
+
const width = Math.max(...SUB_VERBS.map((verb) => verb.synopsis.length));
|
|
191
|
+
return [
|
|
192
|
+
`The sub-verb is required: ${CLI} docs <${SUB_VERBS.map((verb) => verb.name).join('|')}>`,
|
|
193
|
+
'',
|
|
194
|
+
'Sub-verbs:',
|
|
195
|
+
...SUB_VERBS.map((verb) => ` ${verb.synopsis.padEnd(width)} ${verb.summary}`),
|
|
196
|
+
'',
|
|
197
|
+
'Retrieval must be on (phases.docs and docs.retrieval true) and the model cache present;',
|
|
198
|
+
'init sets both up. --dry-run builds the index in memory for index and search and writes',
|
|
199
|
+
'nothing; serve refuses it.',
|
|
200
|
+
];
|
|
201
|
+
}
|
|
202
|
+
async function run(ctx) {
|
|
203
|
+
const [name, ...args] = ctx.argv;
|
|
204
|
+
const names = SUB_VERBS.map((verb) => verb.name).join(', ');
|
|
205
|
+
if (name === undefined)
|
|
206
|
+
throw new HarnessError(`docs: no sub-verb given; expected ${names}; ${helpHint()}`);
|
|
207
|
+
const verb = SUB_VERBS.find((candidate) => candidate.name === name);
|
|
208
|
+
if (verb === undefined) {
|
|
209
|
+
const what = name.startsWith('-') ? 'unknown option' : 'unknown sub-verb';
|
|
210
|
+
throw new HarnessError(`docs: ${what} ${JSON.stringify(name)}; expected ${names}; ${helpHint()}`);
|
|
211
|
+
}
|
|
212
|
+
return verb.run(ctx, args);
|
|
213
|
+
}
|
|
214
|
+
export const DOCS_COMMAND = {
|
|
215
|
+
name: 'docs',
|
|
216
|
+
summary: SUMMARY,
|
|
217
|
+
usage: usage(),
|
|
218
|
+
run,
|
|
219
|
+
};
|
|
220
|
+
//# sourceMappingURL=docs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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,8 +38,8 @@
|
|
|
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
44
|
*/
|
|
45
45
|
import { spawnSync } from 'node:child_process';
|
|
@@ -64,20 +64,28 @@ const TEST_NOTIFICATION_FLAG = '--test-notification';
|
|
|
64
64
|
* air-gapped finds out at the first interactive-test dispatch instead. This flag asks now.
|
|
65
65
|
*/
|
|
66
66
|
const CHECK_REGISTRY_FLAG = '--check-registry';
|
|
67
|
+
/**
|
|
68
|
+
* An option this command takes of its own: it turns on the `remote-github` check's `gh` queries and
|
|
69
|
+
* changes no other check.
|
|
70
|
+
*
|
|
71
|
+
* Off by default for {@link CHECK_REGISTRY_FLAG}'s reason: a default run answers the same in CI,
|
|
72
|
+
* offline and in an `&&` chain, and asking GitHub is a network round trip per question.
|
|
73
|
+
*/
|
|
74
|
+
const CHECK_GITHUB_FLAG = '--check-github';
|
|
67
75
|
/**
|
|
68
76
|
* Every option this command takes of its own, in the order `--help` lists them.
|
|
69
77
|
*
|
|
70
78
|
* Declared as the list rather than spelled into the refusal message, so the message a mistyped flag
|
|
71
79
|
* gets names whatever the command actually accepts and cannot fall behind it.
|
|
72
80
|
*/
|
|
73
|
-
const OWN_FLAGS = Object.freeze([TEST_NOTIFICATION_FLAG, CHECK_REGISTRY_FLAG]);
|
|
81
|
+
const OWN_FLAGS = Object.freeze([TEST_NOTIFICATION_FLAG, CHECK_REGISTRY_FLAG, CHECK_GITHUB_FLAG]);
|
|
74
82
|
/**
|
|
75
83
|
* The event word the test send carries.
|
|
76
84
|
*
|
|
77
|
-
* Deliberately **not** one of the notifier's
|
|
78
|
-
* by the watcher — `completed`, `parked`, `paused`, `failed`, `launched`, `resumed
|
|
79
|
-
* from here would put a message an operator reads as a real run's
|
|
80
|
-
* ones arrive in. The script's header states that an unrecognized word is still delivered, under a
|
|
85
|
+
* Deliberately **not** one of the notifier's seven lifecycle words. That vocabulary is a contract
|
|
86
|
+
* owned by the watcher — `completed`, `parked`, `paused`, `failed`, `launched`, `resumed`,
|
|
87
|
+
* `park_loop` — and sending one from here would put a message an operator reads as a real run's
|
|
88
|
+
* outcome into the same stream real ones arrive in. The script's header states that an unrecognized word is still delivered, under a
|
|
81
89
|
* generic title, and its dispatcher's `*)` branch is where this one lands: the message reads
|
|
82
90
|
* `Run '<branch>': doctor-test.` and cannot be mistaken for a lifecycle event.
|
|
83
91
|
*/
|
|
@@ -110,10 +118,12 @@ const DOCTOR_USAGE = Object.freeze([
|
|
|
110
118
|
' autonomous-notify.sh, after the report',
|
|
111
119
|
` ${CHECK_REGISTRY_FLAG} Ask the registry whether each pinned MCP server package can be`,
|
|
112
120
|
' fetched, inside the browser-wiring check',
|
|
121
|
+
` ${CHECK_GITHUB_FLAG} Ask GitHub, through gh, whether the remote-execution setup is`,
|
|
122
|
+
' complete, inside the remote-github check',
|
|
113
123
|
'',
|
|
114
124
|
'A default run sends nothing: the notifications check reads which settings file the notifier',
|
|
115
125
|
`resolves and prints no value from it, and only ${TEST_NOTIFICATION_FLAG} delivers a message. The`,
|
|
116
|
-
`test send carries the event word ${TEST_NOTIFICATION_EVENT}, which is none of the watcher's
|
|
126
|
+
`test send carries the event word ${TEST_NOTIFICATION_EVENT}, which is none of the watcher's seven`,
|
|
117
127
|
"lifecycle words, so it cannot be read as a real run's outcome. It does not change the exit status:",
|
|
118
128
|
'a best-effort notifier that could not reach an endpoint is not a failed check. Under --dry-run it',
|
|
119
129
|
'reports the invocation it would make and sends nothing, after every refusal a real run would make.',
|
|
@@ -127,6 +137,12 @@ const DOCTOR_USAGE = Object.freeze([
|
|
|
127
137
|
'nothing — and one that cannot be reached warns. It never changes the exit status, and --dry-run',
|
|
128
138
|
'does not suppress it: a metadata read changes nothing, here or anywhere else.',
|
|
129
139
|
'',
|
|
140
|
+
`${CHECK_GITHUB_FLAG} is off by default for the same reason. With it on and execution.target`,
|
|
141
|
+
'github-actions, remote-github asks gh whether it is authenticated, whether GitHub knows',
|
|
142
|
+
'harness-run.yml and harness-resume.yml, which secret names are set (names only, never values) and',
|
|
143
|
+
'which runner HARNESS_RUNNER selects. A call that times out or cannot reach GitHub warns rather than',
|
|
144
|
+
'fails. Every call is a read, so --dry-run does not suppress it either.',
|
|
145
|
+
'',
|
|
130
146
|
'Exit status is the contract — branch on it rather than on the report text:',
|
|
131
147
|
' 0 no check failed: every check passed, or the only findings were warnings',
|
|
132
148
|
' 1 at least one check failed',
|
|
@@ -160,6 +176,7 @@ const DOCTOR_USAGE = Object.freeze([
|
|
|
160
176
|
function parseOptions(argv) {
|
|
161
177
|
let testNotification = false;
|
|
162
178
|
let checkRegistry = false;
|
|
179
|
+
let checkGithub = false;
|
|
163
180
|
for (const token of argv) {
|
|
164
181
|
if (token === TEST_NOTIFICATION_FLAG) {
|
|
165
182
|
testNotification = true;
|
|
@@ -169,11 +186,15 @@ function parseOptions(argv) {
|
|
|
169
186
|
checkRegistry = true;
|
|
170
187
|
continue;
|
|
171
188
|
}
|
|
189
|
+
if (token === CHECK_GITHUB_FLAG) {
|
|
190
|
+
checkGithub = true;
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
172
193
|
throw new HarnessError(token.startsWith('-')
|
|
173
|
-
? `doctor: unknown option ${JSON.stringify(token)} — the options doctor takes of its own are ${OWN_FLAGS.join('
|
|
194
|
+
? `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
195
|
: `doctor: unexpected argument ${JSON.stringify(token)} — doctor takes no arguments, and checks the repository containing the current directory (or --cwd)`);
|
|
175
196
|
}
|
|
176
|
-
return { testNotification, checkRegistry };
|
|
197
|
+
return { testNotification, checkRegistry, checkGithub };
|
|
177
198
|
}
|
|
178
199
|
/** `Summary: 9 pass, 3 warn, 0 fail — exit 0 (no check failed; warnings do not fail the command)`. */
|
|
179
200
|
function summaryLine(pass, warn, fail) {
|
|
@@ -300,7 +321,7 @@ function sendTestNotification(ctx, checks) {
|
|
|
300
321
|
*/
|
|
301
322
|
async function run(ctx) {
|
|
302
323
|
const options = parseOptions(ctx.argv);
|
|
303
|
-
const checks = buildCheckContext(ctx.cwd, options.checkRegistry);
|
|
324
|
+
const checks = buildCheckContext(ctx.cwd, options.checkRegistry, options.checkGithub);
|
|
304
325
|
const results = runChecks(checks);
|
|
305
326
|
const width = Math.max(...results.map((result) => result.id.length));
|
|
306
327
|
ctx.report.step(`checks (${ctx.cwd})`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,SAAS,GAGV,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAG5F,8FAA8F;AAC9F,MAAM,OAAO,GACX,6GAA6G,CAAC;AAEhH,4EAA4E;AAC5E,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB,uEAAuE;AACvE,MAAM,sBAAsB,GAAG,qBAAqB,CAAC;AAErD;;;;;;;;GAQG;AACH,MAAM,mBAAmB,GAAG,kBAAkB,CAAC;AAE/C;;;;;GAKG;AACH,MAAM,SAAS,GAAsB,MAAM,CAAC,MAAM,CAAC,CAAC,sBAAsB,EAAE,mBAAmB,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|