@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.
Files changed (240) hide show
  1. package/README.md +20 -45
  2. package/{dist/bun/npm/harness.js → harness.js} +3 -3
  3. package/package.json +9 -23
  4. package/{dist/bun/npm/payload → payload}/harness/runtime/harness.mjs +3 -3
  5. package/dist/apptoolkit-harness-1.0.0.tgz +0 -0
  6. package/dist/bun/apptoolkit-harness-1.0.0.tgz +0 -0
  7. package/dist/bun/native/README.md +0 -33
  8. package/dist/bun/native/harness +0 -4
  9. package/dist/bun/native/payload/harness/runtime/harness.mjs +0 -104
  10. package/dist/bun/npm/LICENSE +0 -21
  11. package/dist/bun/npm/README.md +0 -33
  12. package/dist/bun/npm/package.json +0 -23
  13. package/dist/bun/npm/payload/HARNESS.md +0 -21
  14. package/dist/bun/npm/payload/author-style/README.md +0 -56
  15. package/dist/bun/npm/payload/author-style/biome-core.json +0 -57
  16. package/dist/bun/npm/payload/author-style/biome-react.json +0 -9
  17. package/dist/bun/npm/payload/author-style/biome-sql.json +0 -9
  18. package/dist/bun/npm/payload/author-style/bun.lock +0 -37
  19. package/dist/bun/npm/payload/author-style/check.llm.md +0 -17
  20. package/dist/bun/npm/payload/author-style/check.test.llm.md +0 -17
  21. package/dist/bun/npm/payload/author-style/check.test.ts +0 -238
  22. package/dist/bun/npm/payload/author-style/check.ts +0 -181
  23. package/dist/bun/npm/payload/author-style/member-spacing.test.ts +0 -172
  24. package/dist/bun/npm/payload/author-style/member-spacing.ts +0 -106
  25. package/dist/bun/npm/payload/author-style/package.json +0 -18
  26. package/dist/bun/npm/payload/author-style/plugins/class-member-order.grit +0 -133
  27. package/dist/bun/npm/payload/author-style/plugins/event-handler-names.grit +0 -110
  28. package/dist/bun/npm/payload/author-style/plugins/explicit-arrow-body.grit +0 -15
  29. package/dist/bun/npm/payload/author-style/plugins/explicit-source-constructs.grit +0 -10
  30. package/dist/bun/npm/payload/author-style/plugins/react-arrow-body.grit +0 -85
  31. package/dist/bun/npm/payload/author-style/plugins/sql-style.grit +0 -125
  32. package/dist/bun/npm/payload/author-style/react-module.llm.md +0 -17
  33. package/dist/bun/npm/payload/author-style/react-module.test.ts +0 -150
  34. package/dist/bun/npm/payload/author-style/react-module.ts +0 -255
  35. package/dist/bun/npm/payload/author-style/source-policy.llm.md +0 -17
  36. package/dist/bun/npm/payload/author-style/source-policy.test.ts +0 -70
  37. package/dist/bun/npm/payload/author-style/source-policy.ts +0 -215
  38. package/dist/bun/npm/payload/author-style/spacing.llm.md +0 -17
  39. package/dist/bun/npm/payload/author-style/spacing.test.ts +0 -174
  40. package/dist/bun/npm/payload/author-style/spacing.ts +0 -211
  41. package/dist/bun/npm/payload/harness/POLICY.md +0 -33
  42. package/dist/bun/npm/payload/harness/PROJECT.md +0 -26
  43. package/dist/bun/npm/payload/harness/REVIEW.md +0 -17
  44. package/dist/bun/npm/payload/harness/TEMPLATES.md +0 -20
  45. package/dist/bun/npm/payload/harness/WORKFLOWS.md +0 -65
  46. package/dist/bun/npm/payload/harness/runtime/ZOD-LICENSE +0 -21
  47. package/dist/bun/npm/payload/harness/services/README.md +0 -26
  48. package/dist/bun/npm/payload/harness/services/penpot.json +0 -7
  49. package/dist/bun/npm/payload/harness/services/plane.json +0 -9
  50. package/dist/bun/npm/payload/harness/workflows/W01.md +0 -13
  51. package/dist/bun/npm/payload/harness/workflows/W02.md +0 -13
  52. package/dist/bun/npm/payload/harness/workflows/W03.md +0 -13
  53. package/dist/bun/npm/payload/harness/workflows/W04.md +0 -13
  54. package/dist/bun/npm/payload/harness/workflows/W05.md +0 -13
  55. package/dist/bun/npm/payload/harness/workflows/W06.md +0 -13
  56. package/dist/bun/npm/payload/harness/workflows/W07.md +0 -13
  57. package/dist/bun/npm/payload/harness/workflows/W08.md +0 -13
  58. package/dist/bun/npm/payload/harness/workflows/W09.md +0 -13
  59. package/dist/bun/npm/payload/harness/workflows/W10.md +0 -13
  60. package/dist/bun/npm/payload/harness/workflows/W11.md +0 -13
  61. package/dist/bun/npm/payload/harness/workflows/W12.md +0 -13
  62. package/dist/bun/npm/payload/harness/workflows/W13.md +0 -13
  63. package/dist/bun/npm/payload/harness/workflows/W14.md +0 -13
  64. package/dist/bun/npm/payload/harness/workflows/W15.md +0 -13
  65. package/dist/bun/npm/payload/harness/workflows/W16.md +0 -13
  66. package/dist/bun/npm/payload/harness/workflows/W17.md +0 -13
  67. package/dist/bun/npm/payload/harness/workflows/W18.md +0 -13
  68. package/dist/bun/npm/payload/harness/workflows/W19.md +0 -13
  69. package/dist/bun/npm/payload/harness/workflows/W20.md +0 -13
  70. package/dist/bun/npm/payload/harness/workflows/W21.md +0 -15
  71. package/dist/bun/npm/payload/harness/workflows/W22.md +0 -13
  72. package/dist/bun/npm/payload/harness/workflows/W23.md +0 -21
  73. package/dist/bun/npm/payload/harness/workflows/W24.md +0 -13
  74. package/dist/bun/npm/payload/harness/workflows/W25.md +0 -13
  75. package/dist/bun/npm/payload/harness/workflows/W26.md +0 -13
  76. package/dist/bun/npm/payload/harness/workflows/W27.md +0 -13
  77. package/dist/bun/npm/payload/harness/workflows/W28.md +0 -13
  78. package/dist/bun/npm/payload/harness/workflows/W29.md +0 -13
  79. package/dist/bun/npm/payload/harness/workflows/W30.md +0 -13
  80. package/dist/bun/npm/payload/harness/workflows/W31.md +0 -13
  81. package/dist/bun/npm/payload/harness/workflows/W32.md +0 -13
  82. package/dist/bun/npm/payload/harness/workflows/W33.md +0 -13
  83. package/dist/bun/npm/payload/harness/workflows/W34.md +0 -13
  84. package/dist/bun/npm/payload/harness/workflows/W35.md +0 -13
  85. package/dist/bun/npm/payload/harness/workflows/W36.md +0 -13
  86. package/dist/bun/npm/payload/harness/workflows/W37.md +0 -13
  87. package/dist/npm/LICENSE +0 -21
  88. package/dist/npm/README.md +0 -30
  89. package/dist/npm/harness.js +0 -104
  90. package/dist/npm/package.json +0 -25
  91. package/dist/npm/payload/HARNESS.md +0 -21
  92. package/dist/npm/payload/author-style/README.md +0 -56
  93. package/dist/npm/payload/author-style/biome-core.json +0 -57
  94. package/dist/npm/payload/author-style/biome-react.json +0 -9
  95. package/dist/npm/payload/author-style/biome-sql.json +0 -9
  96. package/dist/npm/payload/author-style/check.llm.md +0 -17
  97. package/dist/npm/payload/author-style/check.test.llm.md +0 -17
  98. package/dist/npm/payload/author-style/check.test.ts +0 -224
  99. package/dist/npm/payload/author-style/check.ts +0 -179
  100. package/dist/npm/payload/author-style/member-spacing.test.ts +0 -172
  101. package/dist/npm/payload/author-style/member-spacing.ts +0 -106
  102. package/dist/npm/payload/author-style/package-lock.json +0 -180
  103. package/dist/npm/payload/author-style/package.json +0 -17
  104. package/dist/npm/payload/author-style/plugins/class-member-order.grit +0 -133
  105. package/dist/npm/payload/author-style/plugins/event-handler-names.grit +0 -110
  106. package/dist/npm/payload/author-style/plugins/explicit-arrow-body.grit +0 -15
  107. package/dist/npm/payload/author-style/plugins/explicit-source-constructs.grit +0 -10
  108. package/dist/npm/payload/author-style/plugins/react-arrow-body.grit +0 -85
  109. package/dist/npm/payload/author-style/plugins/sql-style.grit +0 -125
  110. package/dist/npm/payload/author-style/react-module.llm.md +0 -17
  111. package/dist/npm/payload/author-style/react-module.test.ts +0 -150
  112. package/dist/npm/payload/author-style/react-module.ts +0 -255
  113. package/dist/npm/payload/author-style/source-policy.llm.md +0 -17
  114. package/dist/npm/payload/author-style/source-policy.test.ts +0 -70
  115. package/dist/npm/payload/author-style/source-policy.ts +0 -215
  116. package/dist/npm/payload/author-style/spacing.llm.md +0 -17
  117. package/dist/npm/payload/author-style/spacing.test.ts +0 -174
  118. package/dist/npm/payload/author-style/spacing.ts +0 -211
  119. package/dist/npm/payload/harness/POLICY.md +0 -33
  120. package/dist/npm/payload/harness/PROJECT.md +0 -26
  121. package/dist/npm/payload/harness/REVIEW.md +0 -17
  122. package/dist/npm/payload/harness/TEMPLATES.md +0 -20
  123. package/dist/npm/payload/harness/WORKFLOWS.md +0 -65
  124. package/dist/npm/payload/harness/runtime/ZOD-LICENSE +0 -21
  125. package/dist/npm/payload/harness/runtime/harness.mjs +0 -104
  126. package/dist/npm/payload/harness/services/README.md +0 -26
  127. package/dist/npm/payload/harness/services/penpot.json +0 -7
  128. package/dist/npm/payload/harness/services/plane.json +0 -9
  129. package/dist/npm/payload/harness/workflows/W01.md +0 -13
  130. package/dist/npm/payload/harness/workflows/W02.md +0 -13
  131. package/dist/npm/payload/harness/workflows/W03.md +0 -13
  132. package/dist/npm/payload/harness/workflows/W04.md +0 -13
  133. package/dist/npm/payload/harness/workflows/W05.md +0 -13
  134. package/dist/npm/payload/harness/workflows/W06.md +0 -13
  135. package/dist/npm/payload/harness/workflows/W07.md +0 -13
  136. package/dist/npm/payload/harness/workflows/W08.md +0 -13
  137. package/dist/npm/payload/harness/workflows/W09.md +0 -13
  138. package/dist/npm/payload/harness/workflows/W10.md +0 -13
  139. package/dist/npm/payload/harness/workflows/W11.md +0 -13
  140. package/dist/npm/payload/harness/workflows/W12.md +0 -13
  141. package/dist/npm/payload/harness/workflows/W13.md +0 -13
  142. package/dist/npm/payload/harness/workflows/W14.md +0 -13
  143. package/dist/npm/payload/harness/workflows/W15.md +0 -13
  144. package/dist/npm/payload/harness/workflows/W16.md +0 -13
  145. package/dist/npm/payload/harness/workflows/W17.md +0 -13
  146. package/dist/npm/payload/harness/workflows/W18.md +0 -13
  147. package/dist/npm/payload/harness/workflows/W19.md +0 -13
  148. package/dist/npm/payload/harness/workflows/W20.md +0 -13
  149. package/dist/npm/payload/harness/workflows/W21.md +0 -15
  150. package/dist/npm/payload/harness/workflows/W22.md +0 -13
  151. package/dist/npm/payload/harness/workflows/W23.md +0 -21
  152. package/dist/npm/payload/harness/workflows/W24.md +0 -13
  153. package/dist/npm/payload/harness/workflows/W25.md +0 -13
  154. package/dist/npm/payload/harness/workflows/W26.md +0 -13
  155. package/dist/npm/payload/harness/workflows/W27.md +0 -13
  156. package/dist/npm/payload/harness/workflows/W28.md +0 -13
  157. package/dist/npm/payload/harness/workflows/W29.md +0 -13
  158. package/dist/npm/payload/harness/workflows/W30.md +0 -13
  159. package/dist/npm/payload/harness/workflows/W31.md +0 -13
  160. package/dist/npm/payload/harness/workflows/W32.md +0 -13
  161. package/dist/npm/payload/harness/workflows/W33.md +0 -13
  162. package/dist/npm/payload/harness/workflows/W34.md +0 -13
  163. package/dist/npm/payload/harness/workflows/W35.md +0 -13
  164. package/dist/npm/payload/harness/workflows/W36.md +0 -13
  165. package/dist/npm/payload/harness/workflows/W37.md +0 -13
  166. /package/{dist/bun/native/LICENSE → LICENSE} +0 -0
  167. /package/{dist/bun/native/payload → payload}/HARNESS.md +0 -0
  168. /package/{dist/bun/native/payload → payload}/author-style/README.md +0 -0
  169. /package/{dist/bun/native/payload → payload}/author-style/biome-core.json +0 -0
  170. /package/{dist/bun/native/payload → payload}/author-style/biome-react.json +0 -0
  171. /package/{dist/bun/native/payload → payload}/author-style/biome-sql.json +0 -0
  172. /package/{dist/bun/native/payload → payload}/author-style/bun.lock +0 -0
  173. /package/{dist/bun/native/payload → payload}/author-style/check.llm.md +0 -0
  174. /package/{dist/bun/native/payload → payload}/author-style/check.test.llm.md +0 -0
  175. /package/{dist/bun/native/payload → payload}/author-style/check.test.ts +0 -0
  176. /package/{dist/bun/native/payload → payload}/author-style/check.ts +0 -0
  177. /package/{dist/bun/native/payload → payload}/author-style/member-spacing.test.ts +0 -0
  178. /package/{dist/bun/native/payload → payload}/author-style/member-spacing.ts +0 -0
  179. /package/{dist/bun/native/payload → payload}/author-style/package.json +0 -0
  180. /package/{dist/bun/native/payload → payload}/author-style/plugins/class-member-order.grit +0 -0
  181. /package/{dist/bun/native/payload → payload}/author-style/plugins/event-handler-names.grit +0 -0
  182. /package/{dist/bun/native/payload → payload}/author-style/plugins/explicit-arrow-body.grit +0 -0
  183. /package/{dist/bun/native/payload → payload}/author-style/plugins/explicit-source-constructs.grit +0 -0
  184. /package/{dist/bun/native/payload → payload}/author-style/plugins/react-arrow-body.grit +0 -0
  185. /package/{dist/bun/native/payload → payload}/author-style/plugins/sql-style.grit +0 -0
  186. /package/{dist/bun/native/payload → payload}/author-style/react-module.llm.md +0 -0
  187. /package/{dist/bun/native/payload → payload}/author-style/react-module.test.ts +0 -0
  188. /package/{dist/bun/native/payload → payload}/author-style/react-module.ts +0 -0
  189. /package/{dist/bun/native/payload → payload}/author-style/source-policy.llm.md +0 -0
  190. /package/{dist/bun/native/payload → payload}/author-style/source-policy.test.ts +0 -0
  191. /package/{dist/bun/native/payload → payload}/author-style/source-policy.ts +0 -0
  192. /package/{dist/bun/native/payload → payload}/author-style/spacing.llm.md +0 -0
  193. /package/{dist/bun/native/payload → payload}/author-style/spacing.test.ts +0 -0
  194. /package/{dist/bun/native/payload → payload}/author-style/spacing.ts +0 -0
  195. /package/{dist/bun/native/payload → payload}/harness/POLICY.md +0 -0
  196. /package/{dist/bun/native/payload → payload}/harness/PROJECT.md +0 -0
  197. /package/{dist/bun/native/payload → payload}/harness/REVIEW.md +0 -0
  198. /package/{dist/bun/native/payload → payload}/harness/TEMPLATES.md +0 -0
  199. /package/{dist/bun/native/payload → payload}/harness/WORKFLOWS.md +0 -0
  200. /package/{dist/bun/native/payload → payload}/harness/runtime/ZOD-LICENSE +0 -0
  201. /package/{dist/bun/native/payload → payload}/harness/services/README.md +0 -0
  202. /package/{dist/bun/native/payload → payload}/harness/services/penpot.json +0 -0
  203. /package/{dist/bun/native/payload → payload}/harness/services/plane.json +0 -0
  204. /package/{dist/bun/native/payload → payload}/harness/workflows/W01.md +0 -0
  205. /package/{dist/bun/native/payload → payload}/harness/workflows/W02.md +0 -0
  206. /package/{dist/bun/native/payload → payload}/harness/workflows/W03.md +0 -0
  207. /package/{dist/bun/native/payload → payload}/harness/workflows/W04.md +0 -0
  208. /package/{dist/bun/native/payload → payload}/harness/workflows/W05.md +0 -0
  209. /package/{dist/bun/native/payload → payload}/harness/workflows/W06.md +0 -0
  210. /package/{dist/bun/native/payload → payload}/harness/workflows/W07.md +0 -0
  211. /package/{dist/bun/native/payload → payload}/harness/workflows/W08.md +0 -0
  212. /package/{dist/bun/native/payload → payload}/harness/workflows/W09.md +0 -0
  213. /package/{dist/bun/native/payload → payload}/harness/workflows/W10.md +0 -0
  214. /package/{dist/bun/native/payload → payload}/harness/workflows/W11.md +0 -0
  215. /package/{dist/bun/native/payload → payload}/harness/workflows/W12.md +0 -0
  216. /package/{dist/bun/native/payload → payload}/harness/workflows/W13.md +0 -0
  217. /package/{dist/bun/native/payload → payload}/harness/workflows/W14.md +0 -0
  218. /package/{dist/bun/native/payload → payload}/harness/workflows/W15.md +0 -0
  219. /package/{dist/bun/native/payload → payload}/harness/workflows/W16.md +0 -0
  220. /package/{dist/bun/native/payload → payload}/harness/workflows/W17.md +0 -0
  221. /package/{dist/bun/native/payload → payload}/harness/workflows/W18.md +0 -0
  222. /package/{dist/bun/native/payload → payload}/harness/workflows/W19.md +0 -0
  223. /package/{dist/bun/native/payload → payload}/harness/workflows/W20.md +0 -0
  224. /package/{dist/bun/native/payload → payload}/harness/workflows/W21.md +0 -0
  225. /package/{dist/bun/native/payload → payload}/harness/workflows/W22.md +0 -0
  226. /package/{dist/bun/native/payload → payload}/harness/workflows/W23.md +0 -0
  227. /package/{dist/bun/native/payload → payload}/harness/workflows/W24.md +0 -0
  228. /package/{dist/bun/native/payload → payload}/harness/workflows/W25.md +0 -0
  229. /package/{dist/bun/native/payload → payload}/harness/workflows/W26.md +0 -0
  230. /package/{dist/bun/native/payload → payload}/harness/workflows/W27.md +0 -0
  231. /package/{dist/bun/native/payload → payload}/harness/workflows/W28.md +0 -0
  232. /package/{dist/bun/native/payload → payload}/harness/workflows/W29.md +0 -0
  233. /package/{dist/bun/native/payload → payload}/harness/workflows/W30.md +0 -0
  234. /package/{dist/bun/native/payload → payload}/harness/workflows/W31.md +0 -0
  235. /package/{dist/bun/native/payload → payload}/harness/workflows/W32.md +0 -0
  236. /package/{dist/bun/native/payload → payload}/harness/workflows/W33.md +0 -0
  237. /package/{dist/bun/native/payload → payload}/harness/workflows/W34.md +0 -0
  238. /package/{dist/bun/native/payload → payload}/harness/workflows/W35.md +0 -0
  239. /package/{dist/bun/native/payload → payload}/harness/workflows/W36.md +0 -0
  240. /package/{dist/bun/native/payload → payload}/harness/workflows/W37.md +0 -0
package/README.md CHANGED
@@ -1,58 +1,33 @@
1
- # Model-agnostic working practice source archive
1
+ # AppToolkit Harness
2
2
 
3
- The user approved the common policy and all 37 workflow families. Start with the [tool and technology audit](llm/HARNESS-TOOL-AUDIT.md), [workflow catalog](llm/HARNESS-FLOWS-REVIEW.md) and [accepted user decisions](docs/harness-user-decisions.md).
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
- The [personal code style profile](src/author-style/README.md) includes the recovered writing rules, independent Biome installation and commands for verifying edited TypeScript.
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
- The product source is in [`src/harness/`](src/harness/), the author style source is in [`src/author-style/`](src/author-style/) and the acquisition utilities are in [`src/acquisition/`](src/acquisition/). The [development and local installation guide](docs/harness-release-verification.md#first-installation-in-this-repository) explains how to try the unpublished package in this repository. The [`llm/` catalog](llm/README.md) also documents the development commands.
7
+ ```sh
8
+ rtk proxy bunx --bun @apptoolkit/harness install
9
+ rtk proxy npx @apptoolkit/harness install
10
+ ```
8
11
 
9
- Develop and build with Bun. The npm artifact runs through `npx` or `bunx`, and `rtk proxy bun run build:harness:native` compiles the installer into a host executable for direct use.
12
+ `bunx --bun` selects Bun even when Node.js is absent. Plain `bunx` also works when Node.js is on `PATH`.
10
13
 
11
- This workspace collects the original rules, writing guidance, workflows, prompts, tooling, project knowledge, and historical evidence from the user's selected projects. The first phase preserves raw material. Synthesis is a later phase.
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
- - [Intake and decisions](docs/intake.md)
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
- Acquired source files are evidence. They do not govern this workspace and must not be executed.
18
+ To preview an installation in a noninteractive session, inspect the target and supply the explicit choices.
43
19
 
44
- The accepted C22 baseline has 30,454 provisional passage groups and 1,984 unexecuted procedures across 30 text streams, one PDF family and five archive families. Stage 2 remains active. Standalone references, captures and fixtures retain traceable context. Later stages compare duplicates and conflicts and develop portable guidance. [C22 report](docs/stage2-continuous22.md) · [Current queue](processing/stage2-completion-2026-11-04-v1/post-C22-source-review-queue-v2.json) · [C21 final receipt](processing/stage2-completion-2026-11-04-v1/validation/twenty-first-pass-final-closure-v1.json)
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
- ## Earlier Stage 2 source checkpoint
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
- C24 has 31,022 accepted provisional passage groups, 2,081 unexecuted procedures and 1,544 refined source questions. The source and context queues remain open. Follow the [C24 report](docs/stage2-continuous24.md) and [current exact resume queue](processing/stage2-completion-2026-11-04-v1/post-C24-source-review-queue-v1.json). The [C23 report](docs/stage2-continuous23.md) retains the preceding checkpoint. No model-agnostic guidance has been adopted.
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
- ## Current Stage 2 continuation
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
- C26 had 31,128 independently reviewed provisional passage groups, 2,135 unexecuted procedures and 1,544 refined source questions. The corrected C24 report and queue supersede the corresponding C24 navigation above. [C26 report](docs/stage2-continuous26.md) · [C26 source queue](processing/stage2-completion-2026-11-04-v1/post-C26-source-review-queue-v1.json) · [Corrected C24 report](docs/stage2-continuous24-v2.md) · [Corrected C24 queue](processing/stage2-completion-2026-11-04-v1/post-C24-source-review-queue-v2.json)
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
- C62 has 130,975 independently reviewed provisional groups, 13,744 unexecuted procedures, 1,558 refined source questions and 962 separately typed source contexts. Stage 2 remains open. [C62 report](docs/stage2-continuous62.md) · [Current source queue](processing/stage2-completion-2026-11-04-v1/post-C62-source-review-queue-v1.json) · [C61 report](docs/stage2-continuous61.md)
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.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.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.0",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}
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.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
- "packageManager": "bun@1.4.2",
7
+ "bin": {
8
+ "harness": "./harness.js"
9
+ },
7
10
  "files": [
8
- "dist/"
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.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.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.0",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}
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
@@ -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.
@@ -1,4 +0,0 @@
1
- [diffend] Oversized file quarantined before diffing.
2
- name: package/dist/bun/native/harness
3
- size: 63267186 bytes
4
- sha256: 073a12fd1b3f9c7430961f47079e444d46cd0be30116156c7677beaba0660070