@ai-substrate/engineering-harness 0.2.0-canary.45
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/LICENSE +21 -0
- package/README.md +119 -0
- package/harness/cli/bin/harness.js +12 -0
- package/harness/cli/dist/acts/docs.d.ts +17 -0
- package/harness/cli/dist/acts/docs.js +73 -0
- package/harness/cli/dist/acts/docs.js.map +1 -0
- package/harness/cli/dist/acts/doctor.d.ts +14 -0
- package/harness/cli/dist/acts/doctor.js +43 -0
- package/harness/cli/dist/acts/doctor.js.map +1 -0
- package/harness/cli/dist/acts/help.d.ts +14 -0
- package/harness/cli/dist/acts/help.js +29 -0
- package/harness/cli/dist/acts/help.js.map +1 -0
- package/harness/cli/dist/acts/init.d.ts +22 -0
- package/harness/cli/dist/acts/init.js +61 -0
- package/harness/cli/dist/acts/init.js.map +1 -0
- package/harness/cli/dist/acts/instructions.d.ts +21 -0
- package/harness/cli/dist/acts/instructions.js +75 -0
- package/harness/cli/dist/acts/instructions.js.map +1 -0
- package/harness/cli/dist/acts/new.d.ts +19 -0
- package/harness/cli/dist/acts/new.js +66 -0
- package/harness/cli/dist/acts/new.js.map +1 -0
- package/harness/cli/dist/acts/observe.d.ts +23 -0
- package/harness/cli/dist/acts/observe.js +129 -0
- package/harness/cli/dist/acts/observe.js.map +1 -0
- package/harness/cli/dist/acts/record.d.ts +24 -0
- package/harness/cli/dist/acts/record.js +93 -0
- package/harness/cli/dist/acts/record.js.map +1 -0
- package/harness/cli/dist/acts/skills.d.ts +32 -0
- package/harness/cli/dist/acts/skills.js +256 -0
- package/harness/cli/dist/acts/skills.js.map +1 -0
- package/harness/cli/dist/acts/update.d.ts +23 -0
- package/harness/cli/dist/acts/update.js +297 -0
- package/harness/cli/dist/acts/update.js.map +1 -0
- package/harness/cli/dist/acts/verb.d.ts +27 -0
- package/harness/cli/dist/acts/verb.js +56 -0
- package/harness/cli/dist/acts/verb.js.map +1 -0
- package/harness/cli/dist/adapters/clock/clock-port.d.ts +10 -0
- package/harness/cli/dist/adapters/clock/clock-port.js +2 -0
- package/harness/cli/dist/adapters/clock/clock-port.js.map +1 -0
- package/harness/cli/dist/adapters/clock/fake-clock.d.ts +15 -0
- package/harness/cli/dist/adapters/clock/fake-clock.js +25 -0
- package/harness/cli/dist/adapters/clock/fake-clock.js.map +1 -0
- package/harness/cli/dist/adapters/clock/system-clock.d.ts +5 -0
- package/harness/cli/dist/adapters/clock/system-clock.js +7 -0
- package/harness/cli/dist/adapters/clock/system-clock.js.map +1 -0
- package/harness/cli/dist/adapters/env/env-port.d.ts +17 -0
- package/harness/cli/dist/adapters/env/env-port.js +2 -0
- package/harness/cli/dist/adapters/env/env-port.js.map +1 -0
- package/harness/cli/dist/adapters/env/fake-env.d.ts +15 -0
- package/harness/cli/dist/adapters/env/fake-env.js +24 -0
- package/harness/cli/dist/adapters/env/fake-env.js.map +1 -0
- package/harness/cli/dist/adapters/env/node-env.d.ts +6 -0
- package/harness/cli/dist/adapters/env/node-env.js +16 -0
- package/harness/cli/dist/adapters/env/node-env.js.map +1 -0
- package/harness/cli/dist/adapters/exec/exec-port.d.ts +22 -0
- package/harness/cli/dist/adapters/exec/exec-port.js +2 -0
- package/harness/cli/dist/adapters/exec/exec-port.js.map +1 -0
- package/harness/cli/dist/adapters/exec/fake-exec.d.ts +25 -0
- package/harness/cli/dist/adapters/exec/fake-exec.js +25 -0
- package/harness/cli/dist/adapters/exec/fake-exec.js.map +1 -0
- package/harness/cli/dist/adapters/exec/node-exec.d.ts +14 -0
- package/harness/cli/dist/adapters/exec/node-exec.js +38 -0
- package/harness/cli/dist/adapters/exec/node-exec.js.map +1 -0
- package/harness/cli/dist/adapters/fs/fake-fs.d.ts +22 -0
- package/harness/cli/dist/adapters/fs/fake-fs.js +63 -0
- package/harness/cli/dist/adapters/fs/fake-fs.js.map +1 -0
- package/harness/cli/dist/adapters/fs/fs-port.d.ts +20 -0
- package/harness/cli/dist/adapters/fs/fs-port.js +2 -0
- package/harness/cli/dist/adapters/fs/fs-port.js.map +1 -0
- package/harness/cli/dist/adapters/fs/node-fs.d.ts +9 -0
- package/harness/cli/dist/adapters/fs/node-fs.js +30 -0
- package/harness/cli/dist/adapters/fs/node-fs.js.map +1 -0
- package/harness/cli/dist/adapters/git/exec-git.d.ts +6 -0
- package/harness/cli/dist/adapters/git/exec-git.js +21 -0
- package/harness/cli/dist/adapters/git/exec-git.js.map +1 -0
- package/harness/cli/dist/adapters/git/fake-git.d.ts +15 -0
- package/harness/cli/dist/adapters/git/fake-git.js +20 -0
- package/harness/cli/dist/adapters/git/fake-git.js.map +1 -0
- package/harness/cli/dist/adapters/git/git-port.d.ts +12 -0
- package/harness/cli/dist/adapters/git/git-port.js +2 -0
- package/harness/cli/dist/adapters/git/git-port.js.map +1 -0
- package/harness/cli/dist/adapters/loader/fake-loader.d.ts +13 -0
- package/harness/cli/dist/adapters/loader/fake-loader.js +25 -0
- package/harness/cli/dist/adapters/loader/fake-loader.js.map +1 -0
- package/harness/cli/dist/adapters/loader/jiti-loader.d.ts +15 -0
- package/harness/cli/dist/adapters/loader/jiti-loader.js +29 -0
- package/harness/cli/dist/adapters/loader/jiti-loader.js.map +1 -0
- package/harness/cli/dist/adapters/loader/module-loader-port.d.ts +12 -0
- package/harness/cli/dist/adapters/loader/module-loader-port.js +2 -0
- package/harness/cli/dist/adapters/loader/module-loader-port.js.map +1 -0
- package/harness/cli/dist/adapters/process/fake-process.d.ts +13 -0
- package/harness/cli/dist/adapters/process/fake-process.js +21 -0
- package/harness/cli/dist/adapters/process/fake-process.js.map +1 -0
- package/harness/cli/dist/adapters/process/node-process.d.ts +6 -0
- package/harness/cli/dist/adapters/process/node-process.js +17 -0
- package/harness/cli/dist/adapters/process/node-process.js.map +1 -0
- package/harness/cli/dist/adapters/process/process-port.d.ts +13 -0
- package/harness/cli/dist/adapters/process/process-port.js +2 -0
- package/harness/cli/dist/adapters/process/process-port.js.map +1 -0
- package/harness/cli/dist/adapters/version-lookup/fake-version-lookup.d.ts +13 -0
- package/harness/cli/dist/adapters/version-lookup/fake-version-lookup.js +21 -0
- package/harness/cli/dist/adapters/version-lookup/fake-version-lookup.js.map +1 -0
- package/harness/cli/dist/adapters/version-lookup/node-version-lookup.d.ts +18 -0
- package/harness/cli/dist/adapters/version-lookup/node-version-lookup.js +51 -0
- package/harness/cli/dist/adapters/version-lookup/node-version-lookup.js.map +1 -0
- package/harness/cli/dist/adapters/version-lookup/version-lookup-port.d.ts +19 -0
- package/harness/cli/dist/adapters/version-lookup/version-lookup-port.js +2 -0
- package/harness/cli/dist/adapters/version-lookup/version-lookup-port.js.map +1 -0
- package/harness/cli/dist/app.d.ts +70 -0
- package/harness/cli/dist/app.js +221 -0
- package/harness/cli/dist/app.js.map +1 -0
- package/harness/cli/dist/index.d.ts +2 -0
- package/harness/cli/dist/index.js +26 -0
- package/harness/cli/dist/index.js.map +1 -0
- package/harness/cli/dist/output/envelope.d.ts +68 -0
- package/harness/cli/dist/output/envelope.js +56 -0
- package/harness/cli/dist/output/envelope.js.map +1 -0
- package/harness/cli/dist/output/error-codes.d.ts +57 -0
- package/harness/cli/dist/output/error-codes.js +57 -0
- package/harness/cli/dist/output/error-codes.js.map +1 -0
- package/harness/cli/dist/output/exit.d.ts +29 -0
- package/harness/cli/dist/output/exit.js +36 -0
- package/harness/cli/dist/output/exit.js.map +1 -0
- package/harness/cli/dist/output/output-port.d.ts +54 -0
- package/harness/cli/dist/output/output-port.js +55 -0
- package/harness/cli/dist/output/output-port.js.map +1 -0
- package/harness/cli/dist/output/style.d.ts +33 -0
- package/harness/cli/dist/output/style.js +68 -0
- package/harness/cli/dist/output/style.js.map +1 -0
- package/harness/cli/dist/services/config/load-config.d.ts +27 -0
- package/harness/cli/dist/services/config/load-config.js +114 -0
- package/harness/cli/dist/services/config/load-config.js.map +1 -0
- package/harness/cli/dist/services/docs/contract.d.ts +41 -0
- package/harness/cli/dist/services/docs/contract.js +14 -0
- package/harness/cli/dist/services/docs/contract.js.map +1 -0
- package/harness/cli/dist/services/docs/docs-content.d.ts +37 -0
- package/harness/cli/dist/services/docs/docs-content.js +48 -0
- package/harness/cli/dist/services/docs/docs-content.js.map +1 -0
- package/harness/cli/dist/services/docs/docs-service.d.ts +26 -0
- package/harness/cli/dist/services/docs/docs-service.js +25 -0
- package/harness/cli/dist/services/docs/docs-service.js.map +1 -0
- package/harness/cli/dist/services/doctor/doctor-service.d.ts +69 -0
- package/harness/cli/dist/services/doctor/doctor-service.js +237 -0
- package/harness/cli/dist/services/doctor/doctor-service.js.map +1 -0
- package/harness/cli/dist/services/extensions/contract.d.ts +138 -0
- package/harness/cli/dist/services/extensions/contract.js +17 -0
- package/harness/cli/dist/services/extensions/contract.js.map +1 -0
- package/harness/cli/dist/services/extensions/discovery.d.ts +53 -0
- package/harness/cli/dist/services/extensions/discovery.js +116 -0
- package/harness/cli/dist/services/extensions/discovery.js.map +1 -0
- package/harness/cli/dist/services/extensions/registry.d.ts +63 -0
- package/harness/cli/dist/services/extensions/registry.js +165 -0
- package/harness/cli/dist/services/extensions/registry.js.map +1 -0
- package/harness/cli/dist/services/extensions/verb-context.d.ts +44 -0
- package/harness/cli/dist/services/extensions/verb-context.js +97 -0
- package/harness/cli/dist/services/extensions/verb-context.js.map +1 -0
- package/harness/cli/dist/services/help/help-service.d.ts +42 -0
- package/harness/cli/dist/services/help/help-service.js +108 -0
- package/harness/cli/dist/services/help/help-service.js.map +1 -0
- package/harness/cli/dist/services/init/governance-template.d.ts +27 -0
- package/harness/cli/dist/services/init/governance-template.js +72 -0
- package/harness/cli/dist/services/init/governance-template.js.map +1 -0
- package/harness/cli/dist/services/init/init-service.d.ts +38 -0
- package/harness/cli/dist/services/init/init-service.js +44 -0
- package/harness/cli/dist/services/init/init-service.js.map +1 -0
- package/harness/cli/dist/services/instructions/core-instructions.d.ts +11 -0
- package/harness/cli/dist/services/instructions/core-instructions.js +80 -0
- package/harness/cli/dist/services/instructions/core-instructions.js.map +1 -0
- package/harness/cli/dist/services/instructions/instructions-service.d.ts +52 -0
- package/harness/cli/dist/services/instructions/instructions-service.js +53 -0
- package/harness/cli/dist/services/instructions/instructions-service.js.map +1 -0
- package/harness/cli/dist/services/observe/buffer-codec.d.ts +51 -0
- package/harness/cli/dist/services/observe/buffer-codec.js +139 -0
- package/harness/cli/dist/services/observe/buffer-codec.js.map +1 -0
- package/harness/cli/dist/services/observe/observe-service.d.ts +87 -0
- package/harness/cli/dist/services/observe/observe-service.js +221 -0
- package/harness/cli/dist/services/observe/observe-service.js.map +1 -0
- package/harness/cli/dist/services/record/contract.d.ts +32 -0
- package/harness/cli/dist/services/record/contract.js +17 -0
- package/harness/cli/dist/services/record/contract.js.map +1 -0
- package/harness/cli/dist/services/record/core-types/retro.d.ts +20 -0
- package/harness/cli/dist/services/record/core-types/retro.js +55 -0
- package/harness/cli/dist/services/record/core-types/retro.js.map +1 -0
- package/harness/cli/dist/services/record/record-service.d.ts +38 -0
- package/harness/cli/dist/services/record/record-service.js +144 -0
- package/harness/cli/dist/services/record/record-service.js.map +1 -0
- package/harness/cli/dist/services/record/registry.d.ts +46 -0
- package/harness/cli/dist/services/record/registry.js +71 -0
- package/harness/cli/dist/services/record/registry.js.map +1 -0
- package/harness/cli/dist/services/scaffold/scaffold-service.d.ts +29 -0
- package/harness/cli/dist/services/scaffold/scaffold-service.js +88 -0
- package/harness/cli/dist/services/scaffold/scaffold-service.js.map +1 -0
- package/harness/cli/dist/services/scaffold/templates.d.ts +42 -0
- package/harness/cli/dist/services/scaffold/templates.js +178 -0
- package/harness/cli/dist/services/scaffold/templates.js.map +1 -0
- package/harness/cli/dist/services/shared/posix-path.d.ts +54 -0
- package/harness/cli/dist/services/shared/posix-path.js +94 -0
- package/harness/cli/dist/services/shared/posix-path.js.map +1 -0
- package/harness/cli/dist/services/shared/temp.d.ts +24 -0
- package/harness/cli/dist/services/shared/temp.js +29 -0
- package/harness/cli/dist/services/shared/temp.js.map +1 -0
- package/harness/cli/dist/services/skills/contract.d.ts +52 -0
- package/harness/cli/dist/services/skills/contract.js +55 -0
- package/harness/cli/dist/services/skills/contract.js.map +1 -0
- package/harness/cli/dist/services/skills/skills-service.d.ts +73 -0
- package/harness/cli/dist/services/skills/skills-service.js +132 -0
- package/harness/cli/dist/services/skills/skills-service.js.map +1 -0
- package/harness/cli/dist/services/update/banner.d.ts +26 -0
- package/harness/cli/dist/services/update/banner.js +28 -0
- package/harness/cli/dist/services/update/banner.js.map +1 -0
- package/harness/cli/dist/services/update/cache.d.ts +21 -0
- package/harness/cli/dist/services/update/cache.js +61 -0
- package/harness/cli/dist/services/update/cache.js.map +1 -0
- package/harness/cli/dist/services/update/constants.d.ts +9 -0
- package/harness/cli/dist/services/update/constants.js +10 -0
- package/harness/cli/dist/services/update/constants.js.map +1 -0
- package/harness/cli/dist/services/update/install.d.ts +26 -0
- package/harness/cli/dist/services/update/install.js +78 -0
- package/harness/cli/dist/services/update/install.js.map +1 -0
- package/harness/cli/dist/services/update/semver.d.ts +16 -0
- package/harness/cli/dist/services/update/semver.js +108 -0
- package/harness/cli/dist/services/update/semver.js.map +1 -0
- package/harness/cli/dist/services/update/update-service.d.ts +46 -0
- package/harness/cli/dist/services/update/update-service.js +91 -0
- package/harness/cli/dist/services/update/update-service.js.map +1 -0
- package/harness/cli/dist/version.d.ts +8 -0
- package/harness/cli/dist/version.js +15 -0
- package/harness/cli/dist/version.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AI-Substrate
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# The Engineering Harness
|
|
2
|
+
|
|
3
|
+
An engineering harness productises the software-development loop so humans and agents can move from intent to evidence, then encode what they learn into the next run.
|
|
4
|
+
|
|
5
|
+
> **💡 Fastest start — let your agent do it.** Copy this into Claude Code / Copilot / Cursor / Codex in your repo:
|
|
6
|
+
>
|
|
7
|
+
> ```text
|
|
8
|
+
> Install the engineering harness from https://github.com/AI-Substrate/harness-engineering
|
|
9
|
+
> and adopt it in this repo: read that repo's README and skills/README.md, install the
|
|
10
|
+
> skills with npx skills, then run the eng-harness-0-adopt skill.
|
|
11
|
+
> ```
|
|
12
|
+
|
|
13
|
+
## The problem
|
|
14
|
+
|
|
15
|
+
Out of all the problems with agent-driven development, two matter most:
|
|
16
|
+
|
|
17
|
+
- **The loop closes too slowly.** The agent takes too long to get real feedback from your codebase, so it guesses, loops, or waits for a human.
|
|
18
|
+
- **The loop is hard to trust.** "Looks good to me" from a model is inference, not proof.
|
|
19
|
+
|
|
20
|
+
Underneath both: every agent session is a fresh developer onboarding into your repo — cold. If the supported path lives in scattered scripts, docs, and tribal memory, the agent has to infer it, and you pay for that inference every session, on every dev machine.
|
|
21
|
+
|
|
22
|
+
> Can a fresh human or agent move from clean start to proved product behaviour without private tribal knowledge?
|
|
23
|
+
|
|
24
|
+
If the answer is no, the engineering harness is the surface to improve.
|
|
25
|
+
|
|
26
|
+
## The loop
|
|
27
|
+
|
|
28
|
+
An engineering harness makes the **product-development loop** explicit and operable:
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
Boot -> Backpressure Check -> Do Work and Observe -> Retro and Magic Wand -> Improve
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- **Boot** proves the product can start from a known state.
|
|
35
|
+
- **Backpressure Check** is an LLM-assisted, advisory survey of the current scope against the deterministic sensors the repo exposes.
|
|
36
|
+
- **Do Work and Observe** exercises real product behaviour through supported surfaces and captures what happened in inspectable forms.
|
|
37
|
+
- **Retro and Magic Wand** turns friction, missing signals, and improvement wishes into reviewable candidates.
|
|
38
|
+
- **Improve** encodes what was learned so the next run is faster, clearer, safer, or backed by stronger signals.
|
|
39
|
+
|
|
40
|
+
The harness is not throwaway scaffolding. It is a **productised development surface**: the repo-local commands, fixtures, docs, checks, state, workflows, proof paths, and feedback loops every future feature, experiment, human, and agent passes through.
|
|
41
|
+
|
|
42
|
+
## The layers
|
|
43
|
+
|
|
44
|
+
Intent flows down. Evidence flows up. The engineering harness is the **deterministic layer** — the one your repo probably doesn't have as a first-class thing.
|
|
45
|
+
|
|
46
|
+
<!-- Diagram source: docs/media/harness-layers.mmd — re-render to docs/media/harness-layers.png
|
|
47
|
+
(image, not a ```mermaid block, so it renders on npm too — npm doesn't render Mermaid). -->
|
|
48
|
+

|
|
49
|
+
|
|
50
|
+
> "If the agent had to infer it twice, encode it here."
|
|
51
|
+
|
|
52
|
+
## The focal point
|
|
53
|
+
|
|
54
|
+
Reduce all that diffuse engineering-environment information to a single focal point — the harness CLI — and you get three things:
|
|
55
|
+
|
|
56
|
+
- **A — Discover, in one place.** `--help` instead of tribal memory. Months of team encoding shows up in help text, fetched on demand, not stuffed into agent context.
|
|
57
|
+
- **B — Prove, with backpressure.** One place deterministic verdicts live: yes or no, evidence attached. The agent can claim it's done; the harness decides whether the claim is supported.
|
|
58
|
+
- **C — Improve, on rails.** When friction shows up there's a tangible place to encode the fix — a new command, check, fixture, or sensor — and everyone on the repo, human or agent, gets it.
|
|
59
|
+
|
|
60
|
+
The agent explores it the way it explores the git CLI: it has never seen your repo, but it knows how to work a CLI. The nucleus, in one line:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
[CLI focal point + required agent use] + [deterministic backpressure]
|
|
64
|
+
+ [friction capture] + [human-selected encoding] = engineering harness nucleus
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## See the full intro
|
|
68
|
+
|
|
69
|
+
- **[The full deck](https://ai-substrate.github.io/harness-engineering/)** — readable scrolling page with commentary, or hit `P` to present it.
|
|
70
|
+
- **[The layers, one page](https://ai-substrate.github.io/harness-engineering/layers.html)** — the layer model as a self-contained visual explainer.
|
|
71
|
+
- The canonical deck source lives at [`docs/harness-presentations/intro-to-harness.md`](docs/harness-presentations/intro-to-harness.md).
|
|
72
|
+
|
|
73
|
+
## Install the skills
|
|
74
|
+
|
|
75
|
+
This repo publishes a **setup group** (`skills/eng-harness-setup/`) and an **interactive loop group** (`skills/eng-harness-loop/`), consumable by [`npx skills@latest`](https://github.com/vercel-labs/skills):
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npx skills@latest add AI-Substrate/harness-engineering/skills -a claude-code -g
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Swap `-a` for `github-copilot`, `codex`, `cursor`, `opencode`, `pi`…; drop `-g` for a project-local install; add `-s <skill-name>` for a single skill. The harness CLI also wraps this as `harness skills install` (and `harness skills update` to refresh to latest **and prune** skills this repo has renamed or removed). The full per-CLI / global-vs-local matrix is in [`INSTALL.md`](./INSTALL.md), and [`skills/README.md`](skills/README.md) explains when to run each skill.
|
|
82
|
+
|
|
83
|
+
## Engineering harness versus agent harness
|
|
84
|
+
|
|
85
|
+
This repo is about the **engineering harness**, not agent runtimes themselves. (You'll hear the practice called "harness engineering" in the wild — we lead with *engineering harness*, the artifact, so it never gets tangled with agent-harness engineering.)
|
|
86
|
+
|
|
87
|
+
| Layer | Makes operable | Examples | Proves |
|
|
88
|
+
|---|---|---|---|
|
|
89
|
+
| Engineering harness | The product and its development loop | boot commands, build/test/run flows, seed data, fixtures, health checks, diagnostics, proof bundles, retros, encoded improvements | Whether the actual product can run and prove behaviour |
|
|
90
|
+
| Agent harness | The model as a tool-using agent | tool dispatch, permissions, context, session management, orchestration, memory, execution environment | Whether an agent can attempt or coordinate work |
|
|
91
|
+
|
|
92
|
+
An agent harness can drive an engineering harness, but it cannot replace one. If the product cannot boot, run, seed, observe, and prove behaviour, the agent has nothing reliable to operate.
|
|
93
|
+
|
|
94
|
+
## Backpressure
|
|
95
|
+
|
|
96
|
+
A useful harness is also a **backpressure system**: project-side feedback that makes wrong, unsafe, incomplete, or unproven work hard to continue and easy to correct. It is how the harness says: **not yet, and here is why.**
|
|
97
|
+
|
|
98
|
+
Good backpressure includes type checks, compilers, linters, schemas, tests and proof gates; health checks, doctor commands, browser traces, logs, screenshots and database checks; structured command output with failure categories and next actions; proof artefacts that show what passed and how to rerun; and human judgement routes for decisions machines cannot make.
|
|
99
|
+
|
|
100
|
+
Prompts and checklists are useful guides, but high-risk or repeated invariants should move into the strongest practical refusal surface: a command, type, schema, fixture, validation, generated guard, diagnostic, or reviewable proof path. The goal is not ceremony — it is to stop wasting human attention on machine-checkable failure and reserve human judgement for ambiguity, product intent, tradeoffs, taste, and risk.
|
|
101
|
+
|
|
102
|
+
## What's in this repo
|
|
103
|
+
|
|
104
|
+
| Area | What it is |
|
|
105
|
+
|---|---|
|
|
106
|
+
| [`harness-foundations/`](harness-foundations/) | The thesis: [first principles](harness-foundations/first-principles.md), [patterns that work](harness-foundations/patterns-that-work.md), [directives](harness-foundations/directives.md), [the simple version](harness-foundations/simple-mode.md), and [source notes](harness-foundations/source-notes/). |
|
|
107
|
+
| [`harness/cli/`](harness/cli/) | The harness CLI core — npx-installed, upgradeable, extended per repo from `.harness/extensions/`. |
|
|
108
|
+
| [`skills/`](skills/) | The deployable skills. Adoption: [`eng-harness-0-adopt`](skills/eng-harness-setup/eng-harness-0-adopt/SKILL.md), [`eng-harness-0-harnessability-assessment`](skills/eng-harness-setup/eng-harness-0-harnessability-assessment/SKILL.md), [`eng-harness-0-add-extension`](skills/eng-harness-setup/eng-harness-0-add-extension/SKILL.md). Loop: `eng-harness-1-boot`, `eng-harness-2-backpressure`, `eng-harness-4-retro`. See [`skills/README.md`](skills/README.md). |
|
|
109
|
+
| [`docs/`](docs/) | How-to guides ([records](docs/how/record-and-record-types.md), [architecture conformance](docs/how/architecture-conformance.md), [dogfooding](docs/how/dogfood-harness-flow.md)), presentations, plans, and project rules. |
|
|
110
|
+
|
|
111
|
+
Start with [first-principles](harness-foundations/first-principles.md) for the thesis, [patterns-that-work](harness-foundations/patterns-that-work.md) for practical moves, or [directives](harness-foundations/directives.md) for the shortest operating version.
|
|
112
|
+
|
|
113
|
+
## About this repo
|
|
114
|
+
|
|
115
|
+
This is the **home of the harness product itself**: the CLI and skills are authored here and deployed into *other* repos. We also **dogfood** the harness on this repo — *editing* the CLI or skills is product development that ships to every consumer; *running* the loop skills is dogfooding this checkout. See [`AGENTS.md`](./AGENTS.md#this-repos-dual-role) and the constitution ([`docs/project-rules/constitution.md`](docs/project-rules/constitution.md) §1).
|
|
116
|
+
|
|
117
|
+
The CLI's hexagonal architecture is itself under deterministic backpressure: `harness arch-check` proves the import graph against committed dependency-cruiser rules on every PR. Two dogfood extensions exercise the harness against real, unfamiliar repos (`harness validate-harnessability`, `harness validate-harness-flow`) — collected retros are **surfaced, never auto-implemented**. See [`docs/how/dogfood-harness-flow.md`](docs/how/dogfood-harness-flow.md).
|
|
118
|
+
|
|
119
|
+
**Publication boundary**: this repo distils private and public research into general, publication-safe principles. Raw notes and private source material live outside the public surface. Public content should avoid private names, internal codewords, local paths, unreleased details, and exact private metrics unless explicitly approved.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Committed executable bin wrapper (plan 017 — T014 CI repair).
|
|
3
|
+
//
|
|
4
|
+
// `package.json#bin` used to point straight at the tsc output
|
|
5
|
+
// (`harness/cli/dist/index.js`), which tsc emits WITHOUT the execute bit and
|
|
6
|
+
// git does not track. Whether `npx --no-install harness` then works depends
|
|
7
|
+
// entirely on npm's install-time bin fixup having chmodded the build output —
|
|
8
|
+
// observed to be unreliable in CI (same npm 10.9.8, green at 08:36, "sh: 1:
|
|
9
|
+
// harness: Permission denied" at 10:12). This wrapper is tracked with git
|
|
10
|
+
// mode 100755, so the execute bit survives every checkout deterministically
|
|
11
|
+
// and the bin needs no install-time chmod at all.
|
|
12
|
+
import '../dist/index.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import { type CliIo } from '../output/output-port.js';
|
|
3
|
+
/**
|
|
4
|
+
* Register the `docs` command — the CLI front door to the bundled, curated
|
|
5
|
+
* corpus (plan 007). A CORE command (reserved, like `help`/`doctor`/`new`); it
|
|
6
|
+
* owns no business logic — the pure `DocsService` lists/resolves, and this act
|
|
7
|
+
* maps the outcome onto output + exit code:
|
|
8
|
+
*
|
|
9
|
+
* - `harness docs` → `ok` envelope `{ docs: DocEntry[] }` (human table), exit 0
|
|
10
|
+
* - `harness docs <id>` → the doc's RAW markdown to stdout (no envelope), exit 0
|
|
11
|
+
* - `harness docs <bad>` → `error` envelope `E160`, exit 1
|
|
12
|
+
*
|
|
13
|
+
* The raw-dump path mirrors minih `agent-readme`: agent-pipe-friendly, EPIPE-safe
|
|
14
|
+
* (the entrypoint swallows a broken stdout pipe). Exits route through the single
|
|
15
|
+
* exit kernel (`exitWithEnvelope`).
|
|
16
|
+
*/
|
|
17
|
+
export declare function registerDocsAct(program: Command, io: CliIo): void;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { SystemClock } from '../adapters/clock/system-clock.js';
|
|
2
|
+
import { formatError, formatOk } from '../output/envelope.js';
|
|
3
|
+
import { ErrorCodes } from '../output/error-codes.js';
|
|
4
|
+
import { emitRawAndExit, exitWithEnvelope } from '../output/exit.js';
|
|
5
|
+
import { createOutputPort } from '../output/output-port.js';
|
|
6
|
+
import { getDoc, listDocs } from '../services/docs/docs-service.js';
|
|
7
|
+
/** Human-mode listing: one block per doc (id + title, then the summary). */
|
|
8
|
+
function renderList(result) {
|
|
9
|
+
const width = Math.max(4, ...result.docs.map((doc) => doc.id.length));
|
|
10
|
+
const lines = ['harness docs — bundled documentation', ''];
|
|
11
|
+
for (const doc of result.docs) {
|
|
12
|
+
lines.push(` ${doc.id.padEnd(width)} ${doc.title}`);
|
|
13
|
+
lines.push(` ${' '.repeat(width)} ${doc.summary}`);
|
|
14
|
+
}
|
|
15
|
+
lines.push('', 'Run `harness docs <id>` to print one.');
|
|
16
|
+
return `${lines.join('\n')}\n`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Register the `docs` command — the CLI front door to the bundled, curated
|
|
20
|
+
* corpus (plan 007). A CORE command (reserved, like `help`/`doctor`/`new`); it
|
|
21
|
+
* owns no business logic — the pure `DocsService` lists/resolves, and this act
|
|
22
|
+
* maps the outcome onto output + exit code:
|
|
23
|
+
*
|
|
24
|
+
* - `harness docs` → `ok` envelope `{ docs: DocEntry[] }` (human table), exit 0
|
|
25
|
+
* - `harness docs <id>` → the doc's RAW markdown to stdout (no envelope), exit 0
|
|
26
|
+
* - `harness docs <bad>` → `error` envelope `E160`, exit 1
|
|
27
|
+
*
|
|
28
|
+
* The raw-dump path mirrors minih `agent-readme`: agent-pipe-friendly, EPIPE-safe
|
|
29
|
+
* (the entrypoint swallows a broken stdout pipe). Exits route through the single
|
|
30
|
+
* exit kernel (`exitWithEnvelope`).
|
|
31
|
+
*/
|
|
32
|
+
export function registerDocsAct(program, io) {
|
|
33
|
+
program
|
|
34
|
+
.command('docs')
|
|
35
|
+
.description('List the bundled docs, or print one by id (`harness docs <id>`)')
|
|
36
|
+
.argument('[id]', 'doc id to print verbatim (omit to list all docs)')
|
|
37
|
+
.action((id) => {
|
|
38
|
+
const clock = new SystemClock();
|
|
39
|
+
if (id === undefined) {
|
|
40
|
+
const result = listDocs();
|
|
41
|
+
const envelope = formatOk('docs', result, clock, {
|
|
42
|
+
next_action: 'Run `harness docs <id>` to print a doc.',
|
|
43
|
+
});
|
|
44
|
+
const port = io.mode === 'json'
|
|
45
|
+
? createOutputPort('json', io.writers)
|
|
46
|
+
: { emit: () => io.writers.out(renderList(result)) };
|
|
47
|
+
exitWithEnvelope(envelope, port);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const lookup = getDoc(id);
|
|
51
|
+
if ('notFound' in lookup) {
|
|
52
|
+
const envelope = formatError('docs', ErrorCodes.DOC_NOT_FOUND, `no curated doc with id "${id}"`, clock, { next_action: 'Run `harness docs` to see the available ids.' });
|
|
53
|
+
const port = io.mode === 'json'
|
|
54
|
+
? createOutputPort('json', io.writers)
|
|
55
|
+
: {
|
|
56
|
+
emit: (e) => {
|
|
57
|
+
io.writers.err(`harness docs: ${e.error?.message ?? 'failed'}\n`);
|
|
58
|
+
if (e.next_action) {
|
|
59
|
+
io.writers.err(` → ${e.next_action}\n`);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
exitWithEnvelope(envelope, port);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
// Found → write the raw markdown verbatim to stdout and let the process
|
|
67
|
+
// exit NATURALLY with 0. We deliberately do NOT route this through
|
|
68
|
+
// process.exit: a large doc piped/redirected could be truncated if the
|
|
69
|
+
// process terminates before stdout flushes (companion F002 HIGH).
|
|
70
|
+
emitRawAndExit(lookup.content, io.writers);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=docs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../../src/acts/docs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import { type CliIo } from '../output/output-port.js';
|
|
3
|
+
import type { VerbRegistry } from '../services/extensions/registry.js';
|
|
4
|
+
import type { RecordRegistry } from '../services/record/registry.js';
|
|
5
|
+
/**
|
|
6
|
+
* Register the `doctor` command — safe to run at session start. Constructs the
|
|
7
|
+
* real adapters, injects them + the verb registry + the merged record registry
|
|
8
|
+
* (provided by the composition root) into the doctor service, and renders: human
|
|
9
|
+
* mode writes the layered report to stderr + a summary to stdout; JSON mode emits
|
|
10
|
+
* the envelope to stdout. Always exits 0 (reporting succeeded). `doctor`
|
|
11
|
+
* enumerates extensions + record types (P7) without invoking any handler — and is
|
|
12
|
+
* itself a CORE command, never an extension.
|
|
13
|
+
*/
|
|
14
|
+
export declare function registerDoctorAct(program: Command, io: CliIo, registry: VerbRegistry, recordRegistry?: RecordRegistry): void;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { SystemClock } from '../adapters/clock/system-clock.js';
|
|
2
|
+
import { NodeEnv } from '../adapters/env/node-env.js';
|
|
3
|
+
import { NodeFs } from '../adapters/fs/node-fs.js';
|
|
4
|
+
import { ExecGit } from '../adapters/git/exec-git.js';
|
|
5
|
+
import { NodeProcess } from '../adapters/process/node-process.js';
|
|
6
|
+
import { exitWithEnvelope } from '../output/exit.js';
|
|
7
|
+
import { createOutputPort } from '../output/output-port.js';
|
|
8
|
+
import { buildDoctorReport, doctorEnvelope, renderDoctorText, } from '../services/doctor/doctor-service.js';
|
|
9
|
+
/**
|
|
10
|
+
* Register the `doctor` command — safe to run at session start. Constructs the
|
|
11
|
+
* real adapters, injects them + the verb registry + the merged record registry
|
|
12
|
+
* (provided by the composition root) into the doctor service, and renders: human
|
|
13
|
+
* mode writes the layered report to stderr + a summary to stdout; JSON mode emits
|
|
14
|
+
* the envelope to stdout. Always exits 0 (reporting succeeded). `doctor`
|
|
15
|
+
* enumerates extensions + record types (P7) without invoking any handler — and is
|
|
16
|
+
* itself a CORE command, never an extension.
|
|
17
|
+
*/
|
|
18
|
+
export function registerDoctorAct(program, io, registry, recordRegistry) {
|
|
19
|
+
program
|
|
20
|
+
.command('doctor')
|
|
21
|
+
.description('Report what is configured + which extensions loaded (safe at session start)')
|
|
22
|
+
.action(() => {
|
|
23
|
+
const clock = new SystemClock();
|
|
24
|
+
const report = buildDoctorReport({
|
|
25
|
+
fs: new NodeFs(),
|
|
26
|
+
proc: new NodeProcess(),
|
|
27
|
+
git: new ExecGit(),
|
|
28
|
+
env: new NodeEnv(),
|
|
29
|
+
clock,
|
|
30
|
+
}, registry, recordRegistry);
|
|
31
|
+
const envelope = doctorEnvelope(report, clock);
|
|
32
|
+
const port = io.mode === 'json'
|
|
33
|
+
? createOutputPort('json', io.writers)
|
|
34
|
+
: {
|
|
35
|
+
emit: (e) => {
|
|
36
|
+
io.writers.err(renderDoctorText(report));
|
|
37
|
+
io.writers.out(`doctor: ${e.status}\n`);
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
exitWithEnvelope(envelope, port);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/acts/doctor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAc,gBAAgB,EAAmB,MAAM,0BAA0B,CAAC;AACzF,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,gBAAgB,GACjB,MAAM,sCAAsC,CAAC;AAI9C;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAgB,EAChB,EAAS,EACT,QAAsB,EACtB,cAA+B;IAE/B,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,6EAA6E,CAAC;SAC1F,MAAM,CAAC,GAAG,EAAE;QACX,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,iBAAiB,CAC9B;YACE,EAAE,EAAE,IAAI,MAAM,EAAE;YAChB,IAAI,EAAE,IAAI,WAAW,EAAE;YACvB,GAAG,EAAE,IAAI,OAAO,EAAE;YAClB,GAAG,EAAE,IAAI,OAAO,EAAE;YAClB,KAAK;SACN,EACD,QAAQ,EACR,cAAc,CACf,CAAC;QACF,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC/C,MAAM,IAAI,GACR,EAAE,CAAC,IAAI,KAAK,MAAM;YAChB,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC;YACtC,CAAC,CAAC;gBACE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;oBACV,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;oBACzC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;gBAC1C,CAAC;aACF,CAAC;QACR,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { FsPort } from '../adapters/fs/fs-port.js';
|
|
3
|
+
import { type CliIo } from '../output/output-port.js';
|
|
4
|
+
import type { VerbRegistry } from '../services/extensions/registry.js';
|
|
5
|
+
/**
|
|
6
|
+
* Register the `help` orientation command. Human mode prints rich help text
|
|
7
|
+
* (leading with the AGENTS START HERE banner, plan 014 AC-4); JSON mode emits a
|
|
8
|
+
* stable `formatOk('help', …)` envelope whose `data.verbs[]` is the
|
|
9
|
+
* machine-readable, extension-owned command map (AC-1) with per-verb
|
|
10
|
+
* `has_instructions`. The verb registry is injected by the composition root; the
|
|
11
|
+
* `FsPort` powers the per-verb briefing existence probes at help-build time (D4);
|
|
12
|
+
* an empty registry yields an honest "no extensions installed yet" next_action.
|
|
13
|
+
*/
|
|
14
|
+
export declare function registerHelpAct(program: Command, io: CliIo, registry: VerbRegistry, fs: FsPort): void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { SystemClock } from '../adapters/clock/system-clock.js';
|
|
2
|
+
import { formatOk } from '../output/envelope.js';
|
|
3
|
+
import { exitWithEnvelope } from '../output/exit.js';
|
|
4
|
+
import { createOutputPort } from '../output/output-port.js';
|
|
5
|
+
import { buildHelp, helpEmptyHint, renderHelpText } from '../services/help/help-service.js';
|
|
6
|
+
/**
|
|
7
|
+
* Register the `help` orientation command. Human mode prints rich help text
|
|
8
|
+
* (leading with the AGENTS START HERE banner, plan 014 AC-4); JSON mode emits a
|
|
9
|
+
* stable `formatOk('help', …)` envelope whose `data.verbs[]` is the
|
|
10
|
+
* machine-readable, extension-owned command map (AC-1) with per-verb
|
|
11
|
+
* `has_instructions`. The verb registry is injected by the composition root; the
|
|
12
|
+
* `FsPort` powers the per-verb briefing existence probes at help-build time (D4);
|
|
13
|
+
* an empty registry yields an honest "no extensions installed yet" next_action.
|
|
14
|
+
*/
|
|
15
|
+
export function registerHelpAct(program, io, registry, fs) {
|
|
16
|
+
program
|
|
17
|
+
.command('help')
|
|
18
|
+
.description('Explain the harness: purpose, commands, output modes, safe first actions')
|
|
19
|
+
.action(() => {
|
|
20
|
+
const content = buildHelp(registry, fs);
|
|
21
|
+
const hint = helpEmptyHint(content);
|
|
22
|
+
const envelope = formatOk('help', content, new SystemClock(), hint ? { next_action: hint } : undefined);
|
|
23
|
+
const port = io.mode === 'json'
|
|
24
|
+
? createOutputPort('json', io.writers)
|
|
25
|
+
: { emit: () => io.writers.out(renderHelpText(content, io.useColor ?? false)) };
|
|
26
|
+
exitWithEnvelope(envelope, port);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=help.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/acts/help.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAEhE,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAc,gBAAgB,EAAmB,MAAM,0BAA0B,CAAC;AAEzF,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAE5F;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAgB,EAChB,EAAS,EACT,QAAsB,EACtB,EAAU;IAEV,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,0EAA0E,CAAC;SACvF,MAAM,CAAC,GAAG,EAAE;QACX,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACxC,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,QAAQ,CACvB,MAAM,EACN,OAAO,EACP,IAAI,WAAW,EAAE,EACjB,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CACzC,CAAC;QACF,MAAM,IAAI,GACR,EAAE,CAAC,IAAI,KAAK,MAAM;YAChB,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC;YACtC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC;QACpF,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { Clock } from '../adapters/clock/clock-port.js';
|
|
3
|
+
import type { FsPort } from '../adapters/fs/fs-port.js';
|
|
4
|
+
import type { ProcessPort } from '../adapters/process/process-port.js';
|
|
5
|
+
import { type CliIo } from '../output/output-port.js';
|
|
6
|
+
/** The ports the `init` act injects: `fs`+`proc` for the service, `clock` for the envelope timestamp. */
|
|
7
|
+
export interface InitActDeps {
|
|
8
|
+
fs: FsPort;
|
|
9
|
+
proc: ProcessPort;
|
|
10
|
+
clock: Clock;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Register the `init` command — the governance-doc INCEPTION writer. Stamps the
|
|
14
|
+
* `.harness/engineering-harness.md` skeleton (scaffold-and-seed only) and returns
|
|
15
|
+
* its path. A CORE command (reserved, like `help`/`doctor`/`new`/`record`; runs
|
|
16
|
+
* even under `--no-extensions`). Idempotent + never-clobber. It owns no business
|
|
17
|
+
* logic — the `init-service` resolves the path + writes, and this act maps the
|
|
18
|
+
* outcome onto the Envelope + exit code (created/exists → ok 0, write failure →
|
|
19
|
+
* error 1). `maturity_seed:'L0'` rides only on a fresh create — it names what
|
|
20
|
+
* THIS run seeded, so an idempotent re-run that wrote nothing omits it.
|
|
21
|
+
*/
|
|
22
|
+
export declare function registerInitAct(program: Command, io: CliIo, deps: InitActDeps): void;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { formatError, formatOk } from '../output/envelope.js';
|
|
2
|
+
import { exitWithEnvelope } from '../output/exit.js';
|
|
3
|
+
import { createOutputPort } from '../output/output-port.js';
|
|
4
|
+
import { initGovernance } from '../services/init/init-service.js';
|
|
5
|
+
/**
|
|
6
|
+
* Register the `init` command — the governance-doc INCEPTION writer. Stamps the
|
|
7
|
+
* `.harness/engineering-harness.md` skeleton (scaffold-and-seed only) and returns
|
|
8
|
+
* its path. A CORE command (reserved, like `help`/`doctor`/`new`/`record`; runs
|
|
9
|
+
* even under `--no-extensions`). Idempotent + never-clobber. It owns no business
|
|
10
|
+
* logic — the `init-service` resolves the path + writes, and this act maps the
|
|
11
|
+
* outcome onto the Envelope + exit code (created/exists → ok 0, write failure →
|
|
12
|
+
* error 1). `maturity_seed:'L0'` rides only on a fresh create — it names what
|
|
13
|
+
* THIS run seeded, so an idempotent re-run that wrote nothing omits it.
|
|
14
|
+
*/
|
|
15
|
+
export function registerInitAct(program, io, deps) {
|
|
16
|
+
program
|
|
17
|
+
.command('init')
|
|
18
|
+
.description('Seed the engineering-harness governance doc skeleton at .harness/engineering-harness.md (idempotent; returns its path)')
|
|
19
|
+
.action(() => {
|
|
20
|
+
const outcome = initGovernance(deps);
|
|
21
|
+
if (outcome.ok) {
|
|
22
|
+
const data = outcome.created
|
|
23
|
+
? { path: outcome.path, created: true, maturity_seed: 'L0' }
|
|
24
|
+
: { path: outcome.path, created: false };
|
|
25
|
+
const next_action = outcome.created
|
|
26
|
+
? 'Run eng-harness-0-adopt (or fill the TODO sections by hand) to populate boot, signals, and the injection map.'
|
|
27
|
+
: 'Already present — left untouched. Edit it directly, or run eng-harness-0-adopt to fill the injection map.';
|
|
28
|
+
const envelope = formatOk('init', data, deps.clock, {
|
|
29
|
+
evidence: [{ label: 'governance doc', path: outcome.path }],
|
|
30
|
+
next_action,
|
|
31
|
+
});
|
|
32
|
+
const port = io.mode === 'json'
|
|
33
|
+
? createOutputPort('json', io.writers)
|
|
34
|
+
: {
|
|
35
|
+
emit: () => {
|
|
36
|
+
io.writers.out(outcome.created
|
|
37
|
+
? `Created ${outcome.path}\n`
|
|
38
|
+
: `Already present: ${outcome.path} (left untouched)\n`);
|
|
39
|
+
io.writers.out('init: ok\n');
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
exitWithEnvelope(envelope, port);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const envelope = formatError('init', outcome.code, outcome.message, deps.clock, {
|
|
46
|
+
next_action: outcome.next_action,
|
|
47
|
+
});
|
|
48
|
+
const port = io.mode === 'json'
|
|
49
|
+
? createOutputPort('json', io.writers)
|
|
50
|
+
: {
|
|
51
|
+
emit: (e) => {
|
|
52
|
+
io.writers.err(`harness init: ${e.error?.message ?? e.next_action ?? 'failed'}\n`);
|
|
53
|
+
if (e.next_action)
|
|
54
|
+
io.writers.err(` → ${e.next_action}\n`);
|
|
55
|
+
io.writers.out(`init: ${e.status}\n`);
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
exitWithEnvelope(envelope, port);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/acts/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { Clock } from '../adapters/clock/clock-port.js';
|
|
3
|
+
import type { FsPort } from '../adapters/fs/fs-port.js';
|
|
4
|
+
import { type CliIo } from '../output/output-port.js';
|
|
5
|
+
import type { VerbRegistry } from '../services/extensions/registry.js';
|
|
6
|
+
/** The ports the `instructions` act injects (a subset of VerbActDeps). */
|
|
7
|
+
export interface InstructionsActDeps {
|
|
8
|
+
fs: FsPort;
|
|
9
|
+
clock: Clock;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Register the `instructions` command — the calling agent's self-briefing
|
|
13
|
+
* channel (plan 014 AC-1/2/3). A CORE act (reserved, like `help`/`doctor`):
|
|
14
|
+
* bare → the baked core agent briefing + which verbs carry their own briefing;
|
|
15
|
+
* `instructions <verb>` → that extension's `instructions.md`, read from disk at
|
|
16
|
+
* THIS invocation (D4 — edit → next call, no rebuild). Outcome → envelope per
|
|
17
|
+
* D3: ok → 0; unknown verb / missing file → unconfigured → 2 (gap semantics, no
|
|
18
|
+
* error code); exists-but-unreadable → error E145 → 1. Never a crash, never a
|
|
19
|
+
* silent empty.
|
|
20
|
+
*/
|
|
21
|
+
export declare function registerInstructionsAct(program: Command, io: CliIo, deps: InstructionsActDeps, registry: VerbRegistry): void;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { formatError, formatOk, formatUnconfigured } from '../output/envelope.js';
|
|
2
|
+
import { ErrorCodes } from '../output/error-codes.js';
|
|
3
|
+
import { exitWithEnvelope } from '../output/exit.js';
|
|
4
|
+
import { createOutputPort } from '../output/output-port.js';
|
|
5
|
+
import { buildCoreInstructions, loadVerbInstructions, } from '../services/instructions/instructions-service.js';
|
|
6
|
+
/**
|
|
7
|
+
* Register the `instructions` command — the calling agent's self-briefing
|
|
8
|
+
* channel (plan 014 AC-1/2/3). A CORE act (reserved, like `help`/`doctor`):
|
|
9
|
+
* bare → the baked core agent briefing + which verbs carry their own briefing;
|
|
10
|
+
* `instructions <verb>` → that extension's `instructions.md`, read from disk at
|
|
11
|
+
* THIS invocation (D4 — edit → next call, no rebuild). Outcome → envelope per
|
|
12
|
+
* D3: ok → 0; unknown verb / missing file → unconfigured → 2 (gap semantics, no
|
|
13
|
+
* error code); exists-but-unreadable → error E145 → 1. Never a crash, never a
|
|
14
|
+
* silent empty.
|
|
15
|
+
*/
|
|
16
|
+
export function registerInstructionsAct(program, io, deps, registry) {
|
|
17
|
+
program
|
|
18
|
+
.command('instructions')
|
|
19
|
+
.description("Print the harness's agent briefing, or one verb's instructions.md (the calling agent's role)")
|
|
20
|
+
.argument('[verb]', 'verb whose extension briefing to print; omit for the core briefing')
|
|
21
|
+
.action((verb) => {
|
|
22
|
+
if (verb === undefined) {
|
|
23
|
+
emitCore(io, deps, registry);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
emitVerb(verb, io, deps, registry);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/** Bare `harness instructions` → the baked core briefing (always available). */
|
|
30
|
+
function emitCore(io, deps, registry) {
|
|
31
|
+
const payload = buildCoreInstructions(registry, deps.fs);
|
|
32
|
+
const envelope = formatOk('instructions', payload, deps.clock, {
|
|
33
|
+
next_action: 'Run `harness instructions <verb>` to read a verb briefing before using it.',
|
|
34
|
+
});
|
|
35
|
+
const port = io.mode === 'json'
|
|
36
|
+
? createOutputPort('json', io.writers)
|
|
37
|
+
: {
|
|
38
|
+
emit: () => {
|
|
39
|
+
io.writers.out(payload.instructions);
|
|
40
|
+
io.writers.out(payload.verbs_with_instructions.length > 0
|
|
41
|
+
? `\nVerb briefings available: ${payload.verbs_with_instructions.join(', ')}\n`
|
|
42
|
+
: '\nNo verb briefings authored yet (see `harness doctor`).\n');
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
exitWithEnvelope(envelope, port);
|
|
46
|
+
}
|
|
47
|
+
/** `harness instructions <verb>` → that verb's runtime-loaded briefing, or an honest gap/fault. */
|
|
48
|
+
function emitVerb(verb, io, deps, registry) {
|
|
49
|
+
const outcome = loadVerbInstructions(verb, registry, deps.fs);
|
|
50
|
+
if (outcome.kind === 'ok') {
|
|
51
|
+
const envelope = formatOk('instructions', { verb: outcome.verb, path: outcome.path, instructions: outcome.instructions }, deps.clock, { next_action: `Apply the briefing, then run \`harness ${outcome.verb}\`.` });
|
|
52
|
+
const port = io.mode === 'json'
|
|
53
|
+
? createOutputPort('json', io.writers)
|
|
54
|
+
: { emit: () => io.writers.out(outcome.instructions) };
|
|
55
|
+
exitWithEnvelope(envelope, port);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const envelope = outcome.kind === 'unreadable'
|
|
59
|
+
? formatError('instructions', ErrorCodes.INSTRUCTIONS_UNREADABLE, `instructions.md at ${outcome.path} exists but could not be read`, deps.clock, { next_action: 'Check the path is a readable UTF-8 text file, then retry.' })
|
|
60
|
+
: outcome.kind === 'missing'
|
|
61
|
+
? formatUnconfigured('instructions', `Author ${outcome.path} — the briefing for this verb's calling agent (see \`harness instructions\` for the pattern).`, deps.clock)
|
|
62
|
+
: formatUnconfigured('instructions', `No verb '${verb}' is registered. Run \`harness help\` for the verb map.`, deps.clock);
|
|
63
|
+
const port = io.mode === 'json'
|
|
64
|
+
? createOutputPort('json', io.writers)
|
|
65
|
+
: {
|
|
66
|
+
emit: (e) => {
|
|
67
|
+
io.writers.err(`harness instructions: ${e.error?.message ?? e.next_action ?? 'failed'}\n`);
|
|
68
|
+
if (e.next_action)
|
|
69
|
+
io.writers.err(` → ${e.next_action}\n`);
|
|
70
|
+
io.writers.out(`instructions: ${e.status}\n`);
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
exitWithEnvelope(envelope, port);
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=instructions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instructions.js","sourceRoot":"","sources":["../../src/acts/instructions.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,WAAW,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACjG,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAc,gBAAgB,EAAmB,MAAM,0BAA0B,CAAC;AAEzF,OAAO,EACL,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,kDAAkD,CAAC;AAQ1D;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAAgB,EAChB,EAAS,EACT,IAAyB,EACzB,QAAsB;IAEtB,OAAO;SACJ,OAAO,CAAC,cAAc,CAAC;SACvB,WAAW,CACV,8FAA8F,CAC/F;SACA,QAAQ,CAAC,QAAQ,EAAE,oEAAoE,CAAC;SACxF,MAAM,CAAC,CAAC,IAAwB,EAAE,EAAE;QACnC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;YAC7B,OAAO;QACT,CAAC;QACD,QAAQ,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACP,CAAC;AAED,gFAAgF;AAChF,SAAS,QAAQ,CAAC,EAAS,EAAE,IAAyB,EAAE,QAAsB;IAC5E,MAAM,OAAO,GAAG,qBAAqB,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE;QAC7D,WAAW,EAAE,4EAA4E;KAC1F,CAAC,CAAC;IACH,MAAM,IAAI,GACR,EAAE,CAAC,IAAI,KAAK,MAAM;QAChB,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC;QACtC,CAAC,CAAC;YACE,IAAI,EAAE,GAAG,EAAE;gBACT,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;gBACrC,EAAE,CAAC,OAAO,CAAC,GAAG,CACZ,OAAO,CAAC,uBAAuB,CAAC,MAAM,GAAG,CAAC;oBACxC,CAAC,CAAC,+BAA+B,OAAO,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;oBAC/E,CAAC,CAAC,4DAA4D,CACjE,CAAC;YACJ,CAAC;SACF,CAAC;IACR,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACnC,CAAC;AAED,mGAAmG;AACnG,SAAS,QAAQ,CACf,IAAY,EACZ,EAAS,EACT,IAAyB,EACzB,QAAsB;IAEtB,MAAM,OAAO,GAAG,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IAE9D,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,QAAQ,CACvB,cAAc,EACd,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,EAC9E,IAAI,CAAC,KAAK,EACV,EAAE,WAAW,EAAE,0CAA0C,OAAO,CAAC,IAAI,KAAK,EAAE,CAC7E,CAAC;QACF,MAAM,IAAI,GACR,EAAE,CAAC,IAAI,KAAK,MAAM;YAChB,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC;YACtC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QAC3D,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACjC,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GACZ,OAAO,CAAC,IAAI,KAAK,YAAY;QAC3B,CAAC,CAAC,WAAW,CACT,cAAc,EACd,UAAU,CAAC,uBAAuB,EAClC,sBAAsB,OAAO,CAAC,IAAI,+BAA+B,EACjE,IAAI,CAAC,KAAK,EACV,EAAE,WAAW,EAAE,2DAA2D,EAAE,CAC7E;QACH,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS;YAC1B,CAAC,CAAC,kBAAkB,CAChB,cAAc,EACd,UAAU,OAAO,CAAC,IAAI,+FAA+F,EACrH,IAAI,CAAC,KAAK,CACX;YACH,CAAC,CAAC,kBAAkB,CAChB,cAAc,EACd,YAAY,IAAI,yDAAyD,EACzE,IAAI,CAAC,KAAK,CACX,CAAC;IAEV,MAAM,IAAI,GACR,EAAE,CAAC,IAAI,KAAK,MAAM;QAChB,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC;QACtC,CAAC,CAAC;YACE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;gBACV,EAAE,CAAC,OAAO,CAAC,GAAG,CACZ,yBAAyB,CAAC,CAAC,KAAK,EAAE,OAAO,IAAI,CAAC,CAAC,WAAW,IAAI,QAAQ,IAAI,CAC3E,CAAC;gBACF,IAAI,CAAC,CAAC,WAAW;oBAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC;gBAC5D,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;YAChD,CAAC;SACF,CAAC;IACR,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { Clock } from '../adapters/clock/clock-port.js';
|
|
3
|
+
import type { FsPort } from '../adapters/fs/fs-port.js';
|
|
4
|
+
import type { ProcessPort } from '../adapters/process/process-port.js';
|
|
5
|
+
import { type CliIo } from '../output/output-port.js';
|
|
6
|
+
/** The ports the `new` act injects into the scaffold service (a subset of VerbActDeps). */
|
|
7
|
+
export interface NewActDeps {
|
|
8
|
+
fs: FsPort;
|
|
9
|
+
proc: ProcessPort;
|
|
10
|
+
clock: Clock;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Register the `new` command — scaffolds a fresh, loadable extension into the
|
|
14
|
+
* repo's `.harness/extensions/`. A CORE command (reserved, like `help`/`doctor`,
|
|
15
|
+
* runs even in `--no-extensions` mode); it owns no business logic — the
|
|
16
|
+
* `scaffold-service` validates + writes, and this act maps the outcome onto the
|
|
17
|
+
* Envelope + exit code (ok → 0, error → 1).
|
|
18
|
+
*/
|
|
19
|
+
export declare function registerNewAct(program: Command, io: CliIo, deps: NewActDeps): void;
|