opencode-harness-kit 0.4.3 → 0.4.5

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 (74) hide show
  1. package/CHANGELOG.md +569 -18
  2. package/CONTRIBUTING.md +249 -0
  3. package/GLOBAL.md +34 -5
  4. package/MIGRATION.md +151 -0
  5. package/README.md +354 -66
  6. package/SECURITY.md +30 -0
  7. package/bin/baseline.mjs +15 -7
  8. package/bin/git-hooks/pre-commit +41 -9
  9. package/bin/oc-harness.mjs +1268 -82
  10. package/dist/config.d.ts +127 -0
  11. package/dist/denylist.d.ts +33 -0
  12. package/dist/effort.d.ts +64 -0
  13. package/dist/guard.d.ts +23 -0
  14. package/dist/health.d.ts +43 -0
  15. package/dist/index.d.ts +9 -0
  16. package/dist/index.js +532 -149
  17. package/dist/plugin.d.ts +15 -0
  18. package/dist/profile.d.ts +399 -0
  19. package/dist/project.d.ts +8 -0
  20. package/dist/prune.d.ts +6 -0
  21. package/dist/router.d.ts +3 -0
  22. package/dist/rules.d.ts +109 -0
  23. package/dist/safe.d.ts +7 -0
  24. package/dist/telemetry-store.d.ts +12 -0
  25. package/dist/telemetry.d.ts +3 -0
  26. package/docs/EXIT-CODES.md +83 -0
  27. package/docs/KNOWN-LIMITS.md +45 -21
  28. package/docs/RESEARCH.md +20 -5
  29. package/docs/ROUTING.md +191 -31
  30. package/eval/RESULTS.md +457 -0
  31. package/eval/ab.mjs +743 -0
  32. package/eval/attribute.mjs +170 -0
  33. package/eval/flags.mjs +88 -0
  34. package/eval/measure-install.mjs +331 -0
  35. package/eval/measure-prune.mjs +339 -0
  36. package/eval/metrics.js +79 -0
  37. package/eval/models.mjs +302 -0
  38. package/eval/premises.mjs +200 -0
  39. package/eval/prepare.mjs +233 -0
  40. package/eval/run.mjs +376 -0
  41. package/eval/tasks-self.json +81 -0
  42. package/eval/tasks-ts.json +50 -0
  43. package/eval/tasks.json +83 -0
  44. package/eval/thresholds.mjs +134 -0
  45. package/eval/verify.mjs +287 -0
  46. package/package.json +44 -17
  47. package/profiles/fleet-all.json +6 -1
  48. package/profiles/fleet-safe.json +7 -3
  49. package/profiles/schema.json +182 -51
  50. package/prompts/build.md +4 -2
  51. package/skills/space-build/SKILL.md +4 -2
  52. package/skills/space-finish/SKILL.md +6 -2
  53. package/skills/space-plan/reference/task-template.md +13 -5
  54. package/src/config.js +182 -32
  55. package/src/denylist.js +95 -0
  56. package/src/driver/run.mjs +81 -16
  57. package/src/effort.js +15 -4
  58. package/src/guard.ts +165 -13
  59. package/src/health.js +80 -0
  60. package/src/index.ts +15 -4
  61. package/src/lane-usage.js +72 -18
  62. package/src/plugin-type-check.ts +38 -0
  63. package/src/plugin.ts +39 -0
  64. package/src/profile.js +225 -26
  65. package/src/project.js +47 -0
  66. package/src/prune.ts +110 -31
  67. package/src/router.ts +32 -63
  68. package/src/rules.js +99 -7
  69. package/src/safe.ts +27 -0
  70. package/src/sqlite.js +144 -0
  71. package/src/tasks.js +112 -29
  72. package/src/telemetry-store.ts +62 -0
  73. package/src/telemetry.ts +60 -57
  74. package/src/trust.js +70 -9
package/bin/baseline.mjs CHANGED
@@ -19,18 +19,24 @@ const wantJson = args.includes("--json")
19
19
  const dbArg = args.indexOf("--db")
20
20
  const DB = dbArg >= 0 ? args[dbArg + 1] : join(homedir(), ".local/share/opencode/opencode.db")
21
21
 
22
+ const { canQuerySqlite, sqliteMissingMessage, query: queryDb } = await import("../src/sqlite.js")
23
+
22
24
  if (!existsSync(DB)) {
23
25
  console.error(`opencode database not found: ${DB}`)
24
26
  console.error("pass --db <path> or run opencode at least once first")
25
27
  process.exit(1)
26
28
  }
27
29
 
30
+ // The sqlite3 CLI, not the library. A missing tool is a thing a person can
31
+ // fix, and the failure used to be a raw `spawnSync sqlite3 ENOENT` stack
32
+ // trace.
33
+ if (!canQuerySqlite()) {
34
+ console.error(sqliteMissingMessage())
35
+ process.exit(1)
36
+ }
37
+
28
38
  function query(sql) {
29
- const out = execFileSync("sqlite3", ["-json", `file:${DB}?mode=ro`, sql], {
30
- encoding: "utf8",
31
- maxBuffer: 256 * 1024 * 1024,
32
- }).trim()
33
- return out ? JSON.parse(out) : []
39
+ return queryDb(DB, sql)
34
40
  }
35
41
 
36
42
  const ASSISTANT = `json_extract(data,'$.role')='assistant'`
@@ -163,7 +169,9 @@ const topAskers = () => {
163
169
  // allowlist, which meant the number it reported was whatever the list looked
164
170
  // like when the copy was last edited. Every tuning decision in this project is
165
171
  // supposed to rest on this measurement, so it has to measure the real list.
166
- const { BASH_ALLOWLIST } = await import(new URL("../src/config.js", import.meta.url))
172
+ const { BASH_ALLOWLIST } = await import(
173
+ new URL("../src/config.js", import.meta.url).href,
174
+ )
167
175
  const kitAllowlist = BASH_ALLOWLIST
168
176
  const currentAllow = [
169
177
  "git status *", "git log *", "git diff *", "grep *",
@@ -184,7 +192,7 @@ const paidEquivalent =
184
192
  //
185
193
  // This exists because the kit once shipped max_lines 200 / max_bytes 8192 on
186
194
  // the reasoning that tight truncation "saves context", and a later install
187
- // measured 415 of 2,959 reads exceeding 8 KB against 418 reads issued with an
195
+ // measured 415 of 2,966 reads exceeding 8 KB against 423 reads issued with an
188
196
  // `offset`. Truncation causes the re-read roughly one for one, and at the
189
197
  // measured ~17s median per request that round trip is more expensive than the
190
198
  // tokens it saves. Re-run this before changing these numbers again.
@@ -1,12 +1,23 @@
1
1
  #!/bin/sh
2
2
  # Installed by `oc-harness install`. Remove with: rm .git/hooks/pre-commit
3
3
  #
4
- # Runs the offline gate on every commit. The live-install half is deliberately
5
- # left out: measure and attribute read ~/.local/share/opencode, which is slow,
6
- # machine-specific, and irrelevant to whether a commit broke the kit.
4
+ # It runs the PROJECT's own checks, and only if the project has any.
7
5
  #
8
- # On a machine that has never run OpenCode, test:install cannot run at all, so
9
- # this hook uses the subset that needs nothing but the repository.
6
+ # The previous version ran `npm run test:all`, which is a script of THIS KIT,
7
+ # not of the project the hook was installed into. So in every project that
8
+ # installed the kit, every commit failed with:
9
+ #
10
+ # npm error Missing script: "test:all"
11
+ #
12
+ # until the author reached for --no-verify. A gate that blocks every commit
13
+ # is not a gate.
14
+ #
15
+ # The kit's own repository is the exception, and it is handled by the script
16
+ # list below: `test:all` is there, so the kit gates itself.
17
+ #
18
+ # The live-install half is deliberately left out: measure and attribute read
19
+ # ~/.local/share/opencode, which is slow, machine-specific, and irrelevant to
20
+ # whether a commit broke anything.
10
21
 
11
22
  set -e
12
23
 
@@ -18,13 +29,34 @@ if [ -n "$SKIP_SPACE_HARNESS_HOOK" ]; then
18
29
  exit 0
19
30
  fi
20
31
 
21
- echo "pre-commit: npm run test:all"
22
- if ! npm run test:all >/tmp/space-harness-hook.log 2>&1; then
32
+ # No package.json, no JavaScript project, no gate.
33
+ if [ ! -f package.json ]; then
34
+ exit 0
35
+ fi
36
+
37
+ # The gate is the project's own test script, if it has one. The kit's own
38
+ # repository has `test:all`, which is the offline half of its gate.
39
+ gate=""
40
+ if node -e "process.exit(require('./package.json').scripts?.['test:all'] ? 0 : 1)" 2>/dev/null; then
41
+ gate="test:all"
42
+ elif node -e "process.exit(require('./package.json').scripts?.test ? 0 : 1)" 2>/dev/null; then
43
+ gate="test"
44
+ fi
45
+
46
+ if [ -z "$gate" ]; then
47
+ # Nothing to run. A hook that blocks every commit because the project has
48
+ # no test script is worse than no hook.
49
+ exit 0
50
+ fi
51
+
52
+ log="${TMPDIR:-/tmp}/space-harness-hook.log"
53
+ echo "pre-commit: npm run $gate"
54
+ if ! npm run "$gate" >"$log" 2>&1; then
23
55
  echo "pre-commit: FAILED. Last lines:"
24
- tail -30 /tmp/space-harness-hook.log
56
+ tail -30 "$log"
25
57
  echo ""
26
58
  echo "Fix it, or commit with --no-verify if you are certain it is not yours."
27
59
  exit 1
28
60
  fi
29
61
 
30
- exit 0
62
+ exit 0