@apptoolkit/harness 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -45
- package/{dist/bun/npm/harness.js → harness.js} +3 -3
- package/package.json +9 -23
- package/{dist/bun/npm/payload → payload}/harness/runtime/harness.mjs +3 -3
- package/dist/apptoolkit-harness-1.0.0.tgz +0 -0
- package/dist/bun/apptoolkit-harness-1.0.0.tgz +0 -0
- package/dist/bun/native/README.md +0 -33
- package/dist/bun/native/harness +0 -4
- package/dist/bun/native/payload/harness/runtime/harness.mjs +0 -104
- package/dist/bun/npm/LICENSE +0 -21
- package/dist/bun/npm/README.md +0 -33
- package/dist/bun/npm/package.json +0 -23
- package/dist/bun/npm/payload/HARNESS.md +0 -21
- package/dist/bun/npm/payload/author-style/README.md +0 -56
- package/dist/bun/npm/payload/author-style/biome-core.json +0 -57
- package/dist/bun/npm/payload/author-style/biome-react.json +0 -9
- package/dist/bun/npm/payload/author-style/biome-sql.json +0 -9
- package/dist/bun/npm/payload/author-style/bun.lock +0 -37
- package/dist/bun/npm/payload/author-style/check.llm.md +0 -17
- package/dist/bun/npm/payload/author-style/check.test.llm.md +0 -17
- package/dist/bun/npm/payload/author-style/check.test.ts +0 -238
- package/dist/bun/npm/payload/author-style/check.ts +0 -181
- package/dist/bun/npm/payload/author-style/member-spacing.test.ts +0 -172
- package/dist/bun/npm/payload/author-style/member-spacing.ts +0 -106
- package/dist/bun/npm/payload/author-style/package.json +0 -18
- package/dist/bun/npm/payload/author-style/plugins/class-member-order.grit +0 -133
- package/dist/bun/npm/payload/author-style/plugins/event-handler-names.grit +0 -110
- package/dist/bun/npm/payload/author-style/plugins/explicit-arrow-body.grit +0 -15
- package/dist/bun/npm/payload/author-style/plugins/explicit-source-constructs.grit +0 -10
- package/dist/bun/npm/payload/author-style/plugins/react-arrow-body.grit +0 -85
- package/dist/bun/npm/payload/author-style/plugins/sql-style.grit +0 -125
- package/dist/bun/npm/payload/author-style/react-module.llm.md +0 -17
- package/dist/bun/npm/payload/author-style/react-module.test.ts +0 -150
- package/dist/bun/npm/payload/author-style/react-module.ts +0 -255
- package/dist/bun/npm/payload/author-style/source-policy.llm.md +0 -17
- package/dist/bun/npm/payload/author-style/source-policy.test.ts +0 -70
- package/dist/bun/npm/payload/author-style/source-policy.ts +0 -215
- package/dist/bun/npm/payload/author-style/spacing.llm.md +0 -17
- package/dist/bun/npm/payload/author-style/spacing.test.ts +0 -174
- package/dist/bun/npm/payload/author-style/spacing.ts +0 -211
- package/dist/bun/npm/payload/harness/POLICY.md +0 -33
- package/dist/bun/npm/payload/harness/PROJECT.md +0 -26
- package/dist/bun/npm/payload/harness/REVIEW.md +0 -17
- package/dist/bun/npm/payload/harness/TEMPLATES.md +0 -20
- package/dist/bun/npm/payload/harness/WORKFLOWS.md +0 -65
- package/dist/bun/npm/payload/harness/runtime/ZOD-LICENSE +0 -21
- package/dist/bun/npm/payload/harness/services/README.md +0 -26
- package/dist/bun/npm/payload/harness/services/penpot.json +0 -7
- package/dist/bun/npm/payload/harness/services/plane.json +0 -9
- package/dist/bun/npm/payload/harness/workflows/W01.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W02.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W03.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W04.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W05.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W06.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W07.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W08.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W09.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W10.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W11.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W12.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W13.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W14.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W15.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W16.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W17.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W18.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W19.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W20.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W21.md +0 -15
- package/dist/bun/npm/payload/harness/workflows/W22.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W23.md +0 -21
- package/dist/bun/npm/payload/harness/workflows/W24.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W25.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W26.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W27.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W28.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W29.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W30.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W31.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W32.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W33.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W34.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W35.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W36.md +0 -13
- package/dist/bun/npm/payload/harness/workflows/W37.md +0 -13
- package/dist/npm/LICENSE +0 -21
- package/dist/npm/README.md +0 -30
- package/dist/npm/harness.js +0 -104
- package/dist/npm/package.json +0 -25
- package/dist/npm/payload/HARNESS.md +0 -21
- package/dist/npm/payload/author-style/README.md +0 -56
- package/dist/npm/payload/author-style/biome-core.json +0 -57
- package/dist/npm/payload/author-style/biome-react.json +0 -9
- package/dist/npm/payload/author-style/biome-sql.json +0 -9
- package/dist/npm/payload/author-style/check.llm.md +0 -17
- package/dist/npm/payload/author-style/check.test.llm.md +0 -17
- package/dist/npm/payload/author-style/check.test.ts +0 -224
- package/dist/npm/payload/author-style/check.ts +0 -179
- package/dist/npm/payload/author-style/member-spacing.test.ts +0 -172
- package/dist/npm/payload/author-style/member-spacing.ts +0 -106
- package/dist/npm/payload/author-style/package-lock.json +0 -180
- package/dist/npm/payload/author-style/package.json +0 -17
- package/dist/npm/payload/author-style/plugins/class-member-order.grit +0 -133
- package/dist/npm/payload/author-style/plugins/event-handler-names.grit +0 -110
- package/dist/npm/payload/author-style/plugins/explicit-arrow-body.grit +0 -15
- package/dist/npm/payload/author-style/plugins/explicit-source-constructs.grit +0 -10
- package/dist/npm/payload/author-style/plugins/react-arrow-body.grit +0 -85
- package/dist/npm/payload/author-style/plugins/sql-style.grit +0 -125
- package/dist/npm/payload/author-style/react-module.llm.md +0 -17
- package/dist/npm/payload/author-style/react-module.test.ts +0 -150
- package/dist/npm/payload/author-style/react-module.ts +0 -255
- package/dist/npm/payload/author-style/source-policy.llm.md +0 -17
- package/dist/npm/payload/author-style/source-policy.test.ts +0 -70
- package/dist/npm/payload/author-style/source-policy.ts +0 -215
- package/dist/npm/payload/author-style/spacing.llm.md +0 -17
- package/dist/npm/payload/author-style/spacing.test.ts +0 -174
- package/dist/npm/payload/author-style/spacing.ts +0 -211
- package/dist/npm/payload/harness/POLICY.md +0 -33
- package/dist/npm/payload/harness/PROJECT.md +0 -26
- package/dist/npm/payload/harness/REVIEW.md +0 -17
- package/dist/npm/payload/harness/TEMPLATES.md +0 -20
- package/dist/npm/payload/harness/WORKFLOWS.md +0 -65
- package/dist/npm/payload/harness/runtime/ZOD-LICENSE +0 -21
- package/dist/npm/payload/harness/runtime/harness.mjs +0 -104
- package/dist/npm/payload/harness/services/README.md +0 -26
- package/dist/npm/payload/harness/services/penpot.json +0 -7
- package/dist/npm/payload/harness/services/plane.json +0 -9
- package/dist/npm/payload/harness/workflows/W01.md +0 -13
- package/dist/npm/payload/harness/workflows/W02.md +0 -13
- package/dist/npm/payload/harness/workflows/W03.md +0 -13
- package/dist/npm/payload/harness/workflows/W04.md +0 -13
- package/dist/npm/payload/harness/workflows/W05.md +0 -13
- package/dist/npm/payload/harness/workflows/W06.md +0 -13
- package/dist/npm/payload/harness/workflows/W07.md +0 -13
- package/dist/npm/payload/harness/workflows/W08.md +0 -13
- package/dist/npm/payload/harness/workflows/W09.md +0 -13
- package/dist/npm/payload/harness/workflows/W10.md +0 -13
- package/dist/npm/payload/harness/workflows/W11.md +0 -13
- package/dist/npm/payload/harness/workflows/W12.md +0 -13
- package/dist/npm/payload/harness/workflows/W13.md +0 -13
- package/dist/npm/payload/harness/workflows/W14.md +0 -13
- package/dist/npm/payload/harness/workflows/W15.md +0 -13
- package/dist/npm/payload/harness/workflows/W16.md +0 -13
- package/dist/npm/payload/harness/workflows/W17.md +0 -13
- package/dist/npm/payload/harness/workflows/W18.md +0 -13
- package/dist/npm/payload/harness/workflows/W19.md +0 -13
- package/dist/npm/payload/harness/workflows/W20.md +0 -13
- package/dist/npm/payload/harness/workflows/W21.md +0 -15
- package/dist/npm/payload/harness/workflows/W22.md +0 -13
- package/dist/npm/payload/harness/workflows/W23.md +0 -21
- package/dist/npm/payload/harness/workflows/W24.md +0 -13
- package/dist/npm/payload/harness/workflows/W25.md +0 -13
- package/dist/npm/payload/harness/workflows/W26.md +0 -13
- package/dist/npm/payload/harness/workflows/W27.md +0 -13
- package/dist/npm/payload/harness/workflows/W28.md +0 -13
- package/dist/npm/payload/harness/workflows/W29.md +0 -13
- package/dist/npm/payload/harness/workflows/W30.md +0 -13
- package/dist/npm/payload/harness/workflows/W31.md +0 -13
- package/dist/npm/payload/harness/workflows/W32.md +0 -13
- package/dist/npm/payload/harness/workflows/W33.md +0 -13
- package/dist/npm/payload/harness/workflows/W34.md +0 -13
- package/dist/npm/payload/harness/workflows/W35.md +0 -13
- package/dist/npm/payload/harness/workflows/W36.md +0 -13
- package/dist/npm/payload/harness/workflows/W37.md +0 -13
- /package/{dist/bun/native/LICENSE → LICENSE} +0 -0
- /package/{dist/bun/native/payload → payload}/HARNESS.md +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/README.md +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/biome-core.json +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/biome-react.json +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/biome-sql.json +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/bun.lock +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/check.llm.md +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/check.test.llm.md +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/check.test.ts +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/check.ts +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/member-spacing.test.ts +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/member-spacing.ts +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/package.json +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/plugins/class-member-order.grit +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/plugins/event-handler-names.grit +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/plugins/explicit-arrow-body.grit +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/plugins/explicit-source-constructs.grit +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/plugins/react-arrow-body.grit +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/plugins/sql-style.grit +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/react-module.llm.md +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/react-module.test.ts +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/react-module.ts +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/source-policy.llm.md +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/source-policy.test.ts +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/source-policy.ts +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/spacing.llm.md +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/spacing.test.ts +0 -0
- /package/{dist/bun/native/payload → payload}/author-style/spacing.ts +0 -0
- /package/{dist/bun/native/payload → payload}/harness/POLICY.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/PROJECT.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/REVIEW.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/TEMPLATES.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/WORKFLOWS.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/runtime/ZOD-LICENSE +0 -0
- /package/{dist/bun/native/payload → payload}/harness/services/README.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/services/penpot.json +0 -0
- /package/{dist/bun/native/payload → payload}/harness/services/plane.json +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W01.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W02.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W03.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W04.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W05.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W06.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W07.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W08.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W09.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W10.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W11.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W12.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W13.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W14.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W15.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W16.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W17.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W18.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W19.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W20.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W21.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W22.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W23.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W24.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W25.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W26.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W27.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W28.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W29.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W30.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W31.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W32.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W33.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W34.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W35.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W36.md +0 -0
- /package/{dist/bun/native/payload → payload}/harness/workflows/W37.md +0 -0
package/README.md
CHANGED
|
@@ -1,58 +1,33 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AppToolkit Harness
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
AppToolkit Harness installs project guidance, deterministic verification tools and 37 reusable engineering workflows for Codex, Claude Code and OpenCode. It supports new projects, existing repositories and a shared harness for related repositories.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Use macOS or Linux with Bun 1.4.2 or later, or Node.js 24 or later with npm. Use Git for versioned projects and RTK for project tooling. Run the installer from the target directory using one of these commands.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```sh
|
|
8
|
+
rtk proxy bunx --bun @apptoolkit/harness install
|
|
9
|
+
rtk proxy npx @apptoolkit/harness install
|
|
10
|
+
```
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
`bunx --bun` selects Bun even when Node.js is absent. Plain `bunx` also works when Node.js is on `PATH`.
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
Review the proposed files, then select which agents, repositories and optional services to configure. Open the same directory in your agent and run `$apptoolkit init` in Codex or `/apptoolkit init` in Claude Code or OpenCode. The installed `llm/HARNESS.md` is the shared entry point.
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
- [Raw acquisition index](raw/2026-11-04/README.md)
|
|
15
|
-
- [Coverage and limitations](docs/coverage.md)
|
|
16
|
-
- [Proposed gradual processing plan](docs/processing-plan.md)
|
|
17
|
-
- [Derived coverage workspace](processing/README.md)
|
|
18
|
-
- [Completed stage 1 coverage](docs/stage1-coverage.md)
|
|
19
|
-
- [Stage 2 writing and communication pilot](docs/stage2-pilot.md)
|
|
20
|
-
- [Stage 2 second extraction batch](docs/stage2-batch2.md)
|
|
21
|
-
- [Stage 2 third extraction batch](docs/stage2-batch3.md)
|
|
22
|
-
- [Stage 2 fourth extraction batch](docs/stage2-batch4.md)
|
|
23
|
-
- [Stage 2 fifth extraction batch](docs/stage2-batch5.md)
|
|
24
|
-
- [Stage 2 sixth extraction batch](docs/stage2-batch6.md)
|
|
25
|
-
- [Stage 2 seventh extraction batch](docs/stage2-batch7.md)
|
|
26
|
-
- [Stage 2 eighth extraction batch](docs/stage2-batch8.md)
|
|
27
|
-
- [Stage 2 ninth extraction batch](docs/stage2-batch9.md)
|
|
28
|
-
- [Stage 2 continuous extraction, first checkpoint](docs/stage2-continuous01.md)
|
|
29
|
-
- [Stage 2 continuous extraction, second checkpoint](docs/stage2-continuous02.md)
|
|
30
|
-
- [Stage 2 continuous extraction, third checkpoint](docs/stage2-continuous03.md)
|
|
31
|
-
- [Stage 2 continuous extraction, fourth checkpoint](docs/stage2-continuous04.md)
|
|
32
|
-
- [Stage 2 continuous extraction, fifth checkpoint](docs/stage2-continuous05.md)
|
|
33
|
-
- [Stage 2 continuous extraction, sixth checkpoint](docs/stage2-continuous06.md)
|
|
34
|
-
- [Stage 2 continuous extraction, seventh checkpoint](docs/stage2-continuous07.md)
|
|
35
|
-
- [Stage 2 continuous extraction, eighth checkpoint](docs/stage2-continuous08.md)
|
|
36
|
-
- [Stage 2 primary PDF source integration](docs/stage2-primary-pdf.md)
|
|
37
|
-
- [Stage 2 continuous extraction, ninth checkpoint](docs/stage2-continuous09.md)
|
|
38
|
-
- [Stage 2 continuous extraction, tenth mixed source checkpoint](docs/stage2-continuous10.md)
|
|
39
|
-
- [Stage 2 continuous extraction, eleventh checkpoint](docs/stage2-continuous11.md)
|
|
40
|
-
- [Tool catalog](llm/README.md)
|
|
16
|
+
In a directory of related repositories, start the agent in the parent directory. The central harness keeps shared decisions and scoped repository context. Use `$apptoolkit add repo <path>` or `/apptoolkit add repo <path>` after cloning another repository. Repositories can keep their own guidance and toolchain.
|
|
41
17
|
|
|
42
|
-
|
|
18
|
+
To preview an installation in a noninteractive session, inspect the target and supply the explicit choices.
|
|
43
19
|
|
|
44
|
-
|
|
20
|
+
```sh
|
|
21
|
+
rtk proxy bunx --bun @apptoolkit/harness inspect --root /absolute/workspace --json
|
|
22
|
+
rtk proxy bunx --bun @apptoolkit/harness install --root /absolute/workspace --hosts codex,claude,opencode --local --repo-mode .=local --plan --json
|
|
23
|
+
```
|
|
45
24
|
|
|
46
|
-
|
|
25
|
+
Use `--yes` in place of `--plan` to apply a reviewed noninteractive plan. Select the workspace mode separately from each Git repository's generated files. Local mode uses the repository's `info/exclude` metadata for the planned files. Use `--repo-mode <path>=local|versioned` for each selected Git repository.
|
|
47
26
|
|
|
48
|
-
|
|
27
|
+
Use `rtk proxy bunx --bun @apptoolkit/harness@latest update --plan --json` or `rtk proxy npx @apptoolkit/harness@latest update --plan --json` to preview a release update. The updater checks managed files against the installation receipt. Resolve reported conflicts before applying the update. Keep project decisions in the installed local profile, and review the affected paths and version before applying.
|
|
49
28
|
|
|
50
|
-
|
|
29
|
+
Plane and Penpot are separate opt-ins. To make a provider available after installation, preview an update with `--enable-service plane` or `--enable-service penpot`, apply it, and complete the project connection through `init`. The installed runbooks explain instance setup, private credentials, authorization and readiness checks. Snapshot verification requires a versioned harness and project-level opt-in. Use Bun to install the isolated Biome dependency before first using the author style profile.
|
|
51
30
|
|
|
52
|
-
|
|
31
|
+
The installed local CLI reads the workflow index, retrieves one workflow at a time and checks Markdown against a local document policy. See `llm/HARNESS.md` for the exact commands. The agent records which operations are configured and which were verified in the current environment.
|
|
53
32
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
## Current Stage 2 scope
|
|
57
|
-
|
|
58
|
-
The user narrowed Stage 2 to an inventory of their decisions and mechanisms for working with LLMs. Start with the focused inventory and its source links. C62 remains the last accepted broader source checkpoint and supplies archival evidence. [Focused LLM working practices](docs/intake.md#focused-llm-working-practices) · [C62 report](docs/stage2-continuous62.md)
|
|
33
|
+
Distributed under the MIT license.
|
|
@@ -74,7 +74,7 @@ ${i.scope.toLowerCase()}`;if(r.has(s))t.addIssue({code:"custom",path:["routes",n
|
|
|
74
74
|
Open the [harness index](HARNESS.md) for workspace rules, project routing, workflows and tools.
|
|
75
75
|
`);if(!a||u||a.hash===p.hash)s.set(c,{content:p,versioned:r.workspaceVersioned})}for(let c of r.repositories){if(!Bu(_e(e,c.path),{throwIfNoEntry:!1}))continue;let a=Se(c.path);s.set(a,{content:U(vh(e,c.path)),versioned:c.versioned})}return s}function _h(e,t,r,o,n,i){let s=[],c=new Map(o?.files.map((p)=>[p.path,p])),a=new Set(o?.repositories.map((p)=>Se(p.path))),u=new Set(r.repositories.filter((p)=>!Bu(_e(e,p.path),{throwIfNoEntry:!1})).map((p)=>Se(p.path)));for(let[p,{content:l,versioned:f,fragment:d,observed:g}]of t){let m=R(e,p),y=c.get(p),v=U(l.bytes,m?.mode??l.mode);if(g!==void 0&&!ce(m,g))throw Error(`The native router ${p} changed while planning. Retry the workspace command.`);if(!d&&m&&m.hash!==v.hash&&m.hash!==y?.hash)i.push({path:p,reason:"A different local file is present. Review or move it before applying this release."});else if(!ce(m,v))s.push({base:e,path:p,before:m,after:v});r.files.push({path:p,hash:v.hash,versioned:f,...d?{fragment:d}:{}})}for(let p of c.values()){if(t.has(p.path))continue;if(Du(p.path)||u.has(p.path)||n==="add-repo"&&!a.has(p.path)){r.files.push(p);continue}let l=R(e,p.path);if(!l)continue;if(l.hash!==p.hash){i.push({path:p.path,reason:"The release retires this file, but it has local edits. Preserve the changes before updating."});continue}s.push({base:e,path:p.path,before:l,after:null})}return r.files.sort((p,l)=>p.path.localeCompare(l.path,"en")),s}function Ju(e){let t=Va.parse(e),r=Ze(t.root),{root:o}=r,n=R(o,H),i=Y(o);if(t.action==="update"&&!i)throw Error("Install the workspace harness before updating it.");if(t.action==="install"&&i&&i.version!==t.version)throw Error(`This workspace already has harness ${i.version}. Use update to select ${t.version}.`);let s=t.action==="add-repo"&&i,c=Uu(r,t,i),a=s?i.workspaceVersioned:t.workspaceVersioned;if(a&&!r.gitRoot)throw Error(`The workspace at ${o} does not have Git. Choose local workspace mode before retrying.`);let u={schema:1,version:s?i.version:t.version,hosts:s?i.hosts:[...new Set(t.hosts)].sort(),workspaceVersioned:a,repositories:c,services:s?i.services:[...new Set(t.services)].sort(),installation:i?.installation??M(o).slice(0,16),files:[]},p=[],l=[],f=wh(o,t,u,i,p,l),d=_h(o,f,u,i,t.action,p);if(s){let z=Nu(o,i,u,p);if(z)d.push(z)}let g=d.filter((z)=>z.after===null).map((z)=>z.path),m=Ru(o,u,i,p,g),y=new Set(m.checks.filter((z)=>!z.versioned&&z.git.commonDirectory!==_e(z.git.root,".git")).map((z)=>z.git.commonDirectory));for(let z of y)l.push(`Local Git exclusions use ${_e(z,"info/exclude")}. Linked worktrees that share this Git directory use the same exclusions.`);let v=U(`${JSON.stringify(u,null,2)}
|
|
76
76
|
`,n?.mode);if(!ce(n,R(o,H)))throw Error("The installation receipt changed while planning. Retry the workspace command.");if(!ce(n,v))d.push({base:o,path:H,before:n,after:v});let k=[...m.operations,...d].map((z)=>({path:z.base===o?z.path:_e(z.base,z.path),before:z.before?.hash??null,after:z.after?.hash??null})),G={root:o,action:t.action,writes:k,conflicts:p,notices:l,receipt:u};return Fa(G,{exclusions:m.operations,files:d,checks:m.checks,guards:[{base:o,path:H,before:n,after:n}],boundaries:m.boundaries}),G}import{parseArgs as bh}from"node:util";var Lo=X(["codex","claude","opencode"]),Oe=X(["plane","penpot"]);function Vu(e){let t=bh({args:e,allowPositionals:!0,options:{help:{type:"boolean",short:"h"},version:{type:"boolean",short:"v"},root:{type:"string"},json:{type:"boolean"},yes:{type:"boolean",short:"y"},plan:{type:"boolean"},hosts:{type:"string"},versioned:{type:"boolean"},local:{type:"boolean"},repo:{type:"string",multiple:!0},"repo-mode":{type:"string",multiple:!0},"repo-versioned":{type:"boolean"},"repo-local":{type:"boolean"},"enable-service":{type:"string",multiple:!0},config:{type:"string"},project:{type:"string"},"verify-read":{type:"boolean"},"verify-health":{type:"boolean"},manifest:{type:"string"},file:{type:"string",multiple:!0},section:{type:"string"}}}),{values:r}=t;if(r.versioned&&r.local||r["repo-versioned"]&&r["repo-local"])throw Error("Choose exactly one Git storage mode for each scope.");if(r.plan&&r.yes)throw Error("Choose --plan to preview or --yes to apply.");return t}function K(e,t){return w().min(1,`Supply ${t}.`).parse(e??"")}function Hu(e){let t=new Map;for(let r of e){let o=r.lastIndexOf("="),n=r.slice(0,o),i=r.slice(o+1);if(o<1||i!=="local"&&i!=="versioned"||t.has(n))throw Error(`Invalid or duplicate --repo-mode ${r}. Use <path>=local or <path>=versioned.`);t.set(n,i==="versioned")}return t}import{readFileSync as Ku}from"node:fs";var kh=P({kind:w().min(1),title:w().min(1).optional(),headings:_(w().min(1)).default([]),checkedItems:_(w().min(1)).default([]),requiredText:_(w().min(1)).default([]),forbiddenText:_(w().min(1)).default([])});function $h(e){let t,r=[];for(let o of e.split(/\r?\n/)){let n=/^ {0,3}(`{3,}|~{3,})(.*)$/.exec(o),i=n?.[1];if(t){if(i?.startsWith(t)&&!n?.[2]?.trim())t=void 0}else if(i)t=i;else r.push(o)}return r}function Gu(e,t){let r=kh.parse(JSON.parse(Ku(e,"utf8"))),o=Ku(t,"utf8"),n=$h(o),i=n.join(`
|
|
77
|
-
`),s=o.toLowerCase(),c=n.flatMap((l)=>{let f=/^ {0,3}#{1,6}[ \t]+(.+?)\s*$/.exec(l);return f?.[1]?[f[1].replace(/[ \t]+#+[ \t]*$/,"")]:[]}),a=new Set(n.flatMap((l)=>{let f=/^\s*[-+*]\s+\[[xX]\]\s+(.+?)\s*$/.exec(l);return f?.[1]?[f[1]]:[]})),u=[],p=-1;if(r.title&&c[0]!==r.title)u.push(`Expected the first heading to be ${r.title}.`);for(let l of r.headings){let f=c.indexOf(l,p+1);if(f<0)u.push(`Missing or out-of-order heading: ${l}.`);else p=f}for(let l of r.checkedItems)if(!a.has(l))u.push(`Checklist item must be checked: ${l}.`);for(let l of r.requiredText)if(!i.includes(l))u.push(`Required text is absent: ${l}.`);for(let[l,f]of r.forbiddenText.entries())if(s.includes(f.toLowerCase()))u.push(`Forbidden text rule ${l+1} matched.`);return{kind:r.kind,valid:u.length===0,issues:u}}import{resolve as Mo}from"node:path";var zh=[{label:"Keep harness files local",value:"local"},{label:"Make harness files available to commit",value:"versioned"}],qu=[{label:"No",value:"no"},{label:"Yes",value:"yes"}];async function Uo(e,t,r){if(!e)throw Error(`Supply ${r} for a noninteractive run.`);return await e(t,zh)==="versioned"}async function Sh(e){let{options:t,select:r}=e;if(t.hosts)return[...new Set(_(Lo).min(1).parse(t.hosts.split(",")))];if(!r)throw Error("Supply --hosts codex,claude,opencode or a subset for a noninteractive install.");let n=await r("Which agent hosts should this workspace support?",[{label:"Codex, Claude Code and OpenCode",value:"codex,claude,opencode"},{label:"Codex",value:"codex"},{label:"Claude Code",value:"claude"},{label:"OpenCode",value:"opencode"},{label:"Codex and Claude Code",value:"codex,claude"},{label:"Codex and OpenCode",value:"codex,opencode"},{label:"Claude Code and OpenCode",value:"claude,opencode"}]);return _(Lo).parse(n.split(","))}async function Ph(e,t){let{options:r,select:o}=e,n=Hu(r["repo-mode"]??[]),i=new Set(t.repositories.map(({path:a})=>a)),s=new Set(r.repo??[]),c=[];for(let a of[...s,...n.keys()])if(!i.has(a))throw Error(`No repository was detected at ${a}. Inspect the workspace for accepted relative paths.`);for(let a of t.repositories){if(s.size&&!s.has(a.path))continue;if(t.kind==="workspace"&&o&&!s.size&&!n.has(a.path)){if(await o(`Register ${a.path}?`,[{label:"Register",value:"yes"},{label:"Skip",value:"no"}])==="no")continue}let u=`--repo-mode ${a.path}=local or ${a.path}=versioned`,p=a.gitRoot?n.get(a.path)??await Uo(o,`Version files generated inside ${a.path}?`,u):!1;c.push({path:a.path,versioned:p})}if(t.kind==="workspace"&&c.length===0)throw Error("Select at least one repository for the shared workspace.");return c}async function Eh(e){let{root:t,options:r,select:o,emit:n}=e,i=Ze(t);if(!r.json){let p={blank:"an empty project",existing:"an existing project",workspace:"a parent workspace"};n(`Detected ${i.monorepo?"a monorepo":p[i.kind]} at ${i.root}.`)}let s=await Sh(e),c=i.gitRoot?r.versioned||!r.local&&await Uo(o,"Version the central harness with this Git repository?","--local or --versioned"):!1;if(r.versioned&&!i.gitRoot)throw Error("The workspace root has no Git repository. Use --local.");let a=await Ph(e,i),u=_(Oe).parse(r["enable-service"]??[]);if(o&&!r["enable-service"]){for(let p of Oe.options)if(await o(`Offer ${p==="plane"?"Plane for agent work items":"Penpot for design"} during setup?`,qu)==="yes")u.push(p)}return{hosts:s,workspaceVersioned:c,repositories:a,services:[...new Set(u)]}}function Zh(e){let t=Y(e);if(!t)throw Error(`No harness is registered at ${e}. Run install first.`);return{hosts:t.hosts,workspaceVersioned:t.workspaceVersioned,repositories:t.repositories,services:t.services}}async function Xu(e,t,r){let{root:o,version:n,options:i,emit:s,select:c,contentDirectory:a}=e;if(!a&&t!=="add-repo")throw Error("Run this command from a release package. Use bunx @apptoolkit/harness@latest update for an installed workspace.");let u=Y(o),p=t==="install"&&!u?await Eh(e):Zh(o),l;if(t==="update"&&i["enable-service"]){let m=_(Oe).parse(i["enable-service"]);p.services=[...new Set([...p.services,...m])]}if(t==="add-repo"){l=K(r,"the checkout path");let m=Mo(o,l),y=p.repositories.find(({path:k})=>Mo(o,k)===m),v=i["repo-versioned"]||(i["repo-local"]?!1:y?.versioned??await Uo(c,`Version files generated inside ${l}?`,"--repo-local or --repo-versioned"));p.repositories=[...p.repositories.filter(({path:k})=>Mo(o,k)!==m),{path:l,versioned:v}]}let f=Ju({root:o,action:t,version:n,contentDirectory:a??"",...p,...l?{repository:l}:{}}),d={action:t,root:f.root,writes:f.writes.map(({path:m,before:y,after:v})=>({path:m,effect:v===null?"remove":y===null?"create":"update",before:y,after:v})),conflicts:f.conflicts,notices:f.notices};if(!i.json){s(`Plan for ${f.root} contains ${d.writes.length} change(s).`);for(let m of d.writes)s(` ${m.effect} ${m.path}`);for(let m of d.conflicts)s(` conflict ${m.path}: ${m.reason}`);for(let m of d.notices)s(` note ${m}`)}if(i.plan||!i.yes&&!c){if(i.json)s(d);return f.conflicts.length?1:0}if(f.conflicts.length){if(i.json)s(d);throw Error("Resolve the reported installation conflicts before applying the plan.")}if(!i.yes&&f.writes.length&&c&&await c("Apply this plan?",qu)!=="yes")return 0;let g=mo(f);if(i.json)s({...d,changed:g.changed,version:g.receipt.version,hosts:g.receipt.hosts});else if(s(`Applied ${g.changed} change(s) for @apptoolkit/harness ${g.receipt.version}.`),t==="install"){s(`Open ${f.root} in your selected agent host.`);for(let m of g.receipt.hosts)s(` ${m}: ${m==="codex"?"$":"/"}apptoolkit init`)}return 0}var Mh=`@apptoolkit/harness 1.0.
|
|
77
|
+
`),s=o.toLowerCase(),c=n.flatMap((l)=>{let f=/^ {0,3}#{1,6}[ \t]+(.+?)\s*$/.exec(l);return f?.[1]?[f[1].replace(/[ \t]+#+[ \t]*$/,"")]:[]}),a=new Set(n.flatMap((l)=>{let f=/^\s*[-+*]\s+\[[xX]\]\s+(.+?)\s*$/.exec(l);return f?.[1]?[f[1]]:[]})),u=[],p=-1;if(r.title&&c[0]!==r.title)u.push(`Expected the first heading to be ${r.title}.`);for(let l of r.headings){let f=c.indexOf(l,p+1);if(f<0)u.push(`Missing or out-of-order heading: ${l}.`);else p=f}for(let l of r.checkedItems)if(!a.has(l))u.push(`Checklist item must be checked: ${l}.`);for(let l of r.requiredText)if(!i.includes(l))u.push(`Required text is absent: ${l}.`);for(let[l,f]of r.forbiddenText.entries())if(s.includes(f.toLowerCase()))u.push(`Forbidden text rule ${l+1} matched.`);return{kind:r.kind,valid:u.length===0,issues:u}}import{resolve as Mo}from"node:path";var zh=[{label:"Keep harness files local",value:"local"},{label:"Make harness files available to commit",value:"versioned"}],qu=[{label:"No",value:"no"},{label:"Yes",value:"yes"}];async function Uo(e,t,r){if(!e)throw Error(`Supply ${r} for a noninteractive run.`);return await e(t,zh)==="versioned"}async function Sh(e){let{options:t,select:r}=e;if(t.hosts)return[...new Set(_(Lo).min(1).parse(t.hosts.split(",")))];if(!r)throw Error("Supply --hosts codex,claude,opencode or a subset for a noninteractive install.");let n=await r("Which agent hosts should this workspace support?",[{label:"Codex, Claude Code and OpenCode",value:"codex,claude,opencode"},{label:"Codex",value:"codex"},{label:"Claude Code",value:"claude"},{label:"OpenCode",value:"opencode"},{label:"Codex and Claude Code",value:"codex,claude"},{label:"Codex and OpenCode",value:"codex,opencode"},{label:"Claude Code and OpenCode",value:"claude,opencode"}]);return _(Lo).parse(n.split(","))}async function Ph(e,t){let{options:r,select:o}=e,n=Hu(r["repo-mode"]??[]),i=new Set(t.repositories.map(({path:a})=>a)),s=new Set(r.repo??[]),c=[];for(let a of[...s,...n.keys()])if(!i.has(a))throw Error(`No repository was detected at ${a}. Inspect the workspace for accepted relative paths.`);for(let a of t.repositories){if(s.size&&!s.has(a.path))continue;if(t.kind==="workspace"&&o&&!s.size&&!n.has(a.path)){if(await o(`Register ${a.path}?`,[{label:"Register",value:"yes"},{label:"Skip",value:"no"}])==="no")continue}let u=`--repo-mode ${a.path}=local or ${a.path}=versioned`,p=a.gitRoot?n.get(a.path)??await Uo(o,`Version files generated inside ${a.path}?`,u):!1;c.push({path:a.path,versioned:p})}if(t.kind==="workspace"&&c.length===0)throw Error("Select at least one repository for the shared workspace.");return c}async function Eh(e){let{root:t,options:r,select:o,emit:n}=e,i=Ze(t);if(!r.json){let p={blank:"an empty project",existing:"an existing project",workspace:"a parent workspace"};n(`Detected ${i.monorepo?"a monorepo":p[i.kind]} at ${i.root}.`)}let s=await Sh(e),c=i.gitRoot?r.versioned||!r.local&&await Uo(o,"Version the central harness with this Git repository?","--local or --versioned"):!1;if(r.versioned&&!i.gitRoot)throw Error("The workspace root has no Git repository. Use --local.");let a=await Ph(e,i),u=_(Oe).parse(r["enable-service"]??[]);if(o&&!r["enable-service"]){for(let p of Oe.options)if(await o(`Offer ${p==="plane"?"Plane for agent work items":"Penpot for design"} during setup?`,qu)==="yes")u.push(p)}return{hosts:s,workspaceVersioned:c,repositories:a,services:[...new Set(u)]}}function Zh(e){let t=Y(e);if(!t)throw Error(`No harness is registered at ${e}. Run install first.`);return{hosts:t.hosts,workspaceVersioned:t.workspaceVersioned,repositories:t.repositories,services:t.services}}async function Xu(e,t,r){let{root:o,version:n,options:i,emit:s,select:c,contentDirectory:a}=e;if(!a&&t!=="add-repo")throw Error("Run this command from a release package. Use bunx @apptoolkit/harness@latest update for an installed workspace.");let u=Y(o),p=t==="install"&&!u?await Eh(e):Zh(o),l;if(t==="update"&&i["enable-service"]){let m=_(Oe).parse(i["enable-service"]);p.services=[...new Set([...p.services,...m])]}if(t==="add-repo"){l=K(r,"the checkout path");let m=Mo(o,l),y=p.repositories.find(({path:k})=>Mo(o,k)===m),v=i["repo-versioned"]||(i["repo-local"]?!1:y?.versioned??await Uo(c,`Version files generated inside ${l}?`,"--repo-local or --repo-versioned"));p.repositories=[...p.repositories.filter(({path:k})=>Mo(o,k)!==m),{path:l,versioned:v}]}let f=Ju({root:o,action:t,version:n,contentDirectory:a??"",...p,...l?{repository:l}:{}}),d={action:t,root:f.root,writes:f.writes.map(({path:m,before:y,after:v})=>({path:m,effect:v===null?"remove":y===null?"create":"update",before:y,after:v})),conflicts:f.conflicts,notices:f.notices};if(!i.json){s(`Plan for ${f.root} contains ${d.writes.length} change(s).`);for(let m of d.writes)s(` ${m.effect} ${m.path}`);for(let m of d.conflicts)s(` conflict ${m.path}: ${m.reason}`);for(let m of d.notices)s(` note ${m}`)}if(i.plan||!i.yes&&!c){if(i.json)s(d);return f.conflicts.length?1:0}if(f.conflicts.length){if(i.json)s(d);throw Error("Resolve the reported installation conflicts before applying the plan.")}if(!i.yes&&f.writes.length&&c&&await c("Apply this plan?",qu)!=="yes")return 0;let g=mo(f);if(i.json)s({...d,changed:g.changed,version:g.receipt.version,hosts:g.receipt.hosts});else if(s(`Applied ${g.changed} change(s) for @apptoolkit/harness ${g.receipt.version}.`),t==="install"){s(`Open ${f.root} in your selected agent host.`);for(let m of g.receipt.hosts)s(` ${m}: ${m==="codex"?"$":"/"}apptoolkit init`)}return 0}var Mh=`@apptoolkit/harness 1.0.1
|
|
78
78
|
|
|
79
79
|
install Inspect and prepare a project or workspace
|
|
80
80
|
inspect Report workspace topology and installation state
|
|
@@ -97,8 +97,8 @@ Install options: --hosts codex,claude,opencode --local | --versioned
|
|
|
97
97
|
Add options: --repo-local | --repo-versioned
|
|
98
98
|
Service options: --project <repo> --verify-health --verify-read --manifest <file> | --file <export>
|
|
99
99
|
Use --plan to preview. Noninteractive workspace changes require --yes and explicit choices.
|
|
100
|
-
`;function Uh(){return Lh(new URL("./payload/",import.meta.url))}function Wh(e,t){if(t==="list")return lt(e,"llm/harness/WORKFLOWS.md");let r=w().regex(/^W(?:0[1-9]|[12][0-9]|3[0-7])$/,"Choose W01 through W37 or list.").parse(t??""),o=lt(e,`llm/harness/workflows/${r}.md`);if(Buffer.byteLength(o)>32768)throw Error(`Workflow ${r} is larger than 32 KiB. Use context to read a section.`);return o}async function Bh(){let{values:e,positionals:t}=Vu(process.argv.slice(2)),[r,o,n,i]=t;if(e.version)return process.stdout.write(`1.0.
|
|
100
|
+
`;function Uh(){return Lh(new URL("./payload/",import.meta.url))}function Wh(e,t){if(t==="list")return lt(e,"llm/harness/WORKFLOWS.md");let r=w().regex(/^W(?:0[1-9]|[12][0-9]|3[0-7])$/,"Choose W01 through W37 or list.").parse(t??""),o=lt(e,`llm/harness/workflows/${r}.md`);if(Buffer.byteLength(o)>32768)throw Error(`Workflow ${r} is larger than 32 KiB. Use context to read a section.`);return o}async function Bh(){let{values:e,positionals:t}=Vu(process.argv.slice(2)),[r,o,n,i]=t;if(e.version)return process.stdout.write(`1.0.1
|
|
101
101
|
`),0;if(e.help||!r)return process.stdout.write(Mh),0;let s=rr(e.root??process.cwd()),c=(y)=>{if(typeof y==="string")process.stdout.write(`${y.trimEnd()}
|
|
102
102
|
`);else process.stdout.write(`${JSON.stringify(y,null,2)}
|
|
103
|
-
`)};if(r==="inspect"&&!o){let y=Ze(s),v=Y(y.root),G=(v?Ee(y.root):void 0)?.projects.map(({path:z,budget:I,services:S})=>({path:z,budget:I.mode,services:S.map(({provider:q})=>q)}))??[];return c({...y,installation:v??null,configuredProjects:G}),0}if(r==="init"&&!o){if(!e.config)return c(await bo(s)),0;if(e.plan)throw Error("Use init without --config to read the setup template. Applying a configuration requires a separate invocation.");return c(await ko({root:s,configPath:rr(e.config)})),0}if(r==="workflow"&&!n){let y=Wh(s,o);return c(e.json?{id:o,document:y}:y),0}if(r==="context"&&!n){let y=K(o,"the workspace-relative Markdown path");return c(xu({root:s,file:y,...e.section?{section:e.section}:{}})),0}if(r==="verify"&&o==="document"&&!i){let y=rr(K(e.config,"--config <policy.json>")),v=rr(K(n,"the document path")),k=Gu(y,v);return c(k),k.valid?0:1}if(r==="verify"&&o==="coverage"&&!i){let y=K(n,"the workspace-relative LCOV report"),v=K(e.config,"--config <coverage-policy.json>");return c(zu({root:s,file:y,config:v})),0}if(r==="protect"&&!n){let y=K(e.project,"--project <repo>"),v=K(o,"the repository-relative source map path"),k=Do({root:s,repository:y,file:v});if(e.yes&&!k.conflicts.length)c({...k,...Fo(k)});else c(k);return k.conflicts.length?1:0}if(r==="service"&&o==="status"&&!i){let y=Oe.parse(n),v=K(e.project,"--project <repo>");return c(await So({root:s,service:y,project:v,verifyRead:e["verify-read"]??!1,verifyHealth:e["verify-health"]??!1})),0}if(r==="service"&&o==="snapshot"&&!i){let y=Oe.parse(n),v=K(e.project,"--project <repo>"),k=e.file??[];if(k.length&&e.manifest)throw Error("Choose --file to prepare a manifest or --manifest to verify it.");if(k.length)c(await Po({root:s,service:y,project:v,paths:k}));else{let G=K(e.manifest,"--manifest <snapshot.json>");c(await Eo({root:s,service:y,project:v,manifestPath:G}))}return 0}let a=r==="add"&&o==="repo"&&!i,u=r==="install"&&!o;if(!a&&!u&&!(r==="update"&&!o))throw Error("Unknown command or arguments. Run with --help for usage.");let f=process.stdin.isTTY&&!e.json&&!e.plan&&!e.yes?await Promise.resolve().then(() => (Qu(),Yu)):void 0,d={root:s,version:"1.0.
|
|
103
|
+
`)};if(r==="inspect"&&!o){let y=Ze(s),v=Y(y.root),G=(v?Ee(y.root):void 0)?.projects.map(({path:z,budget:I,services:S})=>({path:z,budget:I.mode,services:S.map(({provider:q})=>q)}))??[];return c({...y,installation:v??null,configuredProjects:G}),0}if(r==="init"&&!o){if(!e.config)return c(await bo(s)),0;if(e.plan)throw Error("Use init without --config to read the setup template. Applying a configuration requires a separate invocation.");return c(await ko({root:s,configPath:rr(e.config)})),0}if(r==="workflow"&&!n){let y=Wh(s,o);return c(e.json?{id:o,document:y}:y),0}if(r==="context"&&!n){let y=K(o,"the workspace-relative Markdown path");return c(xu({root:s,file:y,...e.section?{section:e.section}:{}})),0}if(r==="verify"&&o==="document"&&!i){let y=rr(K(e.config,"--config <policy.json>")),v=rr(K(n,"the document path")),k=Gu(y,v);return c(k),k.valid?0:1}if(r==="verify"&&o==="coverage"&&!i){let y=K(n,"the workspace-relative LCOV report"),v=K(e.config,"--config <coverage-policy.json>");return c(zu({root:s,file:y,config:v})),0}if(r==="protect"&&!n){let y=K(e.project,"--project <repo>"),v=K(o,"the repository-relative source map path"),k=Do({root:s,repository:y,file:v});if(e.yes&&!k.conflicts.length)c({...k,...Fo(k)});else c(k);return k.conflicts.length?1:0}if(r==="service"&&o==="status"&&!i){let y=Oe.parse(n),v=K(e.project,"--project <repo>");return c(await So({root:s,service:y,project:v,verifyRead:e["verify-read"]??!1,verifyHealth:e["verify-health"]??!1})),0}if(r==="service"&&o==="snapshot"&&!i){let y=Oe.parse(n),v=K(e.project,"--project <repo>"),k=e.file??[];if(k.length&&e.manifest)throw Error("Choose --file to prepare a manifest or --manifest to verify it.");if(k.length)c(await Po({root:s,service:y,project:v,paths:k}));else{let G=K(e.manifest,"--manifest <snapshot.json>");c(await Eo({root:s,service:y,project:v,manifestPath:G}))}return 0}let a=r==="add"&&o==="repo"&&!i,u=r==="install"&&!o;if(!a&&!u&&!(r==="update"&&!o))throw Error("Unknown command or arguments. Run with --help for usage.");let f=process.stdin.isTTY&&!e.json&&!e.plan&&!e.yes?await Promise.resolve().then(() => (Qu(),Yu)):void 0,d={root:s,version:"1.0.1",options:e,emit:c},g={contentDirectory:Uh()},m=f?{select:f.selectChoice}:{};return Xu({...d,...g,...m},a?"add-repo":u?"install":"update",n)}try{process.exitCode=await Bh()}catch(e){let t=e instanceof Error?e.message:String(e);process.stderr.write(`apptoolkit: ${t}
|
|
104
104
|
`),process.exitCode=1}
|
package/package.json
CHANGED
|
@@ -1,37 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apptoolkit/harness",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "A portable harness for configuring AI coding agents and engineering workflows.",
|
|
5
|
+
"license": "MIT",
|
|
5
6
|
"type": "module",
|
|
6
|
-
"
|
|
7
|
+
"bin": {
|
|
8
|
+
"harness": "./harness.js"
|
|
9
|
+
},
|
|
7
10
|
"files": [
|
|
8
|
-
"
|
|
11
|
+
"harness.js",
|
|
12
|
+
"payload/"
|
|
9
13
|
],
|
|
14
|
+
"packageManager": "bun@1.4.2",
|
|
10
15
|
"publishConfig": {
|
|
11
16
|
"access": "public",
|
|
12
17
|
"registry": "https://registry.npmjs.org/"
|
|
13
18
|
},
|
|
14
|
-
"scripts": {
|
|
15
|
-
"acquire": "bun --no-env-file src/acquisition/acquire.ts",
|
|
16
|
-
"build:harness": "bun --no-env-file src/harness/release/build.ts",
|
|
17
|
-
"build:harness:native": "bun --no-env-file src/harness/release/build.ts --native",
|
|
18
|
-
"pack:harness": "bun pm pack --cwd dist/bun/npm --ignore-scripts --destination .. --quiet",
|
|
19
|
-
"test": "bun test --no-env-file src/acquisition",
|
|
20
|
-
"test:harness": "bun test --no-env-file src/harness",
|
|
21
|
-
"typecheck": "bun --no-env-file node_modules/typescript/bin/tsc --noEmit"
|
|
22
|
-
},
|
|
23
19
|
"dependencies": {
|
|
24
20
|
"ink": "7.1.1",
|
|
25
|
-
"react": "19.3.1"
|
|
26
|
-
"zod": "4.6.7"
|
|
27
|
-
},
|
|
28
|
-
"devDependencies": {
|
|
29
|
-
"@types/node": "24.10.0",
|
|
30
|
-
"@types/react": "19.3.0",
|
|
31
|
-
"react-devtools-core": "6.1.5",
|
|
32
|
-
"typescript": "5.9.3"
|
|
33
|
-
},
|
|
34
|
-
"engines": {
|
|
35
|
-
"bun": ">=1.4.2"
|
|
21
|
+
"react": "19.3.1"
|
|
36
22
|
}
|
|
37
23
|
}
|
|
@@ -74,7 +74,7 @@ ${i.scope.toLowerCase()}`;if(r.has(s))t.addIssue({code:"custom",path:["routes",n
|
|
|
74
74
|
Open the [harness index](HARNESS.md) for workspace rules, project routing, workflows and tools.
|
|
75
75
|
`);if(!a||u||a.hash===p.hash)s.set(c,{content:p,versioned:r.workspaceVersioned})}for(let c of r.repositories){if(!Mu(_e(e,c.path),{throwIfNoEntry:!1}))continue;let a=Se(c.path);s.set(a,{content:U(hh(e,c.path)),versioned:c.versioned})}return s}function gh(e,t,r,o,n,i){let s=[],c=new Map(o?.files.map((p)=>[p.path,p])),a=new Set(o?.repositories.map((p)=>Se(p.path))),u=new Set(r.repositories.filter((p)=>!Mu(_e(e,p.path),{throwIfNoEntry:!1})).map((p)=>Se(p.path)));for(let[p,{content:l,versioned:f,fragment:d,observed:g}]of t){let m=R(e,p),y=c.get(p),v=U(l.bytes,m?.mode??l.mode);if(g!==void 0&&!ce(m,g))throw Error(`The native router ${p} changed while planning. Retry the workspace command.`);if(!d&&m&&m.hash!==v.hash&&m.hash!==y?.hash)i.push({path:p,reason:"A different local file is present. Review or move it before applying this release."});else if(!ce(m,v))s.push({base:e,path:p,before:m,after:v});r.files.push({path:p,hash:v.hash,versioned:f,...d?{fragment:d}:{}})}for(let p of c.values()){if(t.has(p.path))continue;if(Nu(p.path)||u.has(p.path)||n==="add-repo"&&!a.has(p.path)){r.files.push(p);continue}let l=R(e,p.path);if(!l)continue;if(l.hash!==p.hash){i.push({path:p.path,reason:"The release retires this file, but it has local edits. Preserve the changes before updating."});continue}s.push({base:e,path:p.path,before:l,after:null})}return r.files.sort((p,l)=>p.path.localeCompare(l.path,"en")),s}function Uu(e){let t=Wa.parse(e),r=Ze(t.root),{root:o}=r,n=R(o,H),i=Y(o);if(t.action==="update"&&!i)throw Error("Install the workspace harness before updating it.");if(t.action==="install"&&i&&i.version!==t.version)throw Error(`This workspace already has harness ${i.version}. Use update to select ${t.version}.`);let s=t.action==="add-repo"&&i,c=Fu(r,t,i),a=s?i.workspaceVersioned:t.workspaceVersioned;if(a&&!r.gitRoot)throw Error(`The workspace at ${o} does not have Git. Choose local workspace mode before retrying.`);let u={schema:1,version:s?i.version:t.version,hosts:s?i.hosts:[...new Set(t.hosts)].sort(),workspaceVersioned:a,repositories:c,services:s?i.services:[...new Set(t.services)].sort(),installation:i?.installation??M(o).slice(0,16),files:[]},p=[],l=[],f=mh(o,t,u,i,p,l),d=gh(o,f,u,i,t.action,p);if(s){let z=Iu(o,i,u,p);if(z)d.push(z)}let g=d.filter((z)=>z.after===null).map((z)=>z.path),m=Zu(o,u,i,p,g),y=new Set(m.checks.filter((z)=>!z.versioned&&z.git.commonDirectory!==_e(z.git.root,".git")).map((z)=>z.git.commonDirectory));for(let z of y)l.push(`Local Git exclusions use ${_e(z,"info/exclude")}. Linked worktrees that share this Git directory use the same exclusions.`);let v=U(`${JSON.stringify(u,null,2)}
|
|
76
76
|
`,n?.mode);if(!ce(n,R(o,H)))throw Error("The installation receipt changed while planning. Retry the workspace command.");if(!ce(n,v))d.push({base:o,path:H,before:n,after:v});let k=[...m.operations,...d].map((z)=>({path:z.base===o?z.path:_e(z.base,z.path),before:z.before?.hash??null,after:z.after?.hash??null})),G={root:o,action:t.action,writes:k,conflicts:p,notices:l,receipt:u};return Ta(G,{exclusions:m.operations,files:d,checks:m.checks,guards:[{base:o,path:H,before:n,after:n}],boundaries:m.boundaries}),G}import{parseArgs as yh}from"node:util";var Fo=X(["codex","claude","opencode"]),Oe=X(["plane","penpot"]);function Wu(e){let t=yh({args:e,allowPositionals:!0,options:{help:{type:"boolean",short:"h"},version:{type:"boolean",short:"v"},root:{type:"string"},json:{type:"boolean"},yes:{type:"boolean",short:"y"},plan:{type:"boolean"},hosts:{type:"string"},versioned:{type:"boolean"},local:{type:"boolean"},repo:{type:"string",multiple:!0},"repo-mode":{type:"string",multiple:!0},"repo-versioned":{type:"boolean"},"repo-local":{type:"boolean"},"enable-service":{type:"string",multiple:!0},config:{type:"string"},project:{type:"string"},"verify-read":{type:"boolean"},"verify-health":{type:"boolean"},manifest:{type:"string"},file:{type:"string",multiple:!0},section:{type:"string"}}}),{values:r}=t;if(r.versioned&&r.local||r["repo-versioned"]&&r["repo-local"])throw Error("Choose exactly one Git storage mode for each scope.");if(r.plan&&r.yes)throw Error("Choose --plan to preview or --yes to apply.");return t}function K(e,t){return w().min(1,`Supply ${t}.`).parse(e??"")}function Bu(e){let t=new Map;for(let r of e){let o=r.lastIndexOf("="),n=r.slice(0,o),i=r.slice(o+1);if(o<1||i!=="local"&&i!=="versioned"||t.has(n))throw Error(`Invalid or duplicate --repo-mode ${r}. Use <path>=local or <path>=versioned.`);t.set(n,i==="versioned")}return t}import{readFileSync as Ju}from"node:fs";var xh=P({kind:w().min(1),title:w().min(1).optional(),headings:_(w().min(1)).default([]),checkedItems:_(w().min(1)).default([]),requiredText:_(w().min(1)).default([]),forbiddenText:_(w().min(1)).default([])});function vh(e){let t,r=[];for(let o of e.split(/\r?\n/)){let n=/^ {0,3}(`{3,}|~{3,})(.*)$/.exec(o),i=n?.[1];if(t){if(i?.startsWith(t)&&!n?.[2]?.trim())t=void 0}else if(i)t=i;else r.push(o)}return r}function Vu(e,t){let r=xh.parse(JSON.parse(Ju(e,"utf8"))),o=Ju(t,"utf8"),n=vh(o),i=n.join(`
|
|
77
|
-
`),s=o.toLowerCase(),c=n.flatMap((l)=>{let f=/^ {0,3}#{1,6}[ \t]+(.+?)\s*$/.exec(l);return f?.[1]?[f[1].replace(/[ \t]+#+[ \t]*$/,"")]:[]}),a=new Set(n.flatMap((l)=>{let f=/^\s*[-+*]\s+\[[xX]\]\s+(.+?)\s*$/.exec(l);return f?.[1]?[f[1]]:[]})),u=[],p=-1;if(r.title&&c[0]!==r.title)u.push(`Expected the first heading to be ${r.title}.`);for(let l of r.headings){let f=c.indexOf(l,p+1);if(f<0)u.push(`Missing or out-of-order heading: ${l}.`);else p=f}for(let l of r.checkedItems)if(!a.has(l))u.push(`Checklist item must be checked: ${l}.`);for(let l of r.requiredText)if(!i.includes(l))u.push(`Required text is absent: ${l}.`);for(let[l,f]of r.forbiddenText.entries())if(s.includes(f.toLowerCase()))u.push(`Forbidden text rule ${l+1} matched.`);return{kind:r.kind,valid:u.length===0,issues:u}}import{resolve as Lo}from"node:path";var wh=[{label:"Keep harness files local",value:"local"},{label:"Make harness files available to commit",value:"versioned"}],Hu=[{label:"No",value:"no"},{label:"Yes",value:"yes"}];async function Mo(e,t,r){if(!e)throw Error(`Supply ${r} for a noninteractive run.`);return await e(t,wh)==="versioned"}async function _h(e){let{options:t,select:r}=e;if(t.hosts)return[...new Set(_(Fo).min(1).parse(t.hosts.split(",")))];if(!r)throw Error("Supply --hosts codex,claude,opencode or a subset for a noninteractive install.");let n=await r("Which agent hosts should this workspace support?",[{label:"Codex, Claude Code and OpenCode",value:"codex,claude,opencode"},{label:"Codex",value:"codex"},{label:"Claude Code",value:"claude"},{label:"OpenCode",value:"opencode"},{label:"Codex and Claude Code",value:"codex,claude"},{label:"Codex and OpenCode",value:"codex,opencode"},{label:"Claude Code and OpenCode",value:"claude,opencode"}]);return _(Fo).parse(n.split(","))}async function bh(e,t){let{options:r,select:o}=e,n=Bu(r["repo-mode"]??[]),i=new Set(t.repositories.map(({path:a})=>a)),s=new Set(r.repo??[]),c=[];for(let a of[...s,...n.keys()])if(!i.has(a))throw Error(`No repository was detected at ${a}. Inspect the workspace for accepted relative paths.`);for(let a of t.repositories){if(s.size&&!s.has(a.path))continue;if(t.kind==="workspace"&&o&&!s.size&&!n.has(a.path)){if(await o(`Register ${a.path}?`,[{label:"Register",value:"yes"},{label:"Skip",value:"no"}])==="no")continue}let u=`--repo-mode ${a.path}=local or ${a.path}=versioned`,p=a.gitRoot?n.get(a.path)??await Mo(o,`Version files generated inside ${a.path}?`,u):!1;c.push({path:a.path,versioned:p})}if(t.kind==="workspace"&&c.length===0)throw Error("Select at least one repository for the shared workspace.");return c}async function kh(e){let{root:t,options:r,select:o,emit:n}=e,i=Ze(t);if(!r.json){let p={blank:"an empty project",existing:"an existing project",workspace:"a parent workspace"};n(`Detected ${i.monorepo?"a monorepo":p[i.kind]} at ${i.root}.`)}let s=await _h(e),c=i.gitRoot?r.versioned||!r.local&&await Mo(o,"Version the central harness with this Git repository?","--local or --versioned"):!1;if(r.versioned&&!i.gitRoot)throw Error("The workspace root has no Git repository. Use --local.");let a=await bh(e,i),u=_(Oe).parse(r["enable-service"]??[]);if(o&&!r["enable-service"]){for(let p of Oe.options)if(await o(`Offer ${p==="plane"?"Plane for agent work items":"Penpot for design"} during setup?`,Hu)==="yes")u.push(p)}return{hosts:s,workspaceVersioned:c,repositories:a,services:[...new Set(u)]}}function $h(e){let t=Y(e);if(!t)throw Error(`No harness is registered at ${e}. Run install first.`);return{hosts:t.hosts,workspaceVersioned:t.workspaceVersioned,repositories:t.repositories,services:t.services}}async function Ku(e,t,r){let{root:o,version:n,options:i,emit:s,select:c,contentDirectory:a}=e;if(!a&&t!=="add-repo")throw Error("Run this command from a release package. Use bunx @apptoolkit/harness@latest update for an installed workspace.");let u=Y(o),p=t==="install"&&!u?await kh(e):$h(o),l;if(t==="update"&&i["enable-service"]){let m=_(Oe).parse(i["enable-service"]);p.services=[...new Set([...p.services,...m])]}if(t==="add-repo"){l=K(r,"the checkout path");let m=Lo(o,l),y=p.repositories.find(({path:k})=>Lo(o,k)===m),v=i["repo-versioned"]||(i["repo-local"]?!1:y?.versioned??await Mo(c,`Version files generated inside ${l}?`,"--repo-local or --repo-versioned"));p.repositories=[...p.repositories.filter(({path:k})=>Lo(o,k)!==m),{path:l,versioned:v}]}let f=Uu({root:o,action:t,version:n,contentDirectory:a??"",...p,...l?{repository:l}:{}}),d={action:t,root:f.root,writes:f.writes.map(({path:m,before:y,after:v})=>({path:m,effect:v===null?"remove":y===null?"create":"update",before:y,after:v})),conflicts:f.conflicts,notices:f.notices};if(!i.json){s(`Plan for ${f.root} contains ${d.writes.length} change(s).`);for(let m of d.writes)s(` ${m.effect} ${m.path}`);for(let m of d.conflicts)s(` conflict ${m.path}: ${m.reason}`);for(let m of d.notices)s(` note ${m}`)}if(i.plan||!i.yes&&!c){if(i.json)s(d);return f.conflicts.length?1:0}if(f.conflicts.length){if(i.json)s(d);throw Error("Resolve the reported installation conflicts before applying the plan.")}if(!i.yes&&f.writes.length&&c&&await c("Apply this plan?",Hu)!=="yes")return 0;let g=ho(f);if(i.json)s({...d,changed:g.changed,version:g.receipt.version,hosts:g.receipt.hosts});else if(s(`Applied ${g.changed} change(s) for @apptoolkit/harness ${g.receipt.version}.`),t==="install"){s(`Open ${f.root} in your selected agent host.`);for(let m of g.receipt.hosts)s(` ${m}: ${m==="codex"?"$":"/"}apptoolkit init`)}return 0}var Sh=`@apptoolkit/harness 1.0.
|
|
77
|
+
`),s=o.toLowerCase(),c=n.flatMap((l)=>{let f=/^ {0,3}#{1,6}[ \t]+(.+?)\s*$/.exec(l);return f?.[1]?[f[1].replace(/[ \t]+#+[ \t]*$/,"")]:[]}),a=new Set(n.flatMap((l)=>{let f=/^\s*[-+*]\s+\[[xX]\]\s+(.+?)\s*$/.exec(l);return f?.[1]?[f[1]]:[]})),u=[],p=-1;if(r.title&&c[0]!==r.title)u.push(`Expected the first heading to be ${r.title}.`);for(let l of r.headings){let f=c.indexOf(l,p+1);if(f<0)u.push(`Missing or out-of-order heading: ${l}.`);else p=f}for(let l of r.checkedItems)if(!a.has(l))u.push(`Checklist item must be checked: ${l}.`);for(let l of r.requiredText)if(!i.includes(l))u.push(`Required text is absent: ${l}.`);for(let[l,f]of r.forbiddenText.entries())if(s.includes(f.toLowerCase()))u.push(`Forbidden text rule ${l+1} matched.`);return{kind:r.kind,valid:u.length===0,issues:u}}import{resolve as Lo}from"node:path";var wh=[{label:"Keep harness files local",value:"local"},{label:"Make harness files available to commit",value:"versioned"}],Hu=[{label:"No",value:"no"},{label:"Yes",value:"yes"}];async function Mo(e,t,r){if(!e)throw Error(`Supply ${r} for a noninteractive run.`);return await e(t,wh)==="versioned"}async function _h(e){let{options:t,select:r}=e;if(t.hosts)return[...new Set(_(Fo).min(1).parse(t.hosts.split(",")))];if(!r)throw Error("Supply --hosts codex,claude,opencode or a subset for a noninteractive install.");let n=await r("Which agent hosts should this workspace support?",[{label:"Codex, Claude Code and OpenCode",value:"codex,claude,opencode"},{label:"Codex",value:"codex"},{label:"Claude Code",value:"claude"},{label:"OpenCode",value:"opencode"},{label:"Codex and Claude Code",value:"codex,claude"},{label:"Codex and OpenCode",value:"codex,opencode"},{label:"Claude Code and OpenCode",value:"claude,opencode"}]);return _(Fo).parse(n.split(","))}async function bh(e,t){let{options:r,select:o}=e,n=Bu(r["repo-mode"]??[]),i=new Set(t.repositories.map(({path:a})=>a)),s=new Set(r.repo??[]),c=[];for(let a of[...s,...n.keys()])if(!i.has(a))throw Error(`No repository was detected at ${a}. Inspect the workspace for accepted relative paths.`);for(let a of t.repositories){if(s.size&&!s.has(a.path))continue;if(t.kind==="workspace"&&o&&!s.size&&!n.has(a.path)){if(await o(`Register ${a.path}?`,[{label:"Register",value:"yes"},{label:"Skip",value:"no"}])==="no")continue}let u=`--repo-mode ${a.path}=local or ${a.path}=versioned`,p=a.gitRoot?n.get(a.path)??await Mo(o,`Version files generated inside ${a.path}?`,u):!1;c.push({path:a.path,versioned:p})}if(t.kind==="workspace"&&c.length===0)throw Error("Select at least one repository for the shared workspace.");return c}async function kh(e){let{root:t,options:r,select:o,emit:n}=e,i=Ze(t);if(!r.json){let p={blank:"an empty project",existing:"an existing project",workspace:"a parent workspace"};n(`Detected ${i.monorepo?"a monorepo":p[i.kind]} at ${i.root}.`)}let s=await _h(e),c=i.gitRoot?r.versioned||!r.local&&await Mo(o,"Version the central harness with this Git repository?","--local or --versioned"):!1;if(r.versioned&&!i.gitRoot)throw Error("The workspace root has no Git repository. Use --local.");let a=await bh(e,i),u=_(Oe).parse(r["enable-service"]??[]);if(o&&!r["enable-service"]){for(let p of Oe.options)if(await o(`Offer ${p==="plane"?"Plane for agent work items":"Penpot for design"} during setup?`,Hu)==="yes")u.push(p)}return{hosts:s,workspaceVersioned:c,repositories:a,services:[...new Set(u)]}}function $h(e){let t=Y(e);if(!t)throw Error(`No harness is registered at ${e}. Run install first.`);return{hosts:t.hosts,workspaceVersioned:t.workspaceVersioned,repositories:t.repositories,services:t.services}}async function Ku(e,t,r){let{root:o,version:n,options:i,emit:s,select:c,contentDirectory:a}=e;if(!a&&t!=="add-repo")throw Error("Run this command from a release package. Use bunx @apptoolkit/harness@latest update for an installed workspace.");let u=Y(o),p=t==="install"&&!u?await kh(e):$h(o),l;if(t==="update"&&i["enable-service"]){let m=_(Oe).parse(i["enable-service"]);p.services=[...new Set([...p.services,...m])]}if(t==="add-repo"){l=K(r,"the checkout path");let m=Lo(o,l),y=p.repositories.find(({path:k})=>Lo(o,k)===m),v=i["repo-versioned"]||(i["repo-local"]?!1:y?.versioned??await Mo(c,`Version files generated inside ${l}?`,"--repo-local or --repo-versioned"));p.repositories=[...p.repositories.filter(({path:k})=>Lo(o,k)!==m),{path:l,versioned:v}]}let f=Uu({root:o,action:t,version:n,contentDirectory:a??"",...p,...l?{repository:l}:{}}),d={action:t,root:f.root,writes:f.writes.map(({path:m,before:y,after:v})=>({path:m,effect:v===null?"remove":y===null?"create":"update",before:y,after:v})),conflicts:f.conflicts,notices:f.notices};if(!i.json){s(`Plan for ${f.root} contains ${d.writes.length} change(s).`);for(let m of d.writes)s(` ${m.effect} ${m.path}`);for(let m of d.conflicts)s(` conflict ${m.path}: ${m.reason}`);for(let m of d.notices)s(` note ${m}`)}if(i.plan||!i.yes&&!c){if(i.json)s(d);return f.conflicts.length?1:0}if(f.conflicts.length){if(i.json)s(d);throw Error("Resolve the reported installation conflicts before applying the plan.")}if(!i.yes&&f.writes.length&&c&&await c("Apply this plan?",Hu)!=="yes")return 0;let g=ho(f);if(i.json)s({...d,changed:g.changed,version:g.receipt.version,hosts:g.receipt.hosts});else if(s(`Applied ${g.changed} change(s) for @apptoolkit/harness ${g.receipt.version}.`),t==="install"){s(`Open ${f.root} in your selected agent host.`);for(let m of g.receipt.hosts)s(` ${m}: ${m==="codex"?"$":"/"}apptoolkit init`)}return 0}var Sh=`@apptoolkit/harness 1.0.1
|
|
78
78
|
|
|
79
79
|
install Inspect and prepare a project or workspace
|
|
80
80
|
inspect Report workspace topology and installation state
|
|
@@ -97,8 +97,8 @@ Install options: --hosts codex,claude,opencode --local | --versioned
|
|
|
97
97
|
Add options: --repo-local | --repo-versioned
|
|
98
98
|
Service options: --project <repo> --verify-health --verify-read --manifest <file> | --file <export>
|
|
99
99
|
Use --plan to preview. Noninteractive workspace changes require --yes and explicit choices.
|
|
100
|
-
`;function Ph(e,t){if(t==="list")return lt(e,"llm/harness/WORKFLOWS.md");let r=w().regex(/^W(?:0[1-9]|[12][0-9]|3[0-7])$/,"Choose W01 through W37 or list.").parse(t??""),o=lt(e,`llm/harness/workflows/${r}.md`);if(Buffer.byteLength(o)>32768)throw Error(`Workflow ${r} is larger than 32 KiB. Use context to read a section.`);return o}async function Eh(){let{values:e,positionals:t}=Wu(process.argv.slice(2)),[r,o,n,i]=t;if(e.version)return process.stdout.write(`1.0.
|
|
100
|
+
`;function Ph(e,t){if(t==="list")return lt(e,"llm/harness/WORKFLOWS.md");let r=w().regex(/^W(?:0[1-9]|[12][0-9]|3[0-7])$/,"Choose W01 through W37 or list.").parse(t??""),o=lt(e,`llm/harness/workflows/${r}.md`);if(Buffer.byteLength(o)>32768)throw Error(`Workflow ${r} is larger than 32 KiB. Use context to read a section.`);return o}async function Eh(){let{values:e,positionals:t}=Wu(process.argv.slice(2)),[r,o,n,i]=t;if(e.version)return process.stdout.write(`1.0.1
|
|
101
101
|
`),0;if(e.help||!r)return process.stdout.write(Sh),0;let s=tr(e.root??zh(new URL("../../../",import.meta.url))),c=(y)=>{if(typeof y==="string")process.stdout.write(`${y.trimEnd()}
|
|
102
102
|
`);else process.stdout.write(`${JSON.stringify(y,null,2)}
|
|
103
|
-
`)};if(r==="inspect"&&!o){let y=Ze(s),v=Y(y.root),G=(v?Ee(y.root):void 0)?.projects.map(({path:z,budget:I,services:S})=>({path:z,budget:I.mode,services:S.map(({provider:q})=>q)}))??[];return c({...y,installation:v??null,configuredProjects:G}),0}if(r==="init"&&!o){if(!e.config)return c(await _o(s)),0;if(e.plan)throw Error("Use init without --config to read the setup template. Applying a configuration requires a separate invocation.");return c(await bo({root:s,configPath:tr(e.config)})),0}if(r==="workflow"&&!n){let y=Ph(s,o);return c(e.json?{id:o,document:y}:y),0}if(r==="context"&&!n){let y=K(o,"the workspace-relative Markdown path");return c(mu({root:s,file:y,...e.section?{section:e.section}:{}})),0}if(r==="verify"&&o==="document"&&!i){let y=tr(K(e.config,"--config <policy.json>")),v=tr(K(n,"the document path")),k=Vu(y,v);return c(k),k.valid?0:1}if(r==="verify"&&o==="coverage"&&!i){let y=K(n,"the workspace-relative LCOV report"),v=K(e.config,"--config <coverage-policy.json>");return c(bu({root:s,file:y,config:v})),0}if(r==="protect"&&!n){let y=K(e.project,"--project <repo>"),v=K(o,"the repository-relative source map path"),k=jo({root:s,repository:y,file:v});if(e.yes&&!k.conflicts.length)c({...k,...Do(k)});else c(k);return k.conflicts.length?1:0}if(r==="service"&&o==="status"&&!i){let y=Oe.parse(n),v=K(e.project,"--project <repo>");return c(await zo({root:s,service:y,project:v,verifyRead:e["verify-read"]??!1,verifyHealth:e["verify-health"]??!1})),0}if(r==="service"&&o==="snapshot"&&!i){let y=Oe.parse(n),v=K(e.project,"--project <repo>"),k=e.file??[];if(k.length&&e.manifest)throw Error("Choose --file to prepare a manifest or --manifest to verify it.");if(k.length)c(await So({root:s,service:y,project:v,paths:k}));else{let G=K(e.manifest,"--manifest <snapshot.json>");c(await Po({root:s,service:y,project:v,manifestPath:G}))}return 0}let a=r==="add"&&o==="repo"&&!i,u=r==="install"&&!o;if(!a&&!u&&!(r==="update"&&!o))throw Error("Unknown command or arguments. Run with --help for usage.");let l=process.stdin.isTTY&&!e.json&&!e.plan&&!e.yes,f=void 0,d={root:s,version:"1.0.
|
|
103
|
+
`)};if(r==="inspect"&&!o){let y=Ze(s),v=Y(y.root),G=(v?Ee(y.root):void 0)?.projects.map(({path:z,budget:I,services:S})=>({path:z,budget:I.mode,services:S.map(({provider:q})=>q)}))??[];return c({...y,installation:v??null,configuredProjects:G}),0}if(r==="init"&&!o){if(!e.config)return c(await _o(s)),0;if(e.plan)throw Error("Use init without --config to read the setup template. Applying a configuration requires a separate invocation.");return c(await bo({root:s,configPath:tr(e.config)})),0}if(r==="workflow"&&!n){let y=Ph(s,o);return c(e.json?{id:o,document:y}:y),0}if(r==="context"&&!n){let y=K(o,"the workspace-relative Markdown path");return c(mu({root:s,file:y,...e.section?{section:e.section}:{}})),0}if(r==="verify"&&o==="document"&&!i){let y=tr(K(e.config,"--config <policy.json>")),v=tr(K(n,"the document path")),k=Vu(y,v);return c(k),k.valid?0:1}if(r==="verify"&&o==="coverage"&&!i){let y=K(n,"the workspace-relative LCOV report"),v=K(e.config,"--config <coverage-policy.json>");return c(bu({root:s,file:y,config:v})),0}if(r==="protect"&&!n){let y=K(e.project,"--project <repo>"),v=K(o,"the repository-relative source map path"),k=jo({root:s,repository:y,file:v});if(e.yes&&!k.conflicts.length)c({...k,...Do(k)});else c(k);return k.conflicts.length?1:0}if(r==="service"&&o==="status"&&!i){let y=Oe.parse(n),v=K(e.project,"--project <repo>");return c(await zo({root:s,service:y,project:v,verifyRead:e["verify-read"]??!1,verifyHealth:e["verify-health"]??!1})),0}if(r==="service"&&o==="snapshot"&&!i){let y=Oe.parse(n),v=K(e.project,"--project <repo>"),k=e.file??[];if(k.length&&e.manifest)throw Error("Choose --file to prepare a manifest or --manifest to verify it.");if(k.length)c(await So({root:s,service:y,project:v,paths:k}));else{let G=K(e.manifest,"--manifest <snapshot.json>");c(await Po({root:s,service:y,project:v,manifestPath:G}))}return 0}let a=r==="add"&&o==="repo"&&!i,u=r==="install"&&!o;if(!a&&!u&&!(r==="update"&&!o))throw Error("Unknown command or arguments. Run with --help for usage.");let l=process.stdin.isTTY&&!e.json&&!e.plan&&!e.yes,f=void 0,d={root:s,version:"1.0.1",options:e,emit:c},g={},m=f?{select:f.selectChoice}:{};return Ku({...d,...g,...m},a?"add-repo":u?"install":"update",n)}try{process.exitCode=await Eh()}catch(e){let t=e instanceof Error?e.message:String(e);process.stderr.write(`apptoolkit: ${t}
|
|
104
104
|
`),process.exitCode=1}
|
|
Binary file
|
|
Binary file
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# AppToolkit Harness
|
|
2
|
-
|
|
3
|
-
AppToolkit Harness installs project guidance, deterministic verification tools and 37 reusable engineering workflows for Codex, Claude Code and OpenCode. It supports new projects, existing repositories and a shared harness for related repositories.
|
|
4
|
-
|
|
5
|
-
Use macOS or Linux with Bun 1.4.2 or later, or Node.js 24 or later with npm. Use Git for versioned projects and RTK for project tooling. Run the installer from the target directory using one of these commands.
|
|
6
|
-
|
|
7
|
-
```sh
|
|
8
|
-
rtk proxy bunx --bun @apptoolkit/harness install
|
|
9
|
-
rtk proxy npx @apptoolkit/harness install
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
`bunx --bun` selects Bun even when Node.js is absent. Plain `bunx` also works when Node.js is on `PATH`.
|
|
13
|
-
|
|
14
|
-
Review the proposed files, then select which agents, repositories and optional services to configure. Open the same directory in your agent and run `$apptoolkit init` in Codex or `/apptoolkit init` in Claude Code or OpenCode. The installed `llm/HARNESS.md` is the shared entry point.
|
|
15
|
-
|
|
16
|
-
In a directory of related repositories, start the agent in the parent directory. The central harness keeps shared decisions and scoped repository context. Use `$apptoolkit add repo <path>` or `/apptoolkit add repo <path>` after cloning another repository. Repositories can keep their own guidance and toolchain.
|
|
17
|
-
|
|
18
|
-
To preview an installation in a noninteractive session, inspect the target and supply the explicit choices.
|
|
19
|
-
|
|
20
|
-
```sh
|
|
21
|
-
rtk proxy bunx --bun @apptoolkit/harness inspect --root /absolute/workspace --json
|
|
22
|
-
rtk proxy bunx --bun @apptoolkit/harness install --root /absolute/workspace --hosts codex,claude,opencode --local --repo-mode .=local --plan --json
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
Use `--yes` in place of `--plan` to apply a reviewed noninteractive plan. Select the workspace mode separately from each Git repository's generated files. Local mode uses the repository's `info/exclude` metadata for the planned files. Use `--repo-mode <path>=local|versioned` for each selected Git repository.
|
|
26
|
-
|
|
27
|
-
Use `rtk proxy bunx --bun @apptoolkit/harness@latest update --plan --json` or `rtk proxy npx @apptoolkit/harness@latest update --plan --json` to preview a release update. The updater checks managed files against the installation receipt. Resolve reported conflicts before applying the update. Keep project decisions in the installed local profile, and review the affected paths and version before applying.
|
|
28
|
-
|
|
29
|
-
Plane and Penpot are separate opt-ins. To make a provider available after installation, preview an update with `--enable-service plane` or `--enable-service penpot`, apply it, and complete the project connection through `init`. The installed runbooks explain instance setup, private credentials, authorization and readiness checks. Snapshot verification requires a versioned harness and project-level opt-in. Use Bun to install the isolated Biome dependency before first using the author style profile.
|
|
30
|
-
|
|
31
|
-
The installed local CLI reads the workflow index, retrieves one workflow at a time and checks Markdown against a local document policy. See `llm/HARNESS.md` for the exact commands. The agent records which operations are configured and which were verified in the current environment.
|
|
32
|
-
|
|
33
|
-
Distributed under the MIT license.
|
package/dist/bun/native/harness
DELETED