autonomous-sdlc-harness 0.4.2 → 0.6.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/dist/commands/init.js +113 -16
- package/dist/commands/init.js.map +1 -1
- package/dist/config/check.js +28 -6
- package/dist/config/check.js.map +1 -1
- package/dist/config/model.js +64 -5
- package/dist/config/model.js.map +1 -1
- package/dist/core/pluginIdentity.js +2 -0
- package/dist/core/pluginIdentity.js.map +1 -1
- package/dist/core/writer.js +10 -5
- package/dist/core/writer.js.map +1 -1
- package/dist/core/yamlScalar.js +14 -0
- package/dist/core/yamlScalar.js.map +1 -0
- package/dist/doctor/checks.js +454 -23
- package/dist/doctor/checks.js.map +1 -1
- package/dist/generators/githubWorkflows.js +125 -20
- package/dist/generators/githubWorkflows.js.map +1 -1
- package/dist/generators/repoRoot.js +17 -8
- package/dist/generators/repoRoot.js.map +1 -1
- package/dist/remote/githubActions.js +110 -7
- package/dist/remote/githubActions.js.map +1 -1
- package/dist/retrieval/pythonBackend.js +114 -0
- package/dist/retrieval/pythonBackend.js.map +1 -0
- package/dist/retrieval/setup.js +8 -0
- package/dist/retrieval/setup.js.map +1 -1
- package/package.json +1 -1
- package/templates/README.md +1 -1
- package/templates/github/workflows/harness-control.yml +184 -0
- package/templates/github/workflows/harness-resume.yml +9 -0
- package/templates/github/workflows/harness-run.yml +127 -12
- package/templates/github/workflows/harness-trigger.yml +144 -0
- package/templates/repo/gitignore +5 -0
- package/templates/scripts/README.md +1 -1
- package/templates/scripts/autonomous-watcher.sh +121 -249
- package/templates/scripts/create-worktree.sh +52 -10
- package/templates/scripts/docs-search-server.sh +88 -17
- package/templates/scripts/lib/harness-run-lib.sh +614 -14
- package/templates/scripts/remote-run.sh +3684 -144
- package/templates/scripts/scratch-run.sh +54 -73
- package/templates/state-dir/README-root.md +1 -1
- package/templates/state-dir/scratch/README.md +4 -2
- package/templates/state-dir/user_reviews/README.md +2 -2
|
@@ -9,6 +9,21 @@
|
|
|
9
9
|
# bootstrap it, then PUSH the branch so the remote has it from
|
|
10
10
|
# the first moment. This is what the watcher calls when a prompt
|
|
11
11
|
# arrives for a branch that does not exist yet.
|
|
12
|
+
# --no-bootstrap Skip the bootstrap. Alone, a variant of default mode: cut
|
|
13
|
+
# and push the new branch the same way. With `--existing`, check
|
|
14
|
+
# out the existing branch and never push. Its callers are
|
|
15
|
+
# `remote-run.sh start` (a new branch) and `remote-run.sh review`
|
|
16
|
+
# (an existing one), each of which only places and commits one
|
|
17
|
+
# file: such a copy runs nothing, so a dependency install would
|
|
18
|
+
# cost minutes and could fail the placement for a reason
|
|
19
|
+
# unrelated to the task. It installs no worktree-scoped pre-push
|
|
20
|
+
# backstop — the push a caller makes is of a branch it has
|
|
21
|
+
# already judged not protected, and every later commit goes
|
|
22
|
+
# through `commit-on-branch.sh` and `push-branch.sh`, which refuse
|
|
23
|
+
# a protected branch themselves. An existing branch's copy that a
|
|
24
|
+
# person or a local run works in still wants the bootstrap, so
|
|
25
|
+
# `--existing` alone keeps it; `--no-bootstrap` is for a copy that
|
|
26
|
+
# only places and commits one file.
|
|
12
27
|
# --existing Check out an EXISTING branch — local, or DWIM-created from
|
|
13
28
|
# `origin/<branch>` when only the remote ref exists — bootstrap
|
|
14
29
|
# it, and NEVER push. This is what the watcher calls to recreate
|
|
@@ -33,7 +48,8 @@
|
|
|
33
48
|
# probe stops doing its job. This one is a short, strictly ordered sequence in
|
|
34
49
|
# which every step is a precondition of the next: bootstrapping a half-created
|
|
35
50
|
# worktree, or pushing a branch whose dependency install failed, is worse than
|
|
36
|
-
# stopping
|
|
51
|
+
# stopping (a `--no-bootstrap` cut simply has no bootstrap step in its
|
|
52
|
+
# sequence). So a failing step aborts the script with that step's own status —
|
|
37
53
|
# and the worktree it had already created is LEFT IN PLACE for inspection,
|
|
38
54
|
# because removing a working copy is a decision this script does not get to
|
|
39
55
|
# make silently.
|
|
@@ -62,20 +78,25 @@
|
|
|
62
78
|
# is neither a descriptor duplication (`2>&1`, `>&2`, `2>&-`) nor a redirection
|
|
63
79
|
# to the literal `/dev/null`.
|
|
64
80
|
#
|
|
65
|
-
# Usage: create-worktree.sh [--existing] <branch-name> [worktree-dir]
|
|
81
|
+
# Usage: create-worktree.sh [--existing] [--no-bootstrap] <branch-name> [worktree-dir]
|
|
66
82
|
# --existing check out an existing branch instead of creating a new one
|
|
83
|
+
# --no-bootstrap skip the bootstrap: alone, create and push a new branch; with
|
|
84
|
+
# --existing, check out the existing branch and never push
|
|
67
85
|
# <branch-name> the branch to run on
|
|
68
86
|
# [worktree-dir] optional override; relative paths resolve against $PWD
|
|
69
87
|
#
|
|
70
88
|
# Exit map a caller can switch on:
|
|
71
89
|
#
|
|
72
|
-
# 0 the worktree is ready (and, in default mode
|
|
90
|
+
# 0 the worktree is ready (and, in default mode or under `--no-bootstrap`
|
|
91
|
+
# without `--existing`, the branch was pushed)
|
|
73
92
|
# 1 usage error / the library or the configuration could not be read
|
|
74
93
|
# 2 refusal — nothing was created: `--existing` and the branch is nowhere;
|
|
75
94
|
# the branch is already checked out in another working copy (which is
|
|
76
95
|
# named); or default mode with no `origin` remote, or no
|
|
77
96
|
# `origin/<default branch>` to branch from
|
|
78
|
-
# 4 the working copy was created but could not be bootstrapped
|
|
97
|
+
# 4 the working copy was created but could not be bootstrapped (never under
|
|
98
|
+
# `--no-bootstrap`, with or without `--existing`, which resolves no
|
|
99
|
+
# bootstrap) — it has no
|
|
79
100
|
# dependency install and no pre-push backstop, is LEFT IN PLACE for
|
|
80
101
|
# inspection, and in default mode the branch was NOT pushed, because this
|
|
81
102
|
# exit precedes the push step. In default mode the local
|
|
@@ -104,6 +125,13 @@
|
|
|
104
125
|
# new branch bash "$d/scripts/create-worktree.sh" feat/x
|
|
105
126
|
# -> "$w/demo-feat-x" on feat/x, bootstrapped, and `git -C "$b"
|
|
106
127
|
# branch` now lists feat/x
|
|
128
|
+
# no-bootstrap bash "$d/scripts/create-worktree.sh" --no-bootstrap feat/q
|
|
129
|
+
# -> "$w/demo-feat-q" on feat/q, no deps.marker, and
|
|
130
|
+
# `git -C "$b" branch` lists feat/q
|
|
131
|
+
# existing, no bootstrap git -C "$d" worktree remove "$w/demo-feat-q"
|
|
132
|
+
# git -C "$d" branch -D feat/q
|
|
133
|
+
# bash "$d/scripts/create-worktree.sh" --existing --no-bootstrap feat/q
|
|
134
|
+
# -> "$w/demo-feat-q" on feat/q, no deps.marker, "$b" UNCHANGED
|
|
107
135
|
# already there bash "$d/scripts/create-worktree.sh" --existing feat/x
|
|
108
136
|
# -> exit 2 naming "$w/demo-feat-x"; nothing created
|
|
109
137
|
# recreate git -C "$d" worktree remove "$w/demo-feat-x"
|
|
@@ -150,15 +178,18 @@ fi
|
|
|
150
178
|
. "$hr_lib"
|
|
151
179
|
|
|
152
180
|
usage() {
|
|
153
|
-
echo " usage: create-worktree.sh [--existing] <branch-name> [worktree-dir]" >&2
|
|
181
|
+
echo " usage: create-worktree.sh [--existing] [--no-bootstrap] <branch-name> [worktree-dir]" >&2
|
|
154
182
|
}
|
|
155
183
|
|
|
156
184
|
existing=0
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
185
|
+
no_bootstrap=0
|
|
186
|
+
while [ "$#" -gt 0 ]; do
|
|
187
|
+
case "$1" in
|
|
188
|
+
--existing) existing=1; shift ;;
|
|
189
|
+
--no-bootstrap) no_bootstrap=1; shift ;;
|
|
190
|
+
*) break ;;
|
|
191
|
+
esac
|
|
192
|
+
done
|
|
162
193
|
if [ "$#" -lt 1 ] || [ -z "${1:-}" ]; then
|
|
163
194
|
echo "create-worktree.sh: no branch name given" >&2
|
|
164
195
|
usage
|
|
@@ -325,6 +356,17 @@ fi
|
|
|
325
356
|
# checkout's own copy is not run instead — setup-worktree.sh anchors on its own
|
|
326
357
|
# location and takes no arguments, so running it would bootstrap THIS checkout
|
|
327
358
|
# rather than the new one.
|
|
359
|
+
if [ "$no_bootstrap" -eq 1 ]; then
|
|
360
|
+
if [ "$existing" -eq 1 ]; then
|
|
361
|
+
echo "create-worktree.sh: worktree ready at $worktree_dir (not bootstrapped)"
|
|
362
|
+
echo "create-worktree.sh: branch $branch (existing branch; not pushed)"
|
|
363
|
+
else
|
|
364
|
+
git -C "$worktree_dir" push -u origin "$branch"
|
|
365
|
+
echo "create-worktree.sh: worktree ready at $worktree_dir (not bootstrapped)"
|
|
366
|
+
echo "create-worktree.sh: branch $branch (pushed to origin)"
|
|
367
|
+
fi
|
|
368
|
+
exit 0
|
|
369
|
+
fi
|
|
328
370
|
scripts_rel="$(hr_scripts_dir "$worktree_dir")" || scripts_rel=""
|
|
329
371
|
if [ -z "$scripts_rel" ]; then
|
|
330
372
|
scripts_rel="$script_dir_rel"
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# docs-search-server.sh — start the docs-retrieval MCP server for the checkout
|
|
3
|
-
# this script sits in,
|
|
4
|
-
# `docs serve`.
|
|
3
|
+
# this script sits in, on the backend `docs.retrievalBackend` selects.
|
|
5
4
|
#
|
|
6
5
|
# WHO RUNS IT. The agent runner, from the `harness-docs` entry `init` writes into
|
|
7
6
|
# `.mcp.json` when `docs.retrieval` is on — never a dispatched agent's Bash call,
|
|
@@ -9,29 +8,52 @@
|
|
|
9
8
|
# `agentInvocable: false` and the generated permission profile carries no entry
|
|
10
9
|
# for it.
|
|
11
10
|
#
|
|
12
|
-
# STDOUT BELONGS TO THE MCP TRANSPORT. Nothing here may print to stdout
|
|
13
|
-
#
|
|
14
|
-
#
|
|
11
|
+
# STDOUT BELONGS TO THE MCP TRANSPORT. Nothing here may print to stdout: a stray
|
|
12
|
+
# byte there is a malformed frame for the client. Every diagnostic goes to
|
|
13
|
+
# stderr.
|
|
15
14
|
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
15
|
+
# WHICH SERVER. Two backends, chosen by `docs.retrievalBackend` read at run
|
|
16
|
+
# time, with no fallback between them and no fallback to any other
|
|
17
|
+
# installation. The key is read ONLY WHEN `phases.docs` and `docs.retrieval` are
|
|
18
|
+
# both `true` (`hr_docs_retrieval_applies`, the shell mirror of
|
|
19
|
+
# `retrievalApplies`): `init` merges `.mcp.json` and removes nothing, so this
|
|
20
|
+
# entry outlives turning retrieval off, and with the gate closed the TypeScript
|
|
21
|
+
# runtime is `exec`ed whatever the key holds. `typescript`, or the key absent,
|
|
22
|
+
# `exec`s the machine-shared runtime's `docs serve`; `doctor`'s
|
|
23
|
+
# `retrieval-dependencies` check and `init`'s install both key on the same entry
|
|
24
|
+
# file this script tests. `python` starts the Python package's stdio server.
|
|
25
|
+
# This script checks no database and runs no `self-check`: grading the backend's
|
|
26
|
+
# prerequisites is `doctor`'s. `PATH` is settled through the library's fallback
|
|
27
|
+
# list first, because the starter is the agent runner rather than a login shell.
|
|
28
|
+
#
|
|
29
|
+
# WHY THE PYTHON BRANCH IS NOT `exec`ED. Its failure must surface as exit 3,
|
|
30
|
+
# which an `exec` could not report. It runs as a child with stdin passed
|
|
31
|
+
# explicitly, and a `TERM` or an `INT` the launcher receives is passed on to it
|
|
32
|
+
# as `TERM`, the signal the server stops on: bash starts a background child with
|
|
33
|
+
# `SIGINT` ignored when job control is off, and Python installs no handler over
|
|
34
|
+
# an ignored `SIGINT`, so an `INT` passed on as itself would never arrive.
|
|
22
35
|
#
|
|
23
36
|
# MIRRORS — a change to any owner below is an edit here too:
|
|
24
37
|
# `retrieval/runtime` and `node_modules/autonomous-sdlc-harness/dist/cli.js`
|
|
25
38
|
# mirror `RETRIEVAL_CACHE_DIRNAME`, `RETRIEVAL_RUNTIME_DIRNAME` and
|
|
26
39
|
# `RUNTIME_CLI_RELATIVE` in `cli/src/retrieval/runtime.ts`;
|
|
27
|
-
# `hr_cache_dir` mirrors `machineCacheDir()` in `cli/src/machine/paths.ts
|
|
40
|
+
# `hr_cache_dir` mirrors `machineCacheDir()` in `cli/src/machine/paths.ts`;
|
|
41
|
+
# `harness-docs-retrieval`, `serve-mcp`, `HARNESS_DOCS_RETRIEVAL_DATABASE_URL`,
|
|
42
|
+
# the default connection string and exit 3 mirror `PYTHON_RETRIEVAL_COMMAND`,
|
|
43
|
+
# `PYTHON_SERVE_SUB_COMMAND`, `PYTHON_DATABASE_URL_VARIABLE`,
|
|
44
|
+
# `PYTHON_DEFAULT_DATABASE_URL` and `PYTHON_BACKEND_UNAVAILABLE_EXIT` in
|
|
45
|
+
# `cli/src/retrieval/pythonBackend.ts`.
|
|
28
46
|
#
|
|
29
47
|
# Exit contract:
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
#
|
|
48
|
+
# 0 the Python backend exited 0
|
|
49
|
+
# 1 no repository at this script's location; `docs.retrievalBackend`
|
|
50
|
+
# outside the enum; or, on the TypeScript backend, no runtime entry at
|
|
51
|
+
# the resolved path or no cache directory to resolve it under; stderr
|
|
52
|
+
# names which
|
|
53
|
+
# 3 the Python backend is selected but cannot serve: its command does not
|
|
54
|
+
# resolve on `PATH`, or it exited non-zero; stderr names which
|
|
55
|
+
# N on the TypeScript backend, `docs serve`'s own status, through `exec`; a
|
|
56
|
+
# failure to source the library exits non-zero before that, on stderr only
|
|
35
57
|
|
|
36
58
|
set -euo pipefail
|
|
37
59
|
|
|
@@ -50,6 +72,55 @@ if ! root="$(hr_repo_root "$script_dir")"; then
|
|
|
50
72
|
exit 1
|
|
51
73
|
fi
|
|
52
74
|
|
|
75
|
+
backend=typescript
|
|
76
|
+
config_status=0
|
|
77
|
+
hr_config_load "$root" || config_status=$?
|
|
78
|
+
if [ "$config_status" -eq 2 ]; then
|
|
79
|
+
echo "docs-search-server: $root/harness.config.json could not be read, so the default backend (typescript) was taken" >&2
|
|
80
|
+
elif [ "$config_status" -eq 0 ] && hr_docs_retrieval_applies "$root"; then
|
|
81
|
+
backend_status=0
|
|
82
|
+
backend="$(hr_docs_retrieval_backend "$root")" || backend_status=$?
|
|
83
|
+
if [ "$backend_status" -ne 0 ]; then
|
|
84
|
+
echo "docs-search-server: docs.retrievalBackend in $root/harness.config.json is neither \`typescript\` nor \`python\`; set one of them, then run \`npx autonomous-sdlc-harness doctor\`" >&2
|
|
85
|
+
exit 1
|
|
86
|
+
fi
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
if [ "$backend" = python ]; then
|
|
90
|
+
if ! command -v harness-docs-retrieval >/dev/null 2>&1; then
|
|
91
|
+
echo "docs-search-server: the Python backend is selected but \`harness-docs-retrieval\` does not resolve on PATH (interpreter or package missing); see docs/retrieval.md and run \`npx autonomous-sdlc-harness doctor\`" >&2
|
|
92
|
+
exit 3
|
|
93
|
+
fi
|
|
94
|
+
if [ -z "${HARNESS_DOCS_RETRIEVAL_DATABASE_URL-}" ]; then
|
|
95
|
+
HARNESS_DOCS_RETRIEVAL_DATABASE_URL='postgresql://harness:harness@127.0.0.1:5432/docs_retrieval'
|
|
96
|
+
fi
|
|
97
|
+
export HARNESS_DOCS_RETRIEVAL_DATABASE_URL
|
|
98
|
+
|
|
99
|
+
# A background job's stdin is /dev/null unless it is passed explicitly.
|
|
100
|
+
harness-docs-retrieval serve-mcp --repo "$root" <&0 &
|
|
101
|
+
child=$!
|
|
102
|
+
trapped=0
|
|
103
|
+
trap 'trapped=1; kill -TERM "$child" 2>/dev/null || true' TERM
|
|
104
|
+
trap 'trapped=1; kill -TERM "$child" 2>/dev/null || true' INT
|
|
105
|
+
|
|
106
|
+
# A trapped signal interrupts `wait` before the child's status is collected, so wait again. 127
|
|
107
|
+
# means the first `wait` had already collected it.
|
|
108
|
+
child_status=0
|
|
109
|
+
wait "$child" || child_status=$?
|
|
110
|
+
while [ "$trapped" -eq 1 ]; do
|
|
111
|
+
trapped=0
|
|
112
|
+
again=0
|
|
113
|
+
wait "$child" 2>/dev/null || again=$?
|
|
114
|
+
[ "$again" -eq 127 ] || child_status=$again
|
|
115
|
+
done
|
|
116
|
+
|
|
117
|
+
if [ "$child_status" -eq 0 ]; then
|
|
118
|
+
exit 0
|
|
119
|
+
fi
|
|
120
|
+
echo "docs-search-server: the Python backend exited with status $child_status before or while serving; the line above (\`harness-docs-retrieval: …\`) names why; run \`npx autonomous-sdlc-harness doctor\`" >&2
|
|
121
|
+
exit 3
|
|
122
|
+
fi
|
|
123
|
+
|
|
53
124
|
if ! cache_dir="$(hr_cache_dir)"; then
|
|
54
125
|
echo "docs-search-server: neither XDG_CACHE_HOME nor HOME is set, so the retrieval runtime cannot be located" >&2
|
|
55
126
|
exit 1
|