spexcode 0.2.8 → 0.4.0

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 (101) hide show
  1. package/README.md +56 -44
  2. package/package.json +3 -3
  3. package/spec-cli/bin/spex.mjs +2 -2
  4. package/spec-cli/hooks/dispatch.sh +1 -1
  5. package/spec-cli/hooks/harness.sh +26 -6
  6. package/spec-cli/src/anchors.ts +300 -0
  7. package/spec-cli/src/attach.ts +2 -2
  8. package/spec-cli/src/cli.ts +691 -536
  9. package/spec-cli/src/client.ts +31 -30
  10. package/spec-cli/src/contract-filter.ts +1 -1
  11. package/spec-cli/src/doctor.ts +40 -13
  12. package/spec-cli/src/gateway.ts +11 -7
  13. package/spec-cli/src/git.ts +23 -15
  14. package/spec-cli/src/{board.ts → graph.ts} +44 -14
  15. package/spec-cli/src/{boardCache.ts → graphCache.ts} +41 -21
  16. package/spec-cli/src/{boardDelta.ts → graphDelta.ts} +1 -1
  17. package/spec-cli/src/graphStream.ts +288 -0
  18. package/spec-cli/src/guide.ts +142 -98
  19. package/spec-cli/src/harness-select.ts +2 -2
  20. package/spec-cli/src/harness.ts +30 -14
  21. package/spec-cli/src/help.ts +300 -385
  22. package/spec-cli/src/hooks.ts +1 -1
  23. package/spec-cli/src/index.ts +144 -103
  24. package/spec-cli/src/init.ts +14 -13
  25. package/spec-cli/src/issues.ts +89 -33
  26. package/spec-cli/src/layout.ts +5 -5
  27. package/spec-cli/src/lint.ts +128 -30
  28. package/spec-cli/src/localIssues.ts +61 -60
  29. package/spec-cli/src/materialize.ts +1 -1
  30. package/spec-cli/src/mentions.ts +15 -15
  31. package/spec-cli/src/migrate-table.ts +398 -0
  32. package/spec-cli/src/migrate.ts +386 -0
  33. package/spec-cli/src/ranker.ts +30 -4
  34. package/spec-cli/src/reaper.ts +117 -0
  35. package/spec-cli/src/search.bench.mjs +12 -12
  36. package/spec-cli/src/search.ts +1 -1
  37. package/spec-cli/src/sessions.ts +244 -138
  38. package/spec-cli/src/specs.ts +40 -25
  39. package/spec-cli/src/supervise.ts +2 -2
  40. package/spec-cli/src/tree.ts +5 -5
  41. package/spec-cli/src/uninstall.ts +4 -4
  42. package/spec-cli/templates/hooks/post-checkout +1 -1
  43. package/spec-cli/templates/hooks/post-merge +3 -3
  44. package/spec-cli/templates/hooks/pre-commit +9 -9
  45. package/spec-cli/templates/hooks/prepare-commit-msg +1 -1
  46. package/spec-cli/templates/spec/project/{.config → .plugins}/core/idle/idle.sh +2 -2
  47. package/spec-cli/templates/spec/project/{.config → .plugins}/core/mark-active/mark-active.sh +7 -0
  48. package/spec-cli/templates/spec/project/{.config → .plugins}/core/mark-active/spec.md +2 -0
  49. package/spec-cli/templates/spec/project/{.config → .plugins}/core/session-fail/fail.sh +1 -1
  50. package/spec-cli/templates/spec/project/{.config → .plugins}/core/spec-first/spec-first.sh +1 -1
  51. package/spec-cli/templates/spec/project/{.config → .plugins}/core/spec-of-file/spec-of-file.sh +2 -2
  52. package/spec-cli/templates/spec/project/.plugins/core/spec.md +21 -0
  53. package/spec-cli/templates/spec/project/{.config → .plugins}/core/stop-gate/stop-gate.sh +21 -21
  54. package/spec-cli/templates/spec/project/{.config → .plugins}/distill/spec.md +2 -2
  55. package/spec-cli/templates/spec/project/{.config → .plugins}/extract/spec.md +5 -5
  56. package/spec-cli/templates/spec/project/{.config → .plugins/prompts}/forge-link/spec.md +1 -1
  57. package/spec-cli/templates/spec/project/{.config → .plugins/prompts}/reproduce-before-fix/spec.md +3 -3
  58. package/spec-cli/templates/spec/project/.plugins/prompts/spec.md +20 -0
  59. package/spec-cli/templates/spec/project/{.config → .plugins}/regroup/spec.md +2 -2
  60. package/spec-cli/templates/spec/project/.plugins/spec.md +18 -0
  61. package/spec-cli/templates/spec/project/.plugins/supervisor/spec.md +8 -0
  62. package/spec-cli/templates/spec/project/{.config → .plugins}/tidy/spec.md +1 -1
  63. package/spec-cli/templates/spec/project/spec.md +1 -1
  64. package/spec-dashboard/dist/assets/{Dashboard-P0B9ukSG.js → Dashboard-CTcH2eW9.js} +9 -9
  65. package/spec-dashboard/dist/assets/EvalsPage-CJNKwHLN.js +2 -0
  66. package/spec-dashboard/dist/assets/{FoldToggle-BuQ0lokE.js → FoldToggle-CVFbBpyW.js} +1 -1
  67. package/spec-dashboard/dist/assets/{IssuesPage-H-D8aHEl.js → IssuesPage-kULjonqj.js} +1 -1
  68. package/spec-dashboard/dist/assets/{MobileApp-oZXIeCPb.js → MobileApp-B0ZJju8K.js} +1 -1
  69. package/spec-dashboard/dist/assets/{SessionInterface-Blr_MEdU.js → SessionInterface-BRKJqU2U.js} +3 -3
  70. package/spec-dashboard/dist/assets/{SessionWindow-LcCzBMU7.js → SessionWindow-CDhEL7wO.js} +7 -7
  71. package/spec-dashboard/dist/assets/{Settings-_yOye-In.js → Settings-BL6FV_8S.js} +1 -1
  72. package/spec-dashboard/dist/assets/{index-uGs9v_9o.css → index-DmQsNYKK.css} +1 -1
  73. package/spec-dashboard/dist/assets/{index-BhIslAau.js → index-DulGPk6A.js} +8 -8
  74. package/spec-dashboard/dist/index.html +2 -2
  75. package/{spec-yatsu → spec-eval}/src/cache.ts +8 -5
  76. package/{spec-yatsu → spec-eval}/src/cli.ts +212 -96
  77. package/{spec-yatsu → spec-eval}/src/evaltab.ts +35 -27
  78. package/{spec-yatsu → spec-eval}/src/filing.ts +7 -5
  79. package/{spec-yatsu → spec-eval}/src/freshness.ts +44 -22
  80. package/spec-eval/src/humanok.ts +43 -0
  81. package/{spec-yatsu → spec-eval}/src/scenariofresh.ts +22 -17
  82. package/{spec-yatsu/src/yatsu.ts → spec-eval/src/scenarios.ts} +41 -26
  83. package/{spec-yatsu/src/proof.ts → spec-eval/src/sessioneval.ts} +59 -59
  84. package/{spec-yatsu → spec-eval}/src/sidecar.ts +42 -10
  85. package/{spec-yatsu → spec-eval}/src/timeline.ts +1 -1
  86. package/spec-forge/src/__fixtures__/github-forge.json +9 -9
  87. package/spec-forge/src/cli.ts +14 -13
  88. package/spec-forge/src/{needs-yatsu-eval.ts → needs-eval.ts} +6 -6
  89. package/spec-cli/src/boardStream.ts +0 -179
  90. package/spec-cli/templates/presets/careful/.config/clarify-before-code/spec.md +0 -11
  91. package/spec-cli/templates/spec/project/.config/core/spec.md +0 -17
  92. package/spec-cli/templates/spec/project/.config/spec.md +0 -15
  93. package/spec-cli/templates/spec/project/.config/supervisor/spec.md +0 -8
  94. package/spec-dashboard/dist/assets/EvalsPage-BrvAGyc4.js +0 -2
  95. /package/spec-cli/templates/spec/project/{.config → .plugins}/core/idle/spec.md +0 -0
  96. /package/spec-cli/templates/spec/project/{.config → .plugins}/core/session-fail/spec.md +0 -0
  97. /package/spec-cli/templates/spec/project/{.config → .plugins}/core/spec-first/spec.md +0 -0
  98. /package/spec-cli/templates/spec/project/{.config → .plugins}/core/spec-of-file/spec.md +0 -0
  99. /package/spec-cli/templates/spec/project/{.config → .plugins}/core/stop-gate/spec.md +0 -0
  100. /package/spec-cli/templates/spec/project/{.config → .plugins}/distill/digest.mjs +0 -0
  101. /package/spec-cli/templates/spec/project/{.config → .plugins/prompts}/memory-hygiene/spec.md +0 -0
@@ -1,9 +1,9 @@
1
- // throwaway benchmark harness for spec-search — drives the REAL `spex search --json` over the holdout
2
- // cases and reports recall@1, recall@3, MRR. The cases live in the node's yatsu.md.
1
+ // throwaway benchmark harness for spec-search — drives the REAL `spex spec search --json` over the holdout
2
+ // cases and reports recall@1, recall@3, MRR. The cases live in the node's eval.md.
3
3
  //
4
4
  // Labels are node LEAF names, matched with the same de-collision rule the loader applies (specs.ts reId):
5
5
  // a returned id matches a label if it IS the label or ends with `_<label>` — so a bare leaf keeps matching
6
- // after collision-qualification renames it (e.g. `spec-scout` → `injected-context_spec-scout`). A label may
6
+ // after collision-qualification renames it (e.g. a colliding `probe` leaf → `a_probe`). A label may
7
7
  // also be written pre-qualified to pin one collision branch.
8
8
  import { execFileSync } from 'node:child_process'
9
9
  import { fileURLToPath } from 'node:url'
@@ -21,12 +21,12 @@ const CASES = [
21
21
  ['session-order', 'how is the order of sessions in the session list decided?', ['session-console']],
22
22
  ['node-status', 'what makes a node show as pending vs active vs merged vs drift?', ['spec-node-states']],
23
23
  ['dashboard-backend', 'how does the dashboard reach the backend API and on which port?', ['api-endpoint']],
24
- ['loss-measured', "how is a node's loss measured and its scenarios scored?", ['yatsu-core']],
24
+ ['loss-measured', "how is a node's loss measured and its scenarios scored?", ['eval-core']],
25
25
  ['launch-injection', "what context gets injected into a freshly launched agent's prompt?", ['injected-context']],
26
26
  ['read-before-code', 'the one-shot nudge that makes an agent read its spec before touching code', ['spec-first']],
27
27
  ['hot-reload', 'zero-downtime backend reload without dropping connections', ['supervisor']],
28
28
  ['many-owners', 'can several specs own the same code file, and what happens if too many do?', ['governed-related']],
29
- ['active-spec-search', 'an injected sub-agent that searches specs for the agent, the spec analog of Explore', ['spec-scout']],
29
+ ['active-spec-search', 'an injected sub-agent that searches specs for the agent, the spec analog of Explore', ['spec-search']],
30
30
  ['declare-done', 'how does a worker declare it is done', ['state']],
31
31
  ]
32
32
 
@@ -36,7 +36,7 @@ const matches = (id, label) => id === label || id.endsWith('_' + label)
36
36
  let r1 = 0, r3 = 0, mrr = 0
37
37
  const rows = []
38
38
  for (const [name, query, expect] of CASES) {
39
- const out = execFileSync('node', [BIN, 'search', query, '--json', '--limit', '10'], { encoding: 'utf8' })
39
+ const out = execFileSync('node', [BIN, 'spec', 'search', query, '--json', '--limit', '10'], { encoding: 'utf8' })
40
40
  const results = JSON.parse(out)
41
41
  const ids = results.map((x) => x.id)
42
42
  const rank = ids.findIndex((id) => expect.some((label) => matches(id, label))) + 1 // 1-based; 0 = not found
@@ -55,9 +55,9 @@ for (const row of rows) {
55
55
 
56
56
  // CJK-positive: the corpus is mostly English but a few nodes carry Chinese prose — the root `spexcode`
57
57
  // node's body repeats 节点 throughout. A per-CJK-character tokenizer must let a Chinese content word reach
58
- // that node; `spex search "节点"` MUST return `spexcode` in results (the bug: the old tokenizer split on
58
+ // that node; `spex spec search "节点"` MUST return `spexcode` in results (the bug: the old tokenizer split on
59
59
  // [^a-z0-9]+ and discarded all CJK, so every Chinese query dead-ended at zero results).
60
- const cjkPos = JSON.parse(execFileSync('node', [BIN, 'search', '节点', '--json', '--limit', '10'], { encoding: 'utf8' }))
60
+ const cjkPos = JSON.parse(execFileSync('node', [BIN, 'spec', 'search', '节点', '--json', '--limit', '10'], { encoding: 'utf8' }))
61
61
  const cjkPosRank = cjkPos.map((x) => x.id).findIndex((id) => matches(id, 'spexcode')) + 1
62
62
  const cjkPosPass = cjkPosRank >= 1
63
63
  console.log(`${cjkPosPass ? `✓${cjkPosRank}` : '✗ '} cjk-positive want=spexcode(节点) rank=${cjkPosRank || '—'} top3: ${cjkPos.slice(0, 3).map((x) => x.id).join(', ')}`)
@@ -66,14 +66,14 @@ console.log(`${cjkPosPass ? `✓${cjkPosRank}` : '✗ '} cjk-positive w
66
66
  // nothing, and the zero-result message must still carry the corpus-is-English translate-and-retry fact
67
67
  // (fail-loud) plus the browse-all next step — CJK support does not suppress the honest zero-result route.
68
68
  // (No nearest titles: a CJK query has nothing to be lexically near.)
69
- const cjk = execFileSync('node', [BIN, 'search', '会话'], { encoding: 'utf8' })
70
- const cjkPass = cjk.includes('corpus is English') && cjk.includes('spex tree')
69
+ const cjk = execFileSync('node', [BIN, 'spec', 'search', '会话'], { encoding: 'utf8' })
70
+ const cjkPass = cjk.includes('corpus is English') && cjk.includes('spex graph')
71
71
  console.log(`${cjkPass ? '✓ ' : '✗ '} cjk-zero-result want=corpus-is-English + spex-tree ${cjkPass ? 'both present' : 'MISSING: ' + cjk.trim()}`)
72
72
 
73
73
  // zero-result typo routing: an English typo that matches nothing must surface the nearest node titles
74
74
  // (per-word edit distance) plus the browse-all next step, so a typo routes forward instead of dead-ending.
75
- const typo = execFileSync('node', [BIN, 'search', 'kyeboard'], { encoding: 'utf8' })
76
- const typoPass = typo.includes('nearest titles') && typo.includes('keyboard-nav') && typo.includes('spex tree')
75
+ const typo = execFileSync('node', [BIN, 'spec', 'search', 'kyeboard'], { encoding: 'utf8' })
76
+ const typoPass = typo.includes('nearest titles') && typo.includes('keyboard-nav') && typo.includes('spex graph')
77
77
  console.log(`${typoPass ? '✓ ' : '✗ '} typo-zero-result want=nearest-titles(keyboard-nav) + spex-tree ${typoPass ? 'both present' : 'MISSING: ' + typo.trim()}`)
78
78
 
79
79
  console.log('—'.repeat(72))
@@ -25,7 +25,7 @@ export function nearestTitles(query: string, n = 3): { id: string; title: string
25
25
  return dp[b.length]
26
26
  }
27
27
  const qws = words(query)
28
- if (!qws.length) return [] // nothing to be "near" (e.g. a pure-CJK query) — the caller still points at spex tree
28
+ if (!qws.length) return [] // nothing to be "near" (e.g. a pure-CJK query) — the caller still points at spex graph
29
29
  return loadSpecsLite()
30
30
  .map((s) => {
31
31
  const tws = [...new Set(words(`${s.title} ${s.id}`))]