@tech-leads-club/harness-toolkit 0.3.0 → 0.3.2

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 (44) hide show
  1. package/README.md +46 -11
  2. package/bin/tlc-build.mjs +35 -6
  3. package/config.example.json +1 -1
  4. package/dist/chunks/compact-before-1e4qg1qt.mjs +1185 -0
  5. package/dist/chunks/compact-before-2hpbfxm5.mjs +5782 -0
  6. package/dist/chunks/compact-before-49j320yp.mjs +1283 -0
  7. package/dist/chunks/compact-before-4jrq0sqs.mjs +61 -0
  8. package/dist/chunks/compact-before-6w8n1vh1.mjs +186 -0
  9. package/dist/chunks/compact-before-7sdmwswh.mjs +52 -0
  10. package/dist/chunks/compact-before-beqpmqrm.mjs +187 -0
  11. package/dist/chunks/compact-before-j9y4jgn4.mjs +845 -0
  12. package/dist/chunks/compact-before-pk86tqx2.mjs +118 -0
  13. package/dist/chunks/compact-before-pkqk5v29.mjs +137 -0
  14. package/dist/chunks/compact-before-w1293m4n.mjs +315 -0
  15. package/dist/chunks/compact-before-wnnds45y.mjs +26 -0
  16. package/dist/chunks/compact-before-wt2c3nh4.mjs +551 -0
  17. package/dist/compact-before.mjs +13 -7961
  18. package/dist/doctor.mjs +33 -8480
  19. package/dist/help-topic.mjs +6 -14
  20. package/dist/init-project.mjs +36 -793
  21. package/dist/install-runtime.mjs +18 -1039
  22. package/dist/lessons-cli.mjs +25 -7043
  23. package/dist/obs-cli.mjs +27 -7037
  24. package/dist/price-lookup.mjs +11 -201
  25. package/dist/prompt-submit.mjs +14 -7974
  26. package/dist/refresh-model-prices.mjs +26 -7061
  27. package/dist/response-after.mjs +11 -7961
  28. package/dist/run.mjs +10 -7960
  29. package/dist/session-end.mjs +14 -8029
  30. package/dist/session-start.mjs +20 -8075
  31. package/dist/shim.mjs +18 -7024
  32. package/dist/stop.mjs +29 -8042
  33. package/dist/subagent-start.mjs +13 -7983
  34. package/dist/subagent-stop.mjs +11 -7961
  35. package/dist/support.mjs +21 -7168
  36. package/dist/tlc-cli.mjs +65 -8200
  37. package/dist/tool-after.mjs +20 -8176
  38. package/dist/tool-before.mjs +15 -7990
  39. package/dist/tool-failure.mjs +14 -7961
  40. package/dist/uninstall-runtime.mjs +61 -1008
  41. package/docs/log.md +4 -0
  42. package/package.json +2 -2
  43. package/src/core/release/release.version.ts +10 -4
  44. package/tools/install-runtime.ts +21 -1
package/README.md CHANGED
@@ -1,9 +1,46 @@
1
- # harness-toolkit
2
-
3
- Steers Cursor and Claude Code agents with **gates → follow-up → handoff → policy**.
4
-
5
- Hooks fire on the editor's own events. The harness answers each one with a decision — allow, ask, deny, or
6
- text injected into the turn — and writes a record of what it decided and why.
1
+ <p align="center">
2
+ <img src=".github/assets/logo.png" alt="Tech Leads Club" width="400" />
3
+ </p>
4
+
5
+ <p align="center">
6
+ <img src="https://img.shields.io/npm/v/@tech-leads-club/harness-toolkit?style=flat-square&color=blue" alt="npm version" />
7
+ <img src="https://img.shields.io/npm/dt/@tech-leads-club/harness-toolkit?style=flat-square&color=blue" alt="total downloads" />
8
+ <img src="https://img.shields.io/npm/dm/@tech-leads-club/harness-toolkit?style=flat-square&color=blue" alt="monthly downloads" />
9
+ <img src="https://img.shields.io/badge/license-PolyForm%20Noncommercial-blue?style=flat-square" alt="license" />
10
+ <img src="https://img.shields.io/github/actions/workflow/status/tech-leads-club/harness-toolkit/release.yml?style=flat-square" alt="build status" />
11
+ </p>
12
+
13
+ <p align="center">
14
+ <img src="https://img.shields.io/badge/Bun-recommended-black?style=flat-square&logo=bun" alt="bun" />
15
+ <img src="https://img.shields.io/badge/node-%3E%3D24-brightgreen?style=flat-square&logo=node.js" alt="node version" />
16
+ <img src="https://img.shields.io/badge/TypeScript-strict-blue?style=flat-square&logo=typescript" alt="typescript" />
17
+ <img src="https://img.shields.io/badge/provenance-SLSA%20v1-green?style=flat-square&logo=npm" alt="npm provenance" />
18
+ <img src="https://img.shields.io/badge/dependencies-0%20runtime-brightgreen?style=flat-square" alt="zero runtime dependencies" />
19
+ </p>
20
+
21
+ <p align="center">
22
+ <img src="https://img.shields.io/badge/Cursor-supported-black?style=flat-square" alt="cursor" />
23
+ <img src="https://img.shields.io/badge/Claude%20Code-supported-black?style=flat-square&logo=anthropic" alt="claude code" />
24
+ <img src="https://img.shields.io/badge/Linux%20%C2%B7%20macOS%20%C2%B7%20Windows-tested%20in%20CI-informational?style=flat-square" alt="platforms" />
25
+ </p>
26
+
27
+ <p align="center">
28
+ <img src="https://img.shields.io/github/stars/tech-leads-club/harness-toolkit?style=flat-square&color=yellow" alt="github stars" />
29
+ <img src="https://img.shields.io/github/contributors/tech-leads-club/harness-toolkit?style=flat-square&color=orange" alt="contributors" />
30
+ <img src="https://img.shields.io/github/last-commit/tech-leads-club/harness-toolkit?style=flat-square" alt="last commit" />
31
+ </p>
32
+
33
+ <h1 align="center">🛡️ Harness Toolkit</h1>
34
+
35
+ <p align="center">
36
+ <strong>Steers Cursor and Claude Code agents with gates → follow-up → handoff → policy</strong>
37
+ </p>
38
+
39
+ <p align="center">
40
+ Hooks fire on the editor's own events. The harness answers each one with a decision — <b>allow</b>, <b>ask</b>,
41
+ <b>deny</b>, or text injected into the turn — and writes a record of what it decided and why.
42
+ <b>7 floor rules</b> no configuration can reach, <b>3 always-on checks</b>, and <b>23 rails</b> you choose.
43
+ </p>
7
44
 
8
45
  - **[Everything it validates](#everything-it-validates)** — the whole list, one row per check
9
46
  - **[How to see any of it](#how-to-see-any-of-it)** — the command behind each row
@@ -12,8 +49,7 @@ text injected into the turn — and writes a record of what it decided and why.
12
49
  ## Start here
13
50
 
14
51
  ```bash
15
- npm i -g @tech-leads-club/harness-toolkit
16
- tlc harness install
52
+ npm i -g @tech-leads-club/harness-toolkit && tlc harness install
17
53
  ```
18
54
 
19
55
  Then restart Cursor or Claude Code. That is the whole setup — `install` finds which of the two you
@@ -222,11 +258,10 @@ three on every push; hooks firing inside an editor session on Windows are outsid
222
258
 
223
259
  ## Install
224
260
 
225
- The same two commands on every platform.
261
+ One command, the same on every platform.
226
262
 
227
263
  ```bash
228
- npm i -g @tech-leads-club/harness-toolkit
229
- tlc harness install
264
+ npm i -g @tech-leads-club/harness-toolkit && tlc harness install
230
265
  ```
231
266
 
232
267
  The package is the delivery vehicle and `tlc harness install` is what puts the runtime in place. They are
package/bin/tlc-build.mjs CHANGED
@@ -37,14 +37,37 @@ function sourcesIn(dir) {
37
37
  .map((entry) => ({ name: basename(entry.name, ".ts"), source: join(dir, entry.name) }));
38
38
  }
39
39
 
40
- function buildOne(source, out) {
40
+ /**
41
+ * why one invocation with every entry: `--splitting` can only share a chunk between entries it sees together.
42
+ * Built one at a time, each bundle inlined the whole core — measured, 24 bundles of ~257 KB each where more than
43
+ * half of every one was byte-identical to its neighbour: 5.0 MB of `dist/` to carry 548 KB of distinct code
44
+ * ([/decisions/ad-098.md](/decisions/ad-098.md)).
45
+ *
46
+ * invariant: the entry names stay flat and keep `.mjs`, because the launcher resolves `dist/<entry>.mjs` and the
47
+ * hooks on every installed machine name the launcher. Chunks go in a subdirectory, so pruning an orphan entry
48
+ * never has to tell the two apart.
49
+ */
50
+ const CHUNK_DIR = "chunks";
51
+
52
+ function build(targets) {
41
53
  const result = spawnSync(
42
54
  "bun",
43
- ["build", "--target=node", "--format=esm", `--outfile=${out}`, source],
55
+ [
56
+ "build",
57
+ "--target=node",
58
+ "--format=esm",
59
+ "--splitting",
60
+ `--outdir=${dist}`,
61
+ "--entry-naming",
62
+ "[name].mjs",
63
+ "--chunk-naming",
64
+ `${CHUNK_DIR}/[name]-[hash].mjs`,
65
+ ...targets.map((target) => target.source),
66
+ ],
44
67
  { stdio: "inherit" },
45
68
  );
46
69
  if (result.error?.code === "ENOENT") {
47
- console.error("tlc-build: Bun is not on PATH, and dist/ is committed so the bundler is part of the artefact.");
70
+ console.error("tlc-build: Bun is not on PATH, and it is the only bundler this builds with.");
48
71
  console.error(" curl -fsSL https://bun.sh/install | bash");
49
72
  process.exit(1);
50
73
  }
@@ -61,9 +84,15 @@ const targets = [
61
84
 
62
85
  mkdirSync(dist, { recursive: true });
63
86
  console.log(`tlc-build → ${dist}`);
64
- for (const target of targets) {
65
- buildOne(target.source, join(dist, `${target.name}.mjs`));
66
- }
87
+
88
+ /**
89
+ * hazard: chunk names carry a content hash, so a rebuild after a source change writes new ones and leaves the old
90
+ * ones behind. Nothing references them and they ship anyway, growing the package with every build.
91
+ *
92
+ * invariant: the chunk directory is derived, so it is replaced rather than merged.
93
+ */
94
+ rmSync(join(dist, CHUNK_DIR), { recursive: true, force: true });
95
+ build(targets);
67
96
 
68
97
  // invariant: the launcher stays executable on a filesystem that tracks the bit. A no-op where it does not.
69
98
  try {
@@ -2,7 +2,7 @@
2
2
  "version": 1,
3
3
  "mode": "solo",
4
4
  "subagents": {
5
- "enforceAllowlist": true,
5
+ "enforceAllowlist": false,
6
6
  "requireModel": true,
7
7
  "blockMode": "deny",
8
8
  "blockParentFast": false,