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.
- package/README.md +56 -44
- package/package.json +3 -3
- package/spec-cli/bin/spex.mjs +2 -2
- package/spec-cli/hooks/dispatch.sh +1 -1
- package/spec-cli/hooks/harness.sh +26 -6
- package/spec-cli/src/anchors.ts +300 -0
- package/spec-cli/src/attach.ts +2 -2
- package/spec-cli/src/cli.ts +691 -536
- package/spec-cli/src/client.ts +31 -30
- package/spec-cli/src/contract-filter.ts +1 -1
- package/spec-cli/src/doctor.ts +40 -13
- package/spec-cli/src/gateway.ts +11 -7
- package/spec-cli/src/git.ts +23 -15
- package/spec-cli/src/{board.ts → graph.ts} +44 -14
- package/spec-cli/src/{boardCache.ts → graphCache.ts} +41 -21
- package/spec-cli/src/{boardDelta.ts → graphDelta.ts} +1 -1
- package/spec-cli/src/graphStream.ts +288 -0
- package/spec-cli/src/guide.ts +142 -98
- package/spec-cli/src/harness-select.ts +2 -2
- package/spec-cli/src/harness.ts +30 -14
- package/spec-cli/src/help.ts +300 -385
- package/spec-cli/src/hooks.ts +1 -1
- package/spec-cli/src/index.ts +144 -103
- package/spec-cli/src/init.ts +14 -13
- package/spec-cli/src/issues.ts +89 -33
- package/spec-cli/src/layout.ts +5 -5
- package/spec-cli/src/lint.ts +128 -30
- package/spec-cli/src/localIssues.ts +61 -60
- package/spec-cli/src/materialize.ts +1 -1
- package/spec-cli/src/mentions.ts +15 -15
- package/spec-cli/src/migrate-table.ts +398 -0
- package/spec-cli/src/migrate.ts +386 -0
- package/spec-cli/src/ranker.ts +30 -4
- package/spec-cli/src/reaper.ts +117 -0
- package/spec-cli/src/search.bench.mjs +12 -12
- package/spec-cli/src/search.ts +1 -1
- package/spec-cli/src/sessions.ts +244 -138
- package/spec-cli/src/specs.ts +40 -25
- package/spec-cli/src/supervise.ts +2 -2
- package/spec-cli/src/tree.ts +5 -5
- package/spec-cli/src/uninstall.ts +4 -4
- package/spec-cli/templates/hooks/post-checkout +1 -1
- package/spec-cli/templates/hooks/post-merge +3 -3
- package/spec-cli/templates/hooks/pre-commit +9 -9
- package/spec-cli/templates/hooks/prepare-commit-msg +1 -1
- package/spec-cli/templates/spec/project/{.config → .plugins}/core/idle/idle.sh +2 -2
- package/spec-cli/templates/spec/project/{.config → .plugins}/core/mark-active/mark-active.sh +7 -0
- package/spec-cli/templates/spec/project/{.config → .plugins}/core/mark-active/spec.md +2 -0
- package/spec-cli/templates/spec/project/{.config → .plugins}/core/session-fail/fail.sh +1 -1
- package/spec-cli/templates/spec/project/{.config → .plugins}/core/spec-first/spec-first.sh +1 -1
- package/spec-cli/templates/spec/project/{.config → .plugins}/core/spec-of-file/spec-of-file.sh +2 -2
- package/spec-cli/templates/spec/project/.plugins/core/spec.md +21 -0
- package/spec-cli/templates/spec/project/{.config → .plugins}/core/stop-gate/stop-gate.sh +21 -21
- package/spec-cli/templates/spec/project/{.config → .plugins}/distill/spec.md +2 -2
- package/spec-cli/templates/spec/project/{.config → .plugins}/extract/spec.md +5 -5
- package/spec-cli/templates/spec/project/{.config → .plugins/prompts}/forge-link/spec.md +1 -1
- package/spec-cli/templates/spec/project/{.config → .plugins/prompts}/reproduce-before-fix/spec.md +3 -3
- package/spec-cli/templates/spec/project/.plugins/prompts/spec.md +20 -0
- package/spec-cli/templates/spec/project/{.config → .plugins}/regroup/spec.md +2 -2
- package/spec-cli/templates/spec/project/.plugins/spec.md +18 -0
- package/spec-cli/templates/spec/project/.plugins/supervisor/spec.md +8 -0
- package/spec-cli/templates/spec/project/{.config → .plugins}/tidy/spec.md +1 -1
- package/spec-cli/templates/spec/project/spec.md +1 -1
- package/spec-dashboard/dist/assets/{Dashboard-P0B9ukSG.js → Dashboard-CTcH2eW9.js} +9 -9
- package/spec-dashboard/dist/assets/EvalsPage-CJNKwHLN.js +2 -0
- package/spec-dashboard/dist/assets/{FoldToggle-BuQ0lokE.js → FoldToggle-CVFbBpyW.js} +1 -1
- package/spec-dashboard/dist/assets/{IssuesPage-H-D8aHEl.js → IssuesPage-kULjonqj.js} +1 -1
- package/spec-dashboard/dist/assets/{MobileApp-oZXIeCPb.js → MobileApp-B0ZJju8K.js} +1 -1
- package/spec-dashboard/dist/assets/{SessionInterface-Blr_MEdU.js → SessionInterface-BRKJqU2U.js} +3 -3
- package/spec-dashboard/dist/assets/{SessionWindow-LcCzBMU7.js → SessionWindow-CDhEL7wO.js} +7 -7
- package/spec-dashboard/dist/assets/{Settings-_yOye-In.js → Settings-BL6FV_8S.js} +1 -1
- package/spec-dashboard/dist/assets/{index-uGs9v_9o.css → index-DmQsNYKK.css} +1 -1
- package/spec-dashboard/dist/assets/{index-BhIslAau.js → index-DulGPk6A.js} +8 -8
- package/spec-dashboard/dist/index.html +2 -2
- package/{spec-yatsu → spec-eval}/src/cache.ts +8 -5
- package/{spec-yatsu → spec-eval}/src/cli.ts +212 -96
- package/{spec-yatsu → spec-eval}/src/evaltab.ts +35 -27
- package/{spec-yatsu → spec-eval}/src/filing.ts +7 -5
- package/{spec-yatsu → spec-eval}/src/freshness.ts +44 -22
- package/spec-eval/src/humanok.ts +43 -0
- package/{spec-yatsu → spec-eval}/src/scenariofresh.ts +22 -17
- package/{spec-yatsu/src/yatsu.ts → spec-eval/src/scenarios.ts} +41 -26
- package/{spec-yatsu/src/proof.ts → spec-eval/src/sessioneval.ts} +59 -59
- package/{spec-yatsu → spec-eval}/src/sidecar.ts +42 -10
- package/{spec-yatsu → spec-eval}/src/timeline.ts +1 -1
- package/spec-forge/src/__fixtures__/github-forge.json +9 -9
- package/spec-forge/src/cli.ts +14 -13
- package/spec-forge/src/{needs-yatsu-eval.ts → needs-eval.ts} +6 -6
- package/spec-cli/src/boardStream.ts +0 -179
- package/spec-cli/templates/presets/careful/.config/clarify-before-code/spec.md +0 -11
- package/spec-cli/templates/spec/project/.config/core/spec.md +0 -17
- package/spec-cli/templates/spec/project/.config/spec.md +0 -15
- package/spec-cli/templates/spec/project/.config/supervisor/spec.md +0 -8
- package/spec-dashboard/dist/assets/EvalsPage-BrvAGyc4.js +0 -2
- /package/spec-cli/templates/spec/project/{.config → .plugins}/core/idle/spec.md +0 -0
- /package/spec-cli/templates/spec/project/{.config → .plugins}/core/session-fail/spec.md +0 -0
- /package/spec-cli/templates/spec/project/{.config → .plugins}/core/spec-first/spec.md +0 -0
- /package/spec-cli/templates/spec/project/{.config → .plugins}/core/spec-of-file/spec.md +0 -0
- /package/spec-cli/templates/spec/project/{.config → .plugins}/core/stop-gate/spec.md +0 -0
- /package/spec-cli/templates/spec/project/{.config → .plugins}/distill/digest.mjs +0 -0
- /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
|
|
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. `
|
|
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?", ['
|
|
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-
|
|
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
|
|
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
|
|
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))
|
package/spec-cli/src/search.ts
CHANGED
|
@@ -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
|
|
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}`))]
|