@su-record/vibe 4.2.34 → 4.2.36
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/dist/cli/common.js +4 -1
- package/dist/cli/common.js.map +1 -1
- package/dist/cli/heldout.js +10 -4
- package/dist/cli/heldout.js.map +1 -1
- package/dist/cli/human.js +8 -4
- package/dist/cli/human.js.map +1 -1
- package/dist/cli/internal.js +37 -24
- package/dist/cli/internal.js.map +1 -1
- package/dist/cli/ledger.js +67 -0
- package/dist/cli/ledger.js.map +1 -0
- package/dist/cli/map.js +5 -3
- package/dist/cli/map.js.map +1 -1
- package/dist/cli/memory.js +104 -74
- package/dist/cli/memory.js.map +1 -1
- package/dist/cli/risks.js +20 -3
- package/dist/cli/risks.js.map +1 -1
- package/dist/cli/session.js +4 -2
- package/dist/cli/session.js.map +1 -1
- package/dist/cli/setup.js +44 -13
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/verification.js +1 -1
- package/dist/cli/verification.js.map +1 -1
- package/dist/cli/work.js +75 -22
- package/dist/cli/work.js.map +1 -1
- package/dist/cli.js +18 -6
- package/dist/cli.js.map +1 -1
- package/dist/core/analyze.js +21 -7
- package/dist/core/analyze.js.map +1 -1
- package/dist/core/artifact-paths.js +14 -3
- package/dist/core/artifact-paths.js.map +1 -1
- package/dist/core/capabilities.js +69 -15
- package/dist/core/capabilities.js.map +1 -1
- package/dist/core/check-authorization.js +37 -0
- package/dist/core/check-authorization.js.map +1 -0
- package/dist/core/check-process.js +12 -4
- package/dist/core/check-process.js.map +1 -1
- package/dist/core/check-report.js +66 -0
- package/dist/core/check-report.js.map +1 -0
- package/dist/core/check-selection.js +4 -2
- package/dist/core/check-selection.js.map +1 -1
- package/dist/core/check.js +66 -130
- package/dist/core/check.js.map +1 -1
- package/dist/core/checks/changed.js +20 -6
- package/dist/core/checks/changed.js.map +1 -1
- package/dist/core/checks/eval.js +35 -10
- package/dist/core/checks/eval.js.map +1 -1
- package/dist/core/checks/file.js +26 -23
- package/dist/core/checks/file.js.map +1 -1
- package/dist/core/checks/fileRules.js +42 -16
- package/dist/core/checks/fileRules.js.map +1 -1
- package/dist/core/checks/http.js +35 -34
- package/dist/core/checks/http.js.map +1 -1
- package/dist/core/checks/packs.js +1 -1
- package/dist/core/checks/packs.js.map +1 -1
- package/dist/core/checks/review.js +75 -40
- package/dist/core/checks/review.js.map +1 -1
- package/dist/core/checks/run.js +5 -2
- package/dist/core/checks/run.js.map +1 -1
- package/dist/core/checks/schema.js +25 -0
- package/dist/core/checks/schema.js.map +1 -0
- package/dist/core/checks/source.js +11 -6
- package/dist/core/checks/source.js.map +1 -1
- package/dist/core/config.js +9 -2
- package/dist/core/config.js.map +1 -1
- package/dist/core/consent.js +24 -16
- package/dist/core/consent.js.map +1 -1
- package/dist/core/context-notes.js +15 -7
- package/dist/core/context-notes.js.map +1 -1
- package/dist/core/context.js +24 -12
- package/dist/core/context.js.map +1 -1
- package/dist/core/conventions.js +22 -9
- package/dist/core/conventions.js.map +1 -1
- package/dist/core/docs/cfb.js +81 -45
- package/dist/core/docs/cfb.js.map +1 -1
- package/dist/core/docs/html.js +14 -3
- package/dist/core/docs/html.js.map +1 -1
- package/dist/core/docs/hwp.js +44 -22
- package/dist/core/docs/hwp.js.map +1 -1
- package/dist/core/docs/office.js +20 -10
- package/dist/core/docs/office.js.map +1 -1
- package/dist/core/docs/pdf.js +10 -4
- package/dist/core/docs/pdf.js.map +1 -1
- package/dist/core/docs/read.js +32 -24
- package/dist/core/docs/read.js.map +1 -1
- package/dist/core/docs/zip.js +32 -15
- package/dist/core/docs/zip.js.map +1 -1
- package/dist/core/evidence.js +17 -7
- package/dist/core/evidence.js.map +1 -1
- package/dist/core/failure-message.js +35 -13
- package/dist/core/failure-message.js.map +1 -1
- package/dist/core/failure.js +49 -14
- package/dist/core/failure.js.map +1 -1
- package/dist/core/github.js +3 -1
- package/dist/core/github.js.map +1 -1
- package/dist/core/handoff.js +20 -7
- package/dist/core/handoff.js.map +1 -1
- package/dist/core/heldout-run.js +6 -3
- package/dist/core/heldout-run.js.map +1 -1
- package/dist/core/heldout.js +24 -13
- package/dist/core/heldout.js.map +1 -1
- package/dist/core/inbox.js +3 -1
- package/dist/core/inbox.js.map +1 -1
- package/dist/core/inputs.js +76 -0
- package/dist/core/inputs.js.map +1 -0
- package/dist/core/inspect.js +61 -20
- package/dist/core/inspect.js.map +1 -1
- package/dist/core/intent.js +50 -12
- package/dist/core/intent.js.map +1 -1
- package/dist/core/knowledge-find.js +31 -12
- package/dist/core/knowledge-find.js.map +1 -1
- package/dist/core/knowledge.js +22 -12
- package/dist/core/knowledge.js.map +1 -1
- package/dist/core/lang.js +5 -2
- package/dist/core/lang.js.map +1 -1
- package/dist/core/ledger.js +44 -20
- package/dist/core/ledger.js.map +1 -1
- package/dist/core/locations.js +12 -0
- package/dist/core/locations.js.map +1 -0
- package/dist/core/map/imports.js +20 -9
- package/dist/core/map/imports.js.map +1 -1
- package/dist/core/map/index.js +28 -13
- package/dist/core/map/index.js.map +1 -1
- package/dist/core/map/symbols.js +27 -12
- package/dist/core/map/symbols.js.map +1 -1
- package/dist/core/output-capture.js +7 -4
- package/dist/core/output-capture.js.map +1 -1
- package/dist/core/paths.js +2 -1
- package/dist/core/paths.js.map +1 -1
- package/dist/core/performance.js +43 -17
- package/dist/core/performance.js.map +1 -1
- package/dist/core/profile.js +6 -3
- package/dist/core/profile.js.map +1 -1
- package/dist/core/reader.js +32 -16
- package/dist/core/reader.js.map +1 -1
- package/dist/core/readerSession.js +34 -14
- package/dist/core/readerSession.js.map +1 -1
- package/dist/core/recent.js +20 -6
- package/dist/core/recent.js.map +1 -1
- package/dist/core/regress.js +21 -12
- package/dist/core/regress.js.map +1 -1
- package/dist/core/repair.js +22 -4
- package/dist/core/repair.js.map +1 -1
- package/dist/core/research-queries.js +85 -0
- package/dist/core/research-queries.js.map +1 -0
- package/dist/core/research.js +89 -88
- package/dist/core/research.js.map +1 -1
- package/dist/core/results.js +89 -0
- package/dist/core/results.js.map +1 -0
- package/dist/core/risk-signals.js +55 -16
- package/dist/core/risk-signals.js.map +1 -1
- package/dist/core/run-id.js +10 -6
- package/dist/core/run-id.js.map +1 -1
- package/dist/core/scenarios.js +97 -57
- package/dist/core/scenarios.js.map +1 -1
- package/dist/core/session.js +3 -2
- package/dist/core/session.js.map +1 -1
- package/dist/core/size-gate.js +57 -0
- package/dist/core/size-gate.js.map +1 -0
- package/dist/core/size.js +32 -10
- package/dist/core/size.js.map +1 -1
- package/dist/core/skills.js +66 -28
- package/dist/core/skills.js.map +1 -1
- package/dist/core/skillsmp.js +26 -12
- package/dist/core/skillsmp.js.map +1 -1
- package/dist/core/source-basis.js +21 -9
- package/dist/core/source-basis.js.map +1 -1
- package/dist/core/status.js +26 -13
- package/dist/core/status.js.map +1 -1
- package/dist/core/table.js +8 -1
- package/dist/core/table.js.map +1 -1
- package/dist/core/tokens.js +20 -10
- package/dist/core/tokens.js.map +1 -1
- package/dist/core/tree.js +26 -16
- package/dist/core/tree.js.map +1 -1
- package/dist/core/verification-plan.js +26 -10
- package/dist/core/verification-plan.js.map +1 -1
- package/dist/core/verification.js +14 -7
- package/dist/core/verification.js.map +1 -1
- package/dist/core/view.js +93 -44
- package/dist/core/view.js.map +1 -1
- package/dist/install/global.js +37 -18
- package/dist/install/global.js.map +1 -1
- package/dist/install/hooks.js +17 -8
- package/dist/install/hooks.js.map +1 -1
- package/dist/install/manifest.js +11 -0
- package/dist/install/manifest.js.map +1 -0
- package/dist/install/mcpb.js +52 -23
- package/dist/install/mcpb.js.map +1 -1
- package/dist/install/plugin.js +73 -33
- package/dist/install/plugin.js.map +1 -1
- package/dist/install/project.js +8 -7
- package/dist/install/project.js.map +1 -1
- package/dist/install/register.js +83 -48
- package/dist/install/register.js.map +1 -1
- package/dist/install/tree.js +27 -11
- package/dist/install/tree.js.map +1 -1
- package/dist/install/update.js +46 -20
- package/dist/install/update.js.map +1 -1
- package/hooks/code-map.cjs +22 -9
- package/hooks/file-size.cjs +83 -0
- package/hooks/journal.cjs +28 -18
- package/hooks/knowledge-auto.cjs +55 -21
- package/hooks/knowledge-journal.cjs +47 -20
- package/hooks/knowledge-projects.cjs +50 -21
- package/hooks/knowledge-recall.cjs +16 -6
- package/hooks/knowledge-upkeep.cjs +22 -5
- package/hooks/locations.cjs +35 -0
- package/hooks/notify.js +52 -24
- package/hooks/obsidian.cjs +17 -7
- package/hooks/private-store.cjs +25 -10
- package/hooks/retest.cjs +39 -16
- package/hooks/session-context.cjs +30 -13
- package/hooks/session-files.cjs +44 -21
- package/hooks/session-repair.cjs +26 -11
- package/hooks/session-state.cjs +78 -38
- package/hooks/session.js +19 -8
- package/hooks/slice-command.cjs +38 -17
- package/hooks/slice-guard.cjs +20 -6
- package/hooks/slice-store.cjs +25 -12
- package/internal/guides/code.md +17 -0
- package/mcpb/server/index.js +40 -12
- package/package.json +1 -1
package/dist/core/intent.js
CHANGED
|
@@ -6,13 +6,18 @@ import { denied, usage } from './errors.js';
|
|
|
6
6
|
import { openQuestions, resolve as resolveQuestion } from './inbox.js';
|
|
7
7
|
import { record } from './ledger.js';
|
|
8
8
|
import { vibePath } from './paths.js';
|
|
9
|
+
import { resultsPath } from './results.js';
|
|
9
10
|
import { parseScenarios } from './scenarios.js';
|
|
10
11
|
import { readState, transition } from './state.js';
|
|
11
12
|
import { captureSources, readSourceBasis, saveSourceBasis, sourceValidity } from './source-basis.js';
|
|
12
|
-
import { readText, writeAtomic, writeJson } from './store.js';
|
|
13
|
+
import { readJson, readText, writeAtomic, writeJson } from './store.js';
|
|
13
14
|
import { issueToken, verifyAndConsume } from './tokens.js';
|
|
14
15
|
import { changedVerifiers, consentStatus, saveConsent } from './consent.js';
|
|
15
16
|
import { executionPlan } from './inspect.js';
|
|
17
|
+
const INTENT_HASH_LENGTH = 16;
|
|
18
|
+
/** States from which a plain `approve` renews the receipt instead of approving a draft. */
|
|
19
|
+
const RENEWABLE_STATES = ['APPROVED', 'RUNNING', 'STUCK', 'DONE'];
|
|
20
|
+
const NO_SCENARIOS_ID = '(none)';
|
|
16
21
|
export function intentPath(root) {
|
|
17
22
|
return vibePath(root, 'intent.md');
|
|
18
23
|
}
|
|
@@ -23,7 +28,7 @@ export function intentHash(intentText, scenariosText, sources = []) {
|
|
|
23
28
|
const hash = createHash('sha256').update(intentText).update('\n---\n').update(scenariosText);
|
|
24
29
|
if (sources.length)
|
|
25
30
|
hash.update('\n---sources---\n').update(JSON.stringify(sources));
|
|
26
|
-
return hash.digest('hex').slice(0,
|
|
31
|
+
return hash.digest('hex').slice(0, INTENT_HASH_LENGTH);
|
|
27
32
|
}
|
|
28
33
|
export function loadScenarios(root) {
|
|
29
34
|
const text = readText(scenariosPath(root));
|
|
@@ -35,6 +40,22 @@ export function hasIntent(root) {
|
|
|
35
40
|
const text = readText(intentPath(root));
|
|
36
41
|
return text !== null && text.trim().length > 0;
|
|
37
42
|
}
|
|
43
|
+
/** What decides a scenario's verdict; its prose (`then`, `given`, `when`) does not. */
|
|
44
|
+
function definition(s) {
|
|
45
|
+
return JSON.stringify([s.check, s.needs, s.inputs, s.verifiers, s.artifacts, s.risk, s.irreversible]);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The results a new draft keeps: those of scenarios it defines exactly as before, and of the ones
|
|
49
|
+
* it does not declare (regressions, built-in gates). Each still counts only while its inputs are
|
|
50
|
+
* unchanged, so a draft that adds one scenario does not rerun the others.
|
|
51
|
+
*/
|
|
52
|
+
function keptResults(root, next) {
|
|
53
|
+
const before = new Map(loadScenarios(root).map((s) => [s.id, definition(s)]));
|
|
54
|
+
const after = new Map(next.map((s) => [s.id, definition(s)]));
|
|
55
|
+
const stored = readJson(resultsPath(root)) ?? {};
|
|
56
|
+
const keep = ([id]) => after.has(id) ? before.get(id) === after.get(id) : !before.has(id);
|
|
57
|
+
return Object.fromEntries(Object.entries(stored).filter(keep));
|
|
58
|
+
}
|
|
38
59
|
/**
|
|
39
60
|
* Save intent + scenarios. If any scenario lacks a check type nothing is written — the
|
|
40
61
|
* invariant "every stored scenario is checkable" holds. On success an approval token is issued.
|
|
@@ -46,7 +67,7 @@ export function draft(root, intentText, scenariosText, sources) {
|
|
|
46
67
|
if (parsed.rejections.length > 0)
|
|
47
68
|
return { ok: false, rejections: parsed.rejections };
|
|
48
69
|
if (parsed.scenarios.length === 0)
|
|
49
|
-
return { ok: false, rejections: [{ id:
|
|
70
|
+
return { ok: false, rejections: [{ id: NO_SCENARIOS_ID, reason: 'no scenarios' }] };
|
|
50
71
|
const sourceBasis = captureSources(root, sources);
|
|
51
72
|
// The hash covers the exact bytes written — approve recomputes it from the files.
|
|
52
73
|
const intentNorm = intentText.endsWith('\n') ? intentText : `${intentText}\n`;
|
|
@@ -55,16 +76,28 @@ export function draft(root, intentText, scenariosText, sources) {
|
|
|
55
76
|
const previousState = readState(root);
|
|
56
77
|
const previous = previousState.intentHash;
|
|
57
78
|
captureRiskBase(root, ['NONE', 'DONE', 'ABANDONED'].includes(previousState.state));
|
|
79
|
+
const kept = keptResults(root, parsed.scenarios);
|
|
58
80
|
writeAtomic(intentPath(root), intentNorm);
|
|
59
81
|
writeAtomic(scenariosPath(root), scenariosNorm);
|
|
60
82
|
saveSourceBasis(root, sourceBasis);
|
|
61
|
-
writeJson(
|
|
62
|
-
transition(root, 'DRAFT', {
|
|
83
|
+
writeJson(resultsPath(root), kept);
|
|
84
|
+
transition(root, 'DRAFT', {
|
|
85
|
+
intentHash: hash,
|
|
86
|
+
approvedAt: null,
|
|
87
|
+
runs: previousState.runs,
|
|
88
|
+
failStreak: 0,
|
|
89
|
+
lastFailHash: null,
|
|
90
|
+
repair: null,
|
|
91
|
+
doneAt: null,
|
|
92
|
+
doneTree: null,
|
|
93
|
+
abandonedReason: null,
|
|
94
|
+
});
|
|
63
95
|
const policy = readConfig(root).tokens;
|
|
64
96
|
const issued = approvalNeedsToken(policy) ? issueToken(root, 'approve', hash) : null;
|
|
65
97
|
const edges = previous && previous !== hash ? [{ type: 'supersedes', from: `intent:${hash}`, to: `intent:${previous}` }] : [];
|
|
66
98
|
record(root, { event: 'draft', client: detectClient(), model: detectModel(), detail: hash, edges });
|
|
67
|
-
|
|
99
|
+
const { token, id: tokenId, expiresAt } = issued ?? { token: null, id: null, expiresAt: null };
|
|
100
|
+
return { ok: true, hash, scenarios: parsed.scenarios, token, tokenId, expiresAt, policy };
|
|
68
101
|
}
|
|
69
102
|
/**
|
|
70
103
|
* APPROVED — under `strict` only a human token does it; otherwise a plain approve is recorded as
|
|
@@ -73,7 +106,7 @@ export function draft(root, intentText, scenariosText, sources) {
|
|
|
73
106
|
*/
|
|
74
107
|
export function approve(root, token) {
|
|
75
108
|
const state = readState(root);
|
|
76
|
-
const renewal =
|
|
109
|
+
const renewal = RENEWABLE_STATES.includes(state.state) && !consentStatus(root).valid;
|
|
77
110
|
if ((state.state !== 'DRAFT' && !renewal) || !state.intentHash)
|
|
78
111
|
throw denied(`nothing to approve (current state ${state.state})`);
|
|
79
112
|
const sourceBasis = readSourceBasis(root);
|
|
@@ -81,15 +114,19 @@ export function approve(root, token) {
|
|
|
81
114
|
if (current !== state.intentHash)
|
|
82
115
|
throw denied('intent changed since the draft — run `intent draft` again to get a new token');
|
|
83
116
|
const validity = sourceValidity(root, sourceBasis);
|
|
84
|
-
if (validity && !validity.valid)
|
|
85
|
-
|
|
117
|
+
if (validity && !validity.valid) {
|
|
118
|
+
const files = [...validity.changed, ...validity.missing, ...validity.unreadable].join(', ');
|
|
119
|
+
throw denied(`source changed or missing since the draft: ${files} — re-evaluate affected findings and run \`intent draft\` again`);
|
|
120
|
+
}
|
|
86
121
|
const policy = readConfig(root).tokens;
|
|
87
122
|
const waiting = openQuestions(root).filter((question) => !question.answer?.trim());
|
|
88
123
|
// A pending approval question for this draft is what this approval answers, by token or, when the policy asks none, by chat.
|
|
89
124
|
const answers = token !== null || !approvalNeedsToken(policy);
|
|
90
125
|
const blocked = waiting.filter((question) => !(answers && question.needs === 'approve' && question.target === state.intentHash));
|
|
91
|
-
if (blocked.length)
|
|
92
|
-
|
|
126
|
+
if (blocked.length) {
|
|
127
|
+
const ids = blocked.map((question) => question.id).join(', ');
|
|
128
|
+
throw denied(`unanswered customer decisions: ${ids} — obtain an answer or resolve a withdrawn question before approval; defaults are not agreement`);
|
|
129
|
+
}
|
|
93
130
|
const plan = executionPlan(root);
|
|
94
131
|
// A renewal that changed the declared verifiers re-approves the files that judge the work. The
|
|
95
132
|
// person's policy decides whether that needs a token (only `strict` does, as for any approval);
|
|
@@ -112,7 +149,8 @@ export function approve(root, token) {
|
|
|
112
149
|
for (const question of waiting)
|
|
113
150
|
resolveQuestion(root, question.id);
|
|
114
151
|
const detail = `${state.intentHash} by ${basis}${regraded.length ? `; verifiers changed: ${regraded.join(', ')}` : ''}`;
|
|
115
|
-
|
|
152
|
+
const edges = [{ type: 'decided-by', from: `intent:${state.intentHash}`, to: by }];
|
|
153
|
+
record(root, { event: 'approve', client: detectClient(), model: detectModel(), detail, edges });
|
|
116
154
|
return { hash: state.intentHash, basis, verifiers: regraded };
|
|
117
155
|
}
|
|
118
156
|
export function abandon(root, reason) {
|
package/dist/core/intent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent.js","sourceRoot":"","sources":["../../src/core/intent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,cAAc,EAAiC,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAwB,MAAM,mBAAmB,CAAC;AAC3H,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"intent.js","sourceRoot":"","sources":["../../src/core/intent.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,7 +29,21 @@ export function properties(text) {
|
|
|
29
29
|
return { props, body: text.slice(match[0].length) };
|
|
30
30
|
}
|
|
31
31
|
export { TYPES as PAGE_TYPES } from './knowledge-lint.js';
|
|
32
|
-
|
|
32
|
+
/** Longest summary shown for a page; a longer one is cut to fit with the ellipsis. */
|
|
33
|
+
const SUMMARY_MAX = 160;
|
|
34
|
+
const ELLIPSIS = '...';
|
|
35
|
+
/** Score weights: where a query term is found says how much the page is about it. */
|
|
36
|
+
const WEIGHT = { name: 6, tag: 4, summary: 3, heading: 2, bodyHit: 1 };
|
|
37
|
+
/** A term repeated in the body counts at most this many times, so one repeated word cannot outrank a broader match. */
|
|
38
|
+
const BODY_HITS_MAX = 3;
|
|
39
|
+
/** Archived and superseded pages keep this share of their score. */
|
|
40
|
+
const STALE_SHARE = 1 / 3;
|
|
41
|
+
const DEFAULT_LIMIT = 8;
|
|
42
|
+
const SCORE_ROUNDING = 10;
|
|
43
|
+
const HEADING_LEVELS = /^#{2,6}\s/;
|
|
44
|
+
const STOP = new Set([
|
|
45
|
+
'a', 'an', 'and', 'are', 'as', 'at', 'by', 'for', 'from', 'how', 'in', 'is', 'it', 'of', 'on', 'or', 'the', 'to', 'what', 'when', 'with',
|
|
46
|
+
]);
|
|
33
47
|
/** Words of a query; a Latin word matches the start of a word, so `release` finds `releases`; other scripts match anywhere, so `배포` finds `배포를`. */
|
|
34
48
|
export function queryTerms(query) {
|
|
35
49
|
const words = query.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter(w => w && !STOP.has(w) && (w.length > 1 || /[^\x00-\x7f]/.test(w)));
|
|
@@ -50,10 +64,12 @@ export function describePage(file) {
|
|
|
50
64
|
const stated = props['summary'] ?? props['description'];
|
|
51
65
|
const summary = (typeof stated === 'string' && stated) || first.replace(/^[-*]\s+/, '');
|
|
52
66
|
const names = [title, path.basename(file, '.md').replace(/[-_]+/g, ' '), ...list(props['aliases'])].join('\n');
|
|
53
|
-
const headings = body.split('\n').filter(line =>
|
|
67
|
+
const headings = body.split('\n').filter(line => HEADING_LEVELS.test(line)).join('\n');
|
|
54
68
|
const type = typeof props['type'] === 'string' ? props['type'].toLowerCase() : null;
|
|
55
|
-
|
|
56
|
-
|
|
69
|
+
const clipped = summary.length > SUMMARY_MAX ? `${summary.slice(0, SUMMARY_MAX - ELLIPSIS.length)}${ELLIPSIS}` : summary;
|
|
70
|
+
const supersedes = list(props['supersedes']).flatMap(value => wikiLinks(value).length ? wikiLinks(value) : [value]);
|
|
71
|
+
return { title, names, tags: list(props['tags']), summary: clipped, headings, body,
|
|
72
|
+
type, archived: props['status'] === 'archived', supersedes };
|
|
57
73
|
}
|
|
58
74
|
/**
|
|
59
75
|
* Score one page: a term in the title or another name of the page counts most, then tags, summary, headings
|
|
@@ -62,14 +78,15 @@ export function describePage(file) {
|
|
|
62
78
|
function score(page, terms) {
|
|
63
79
|
let total = 0, matched = 0;
|
|
64
80
|
for (const term of terms) {
|
|
65
|
-
const value = (hits(page.names, term) ?
|
|
66
|
-
+ (hits(page.summary, term) ?
|
|
81
|
+
const value = (hits(page.names, term) ? WEIGHT.name : 0) + (page.tags.some(tag => hits(tag, term)) ? WEIGHT.tag : 0)
|
|
82
|
+
+ (hits(page.summary, term) ? WEIGHT.summary : 0) + (hits(page.headings, term) ? WEIGHT.heading : 0)
|
|
83
|
+
+ Math.min(hits(page.body, term), BODY_HITS_MAX) * WEIGHT.bodyHit;
|
|
67
84
|
if (value) {
|
|
68
85
|
total += value;
|
|
69
86
|
matched++;
|
|
70
87
|
}
|
|
71
88
|
}
|
|
72
|
-
return terms.length ? Math.round(total * matched / terms.length *
|
|
89
|
+
return terms.length ? Math.round(total * matched / terms.length * SCORE_ROUNDING) / SCORE_ROUNDING : 0;
|
|
73
90
|
}
|
|
74
91
|
/** Every page once: the wiki with the project folders it shows, then `extra` folders it does not already reach. */
|
|
75
92
|
function candidates(wiki, extra) {
|
|
@@ -110,9 +127,9 @@ function replacements(pages) {
|
|
|
110
127
|
/**
|
|
111
128
|
* Find the pages a query is about, in the wiki (with the project folders it shows) and in `extra` folders such
|
|
112
129
|
* as the current project's shared knowledge. No model and no index: every page is read, so the answer is current.
|
|
113
|
-
* Archived and superseded pages keep
|
|
130
|
+
* Archived and superseded pages keep STALE_SHARE of their score, so current knowledge comes first.
|
|
114
131
|
*/
|
|
115
|
-
export function findKnowledge(wiki, query, extra = [], limit =
|
|
132
|
+
export function findKnowledge(wiki, query, extra = [], limit = DEFAULT_LIMIT, type) {
|
|
116
133
|
const terms = queryTerms(query);
|
|
117
134
|
const { pages, partial } = candidates(wiki, extra);
|
|
118
135
|
const replaced = replacements(pages);
|
|
@@ -122,9 +139,11 @@ export function findKnowledge(wiki, query, extra = [], limit = 8, type) {
|
|
|
122
139
|
continue;
|
|
123
140
|
const supersededBy = replaced.get(file) ?? null;
|
|
124
141
|
const state = supersededBy ? 'superseded' : d.archived ? 'archived' : 'current';
|
|
125
|
-
const value = score(d, terms) * (state === 'current' ? 1 :
|
|
126
|
-
if (value
|
|
127
|
-
|
|
142
|
+
const value = score(d, terms) * (state === 'current' ? 1 : STALE_SHARE);
|
|
143
|
+
if (value <= 0)
|
|
144
|
+
continue;
|
|
145
|
+
const rounded = Math.round(value * SCORE_ROUNDING) / SCORE_ROUNDING;
|
|
146
|
+
found.push({ page, file, title: d.title, summary: d.summary, tags: d.tags, type: d.type, state, supersededBy, score: rounded });
|
|
128
147
|
}
|
|
129
148
|
found.sort((a, b) => b.score - a.score || a.file.localeCompare(b.file));
|
|
130
149
|
return { query, terms, found: found.slice(0, limit), partial };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"knowledge-find.js","sourceRoot":"","sources":["../../src/core/knowledge-find.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAE3D,yFAAyF;AACzF,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,KAAK,GAAG,8CAA8C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxE,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC7C,MAAM,KAAK,GAAsC,EAAE,CAAC;IACpD,IAAI,IAAI,GAAoB,IAAI,CAAC;IACjC,MAAM,OAAO,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IACxF,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;YAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;YAAC,SAAS;QAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,4BAA4B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,KAAK,KAAK,EAAE;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;aACzC,CAAC;YAAC,IAAI,GAAG,IAAI,CAAC;YAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAAC,CAAC;IAC/I,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;AACtD,CAAC;AAED,OAAO,EAAE,KAAK,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAgB1D,MAAM,
|
|
1
|
+
{"version":3,"file":"knowledge-find.js","sourceRoot":"","sources":["../../src/core/knowledge-find.ts"],"names":[],"mappings":"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"}
|
package/dist/core/knowledge.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import os from 'node:os';
|
|
3
2
|
import path from 'node:path';
|
|
4
3
|
import { detectClient, detectModel } from './client.js';
|
|
5
4
|
import { usage } from './errors.js';
|
|
@@ -8,18 +7,26 @@ import { projectName } from './knowledge-projects.js';
|
|
|
8
7
|
import { realFolder } from './obsidian.js';
|
|
9
8
|
import { vibePath } from './paths.js';
|
|
10
9
|
import { readJson, writeAtomic, writeJson } from './store.js';
|
|
10
|
+
import { vibeConfig, defaultHome, SETTINGS, FOLDERS } from './locations.js';
|
|
11
|
+
const KNOWLEDGE_FOLDER = 'knowledge';
|
|
12
|
+
/** Wiki sub-folder holding one page per project. */
|
|
13
|
+
const PROJECTS_FOLDER = 'projects';
|
|
14
|
+
/** Longest file name stem a note title may produce. */
|
|
15
|
+
const SLUG_MAX = 48;
|
|
16
|
+
const DEFAULT_SLUG = 'note';
|
|
17
|
+
const SKILL_MODES = ['propose', 'create'];
|
|
18
|
+
const JOURNAL_SWITCH = ['on', 'off'];
|
|
11
19
|
/** Domain knowledge is not a skill — it is a document the model reads when it needs it. */
|
|
12
20
|
export function knowledgeDir(root) {
|
|
13
|
-
return vibePath(root,
|
|
21
|
+
return vibePath(root, KNOWLEDGE_FOLDER);
|
|
14
22
|
}
|
|
15
|
-
const defaultHome = () => process.env['VIBE_HOME_DIR'] ?? os.homedir();
|
|
16
23
|
/** Conversation turns without a file change before a knowledge turn; 0 keeps only the file-change trigger. */
|
|
17
24
|
export const DEFAULT_KNOWLEDGE_TURNS = 5;
|
|
18
25
|
/** Changed wiki pages, and days with a changed page, before a knowledge turn also reviews them; 0 pages turns review off. */
|
|
19
26
|
export const DEFAULT_REVIEW_PAGES = 10;
|
|
20
27
|
export const DEFAULT_REVIEW_DAYS = 14;
|
|
21
28
|
export function knowledgeSettingsFile(home = defaultHome()) {
|
|
22
|
-
return
|
|
29
|
+
return vibeConfig(home, SETTINGS.knowledge);
|
|
23
30
|
}
|
|
24
31
|
export function knowledgeSettings(home = defaultHome()) {
|
|
25
32
|
const raw = readJson(knowledgeSettingsFile(home)) ?? {};
|
|
@@ -36,6 +43,10 @@ export function knowledgeSettings(home = defaultHome()) {
|
|
|
36
43
|
reviewDays: count(reviewDays, DEFAULT_REVIEW_DAYS),
|
|
37
44
|
};
|
|
38
45
|
}
|
|
46
|
+
function requireChoice(flag, value, choices) {
|
|
47
|
+
if (value !== undefined && !choices.includes(value))
|
|
48
|
+
throw usage(`--${flag} takes ${choices.join(' | ')}`);
|
|
49
|
+
}
|
|
39
50
|
function absolute(flag, value) {
|
|
40
51
|
if (value !== undefined && !path.isAbsolute(value))
|
|
41
52
|
throw usage(`--${flag} takes an absolute folder path`);
|
|
@@ -44,14 +55,13 @@ function absolute(flag, value) {
|
|
|
44
55
|
/** Apply the person's change; a folder must be absolute, and what the change leaves out is kept. */
|
|
45
56
|
export function setKnowledgeSettings(change, home = defaultHome()) {
|
|
46
57
|
const current = knowledgeSettings(home);
|
|
47
|
-
|
|
58
|
+
const counts = [['turns', change.turns], ['review', change.review], ['review-days', change.reviewDays]];
|
|
59
|
+
for (const [flag, value] of counts) {
|
|
48
60
|
if (value !== undefined && !(Number.isInteger(value) && value >= 0))
|
|
49
61
|
throw usage(`--${flag} takes a whole number, 0 or more`);
|
|
50
62
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (change.journal !== undefined && !['on', 'off'].includes(change.journal))
|
|
54
|
-
throw usage('--journal takes on | off');
|
|
63
|
+
requireChoice('skills', change.skills, SKILL_MODES);
|
|
64
|
+
requireChoice('journal', change.journal, JOURNAL_SWITCH);
|
|
55
65
|
const dir = absolute('dir', change.dir) ?? current.dir;
|
|
56
66
|
const exclude = absolute('exclude', change.exclude), include = absolute('include', change.include);
|
|
57
67
|
const next = {
|
|
@@ -69,18 +79,18 @@ export function setKnowledgeSettings(change, home = defaultHome()) {
|
|
|
69
79
|
}
|
|
70
80
|
/** Cross-project knowledge, outside any `.vibe/` — the same plain-file format, read after a project's own. */
|
|
71
81
|
export function globalKnowledgeDir(home = defaultHome()) {
|
|
72
|
-
return knowledgeSettings(home).dir ??
|
|
82
|
+
return knowledgeSettings(home).dir ?? vibeConfig(home, FOLDERS.knowledge);
|
|
73
83
|
}
|
|
74
84
|
/** The project's own page in the personal wiki, named the way the session hook names it. */
|
|
75
85
|
export function projectPageFile(root, home = defaultHome()) {
|
|
76
|
-
return path.join(globalKnowledgeDir(home),
|
|
86
|
+
return path.join(globalKnowledgeDir(home), PROJECTS_FOLDER, `${projectName(fs.realpathSync(root), home, false)}.md`);
|
|
77
87
|
}
|
|
78
88
|
export function addKnowledge(root, title, body, options = {}) {
|
|
79
89
|
if (!title.trim())
|
|
80
90
|
throw usage('--title is required');
|
|
81
91
|
if (!body.trim())
|
|
82
92
|
throw usage('body is empty');
|
|
83
|
-
const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0,
|
|
93
|
+
const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, SLUG_MAX) || DEFAULT_SLUG;
|
|
84
94
|
const dir = options.global ? globalKnowledgeDir() : knowledgeDir(root);
|
|
85
95
|
const file = path.join(dir, `${slug}.md`);
|
|
86
96
|
writeAtomic(file, `# ${title}\n\n${body.trim()}\n`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"knowledge.js","sourceRoot":"","sources":["../../src/core/knowledge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,
|
|
1
|
+
{"version":3,"file":"knowledge.js","sourceRoot":"","sources":["../../src/core/knowledge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE5E,MAAM,gBAAgB,GAAG,WAAW,CAAC;AACrC,oDAAoD;AACpD,MAAM,eAAe,GAAG,UAAU,CAAC;AACnC,uDAAuD;AACvD,MAAM,QAAQ,GAAG,EAAE,CAAC;AACpB,MAAM,YAAY,GAAG,MAAM,CAAC;AAC5B,MAAM,WAAW,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAU,CAAC;AACnD,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,KAAK,CAAU,CAAC;AAE9C,2FAA2F;AAC3F,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;AAC1C,CAAC;AAGD,8GAA8G;AAC9G,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,6HAA6H;AAC7H,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AACvC,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAgCtC,MAAM,UAAU,qBAAqB,CAAC,OAAe,WAAW,EAAE;IAChE,OAAO,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAe,WAAW,EAAE;IAC5D,MAAM,GAAG,GAAG,QAAQ,CAA0B,qBAAqB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IACjF,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC;IACxD,MAAM,KAAK,GAAG,CAAC,KAAc,EAAE,QAAgB,EAAU,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAK,KAAgB,IAAI,CAAC,CAAC,CAAC,CAAC,KAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC7I,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI;QAC1B,GAAG,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,uBAAuB,CAAC;QAC5C,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;QACzD,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;QACtH,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,KAAK,KAAK;QACjC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,oBAAoB,CAAC;QAC3C,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,mBAAmB,CAAC;KACnD,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,IAAY,EAAE,KAAyB,EAAE,OAA0B;IACxF,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,MAAM,KAAK,CAAC,KAAK,IAAI,UAAU,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAC7G,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,KAAyB;IACvD,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,MAAM,KAAK,CAAC,KAAK,IAAI,gCAAgC,CAAC,CAAC;IAC3G,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AAC7D,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,oBAAoB,CAAC,MAAuB,EAAE,OAAe,WAAW,EAAE;IACxF,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,CAAU,CAAC;IACjH,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QACnC,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;YAAE,MAAM,KAAK,CAAC,KAAK,IAAI,kCAAkC,CAAC,CAAC;IAChI,CAAC;IACD,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACpD,aAAa,CAAC,SAAS,EAAE,MAAM,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACzD,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC;IACvD,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACnG,MAAM,IAAI,GAAsB;QAC9B,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI;QACjC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvB,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK;QACpC,MAAM,EAAG,MAAM,CAAC,MAAgC,IAAI,OAAO,CAAC,MAAM;QAClE,OAAO,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,KAAK,OAAO,CAAC;QAC/G,OAAO,EAAE,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,KAAK,IAAI;QACjF,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM;QACvC,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,OAAO,CAAC,UAAU;KACpD,CAAC;IACF,SAAS,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;IAC7C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,8GAA8G;AAC9G,MAAM,UAAU,kBAAkB,CAAC,OAAe,WAAW,EAAE;IAC7D,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;AAC5E,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,OAAe,WAAW,EAAE;IACxE,OAAO,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,eAAe,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;AACvH,CAAC;AAMD,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,KAAa,EAAE,IAAY,EAAE,UAA+B,EAAE;IACvG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,MAAM,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACtD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;QAAE,MAAM,KAAK,CAAC,eAAe,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAI,YAAY,CAAC;IACxH,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACvE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC;IAC1C,WAAW,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACpD,MAAM,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACrI,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC"}
|
package/dist/core/lang.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
const HANGUL = /[ᄀ-ᇿ-가-]/g;
|
|
2
2
|
const LATIN = /[A-Za-zÀ-ɏ]/g;
|
|
3
3
|
const MIN_LETTERS = 20;
|
|
4
|
+
/** Share of Hangul among the letters from which a text is Korean, and of Latin letters from which it is English. */
|
|
5
|
+
const KO_SHARE = 0.3;
|
|
6
|
+
const EN_SHARE = 0.9;
|
|
4
7
|
export function detectLang(text) {
|
|
5
8
|
const hangul = (text.match(HANGUL) ?? []).length;
|
|
6
9
|
const latin = (text.match(LATIN) ?? []).length;
|
|
7
10
|
const letters = hangul + latin;
|
|
8
11
|
if (letters < MIN_LETTERS)
|
|
9
12
|
return null;
|
|
10
|
-
if (hangul / letters >=
|
|
13
|
+
if (hangul / letters >= KO_SHARE)
|
|
11
14
|
return 'ko';
|
|
12
|
-
if (latin / letters >=
|
|
15
|
+
if (latin / letters >= EN_SHARE)
|
|
13
16
|
return 'en';
|
|
14
17
|
return null;
|
|
15
18
|
}
|
package/dist/core/lang.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lang.js","sourceRoot":"","sources":["../../src/core/lang.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,GAAG,cAAc,CAAC;AAC9B,MAAM,KAAK,GAAG,cAAc,CAAC;AAC7B,MAAM,WAAW,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"lang.js","sourceRoot":"","sources":["../../src/core/lang.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,GAAG,cAAc,CAAC;AAC9B,MAAM,KAAK,GAAG,cAAc,CAAC;AAC7B,MAAM,WAAW,GAAG,EAAE,CAAC;AACvB,oHAAoH;AACpH,MAAM,QAAQ,GAAG,GAAG,CAAC;AACrB,MAAM,QAAQ,GAAG,GAAG,CAAC;AAErB,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;IACjD,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;IAC/C,MAAM,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;IAC/B,IAAI,OAAO,GAAG,WAAW;QAAE,OAAO,IAAI,CAAC;IACvC,IAAI,MAAM,GAAG,OAAO,IAAI,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,KAAK,GAAG,OAAO,IAAI,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/core/ledger.js
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
import { isProjectDir, vibePath } from './paths.js';
|
|
2
|
+
import { RUN_PREFIX } from './run-id.js';
|
|
2
3
|
import { readState } from './state.js';
|
|
3
4
|
import { appendJsonl, nowIso, readJsonl } from './store.js';
|
|
4
5
|
export const EDGE_TYPES = ['supersedes', 'decided-by', 'implements', 'caused'];
|
|
6
|
+
const LEDGER_FILE = 'ledger.jsonl';
|
|
7
|
+
/** How long an authorize record lets an irreversible scenario run. */
|
|
8
|
+
const AUTHORIZE_WINDOW_MS = 10 * 60 * 1000;
|
|
9
|
+
/** Hops `why` follows from a node unless asked for more. */
|
|
10
|
+
const WHY_DEPTH = 3;
|
|
11
|
+
/** Runs per arm `compare` needs before it gives a verdict. */
|
|
12
|
+
const MIN_RUNS = 5;
|
|
13
|
+
/** Recomputed and reported cost further apart than this factor are flagged as a mismatch. */
|
|
14
|
+
const COST_MISMATCH_FACTOR = 3;
|
|
15
|
+
/** Billing weights of cached input against fresh input: reads at a tenth, writes at a quarter more. */
|
|
16
|
+
const CACHE_READ_WEIGHT = 0.1;
|
|
17
|
+
const CACHE_WRITE_WEIGHT = 1.25;
|
|
18
|
+
const UNKNOWN = 'unknown';
|
|
5
19
|
export function ledgerPath(root) {
|
|
6
|
-
return vibePath(root,
|
|
20
|
+
return vibePath(root, LEDGER_FILE);
|
|
7
21
|
}
|
|
8
22
|
export function record(root, event) {
|
|
9
23
|
const full = { at: nowIso(), ...event };
|
|
@@ -14,13 +28,17 @@ export function record(root, event) {
|
|
|
14
28
|
export function recordUsage(root, input) {
|
|
15
29
|
if (!isProjectDir(root))
|
|
16
30
|
return null;
|
|
17
|
-
const run =
|
|
18
|
-
return record(root, {
|
|
31
|
+
const run = `${RUN_PREFIX}${readState(root).runs + 1}`;
|
|
32
|
+
return record(root, {
|
|
33
|
+
event: 'usage', client: input.client, model: input.model, run, detail: input.detail,
|
|
34
|
+
tokens: input.tokens ?? null, costUsd: input.costUsd, ms: input.ms,
|
|
35
|
+
});
|
|
19
36
|
}
|
|
20
37
|
/** An authorize record for `action` inside the window — what lets an irreversible scenario run at all. */
|
|
21
|
-
export function recentAuthorize(root, action, windowMs =
|
|
38
|
+
export function recentAuthorize(root, action, windowMs = AUTHORIZE_WINDOW_MS) {
|
|
22
39
|
const cutoff = Date.now() - windowMs;
|
|
23
|
-
|
|
40
|
+
const authorizes = (e) => e.event === 'authorize' && (e.detail ?? '').startsWith(`${action}:`);
|
|
41
|
+
return readLedger(root).some((e) => authorizes(e) && new Date(e.at).getTime() >= cutoff);
|
|
24
42
|
}
|
|
25
43
|
export function readLedger(root, sinceMs) {
|
|
26
44
|
const all = readJsonl(ledgerPath(root));
|
|
@@ -46,7 +64,7 @@ function nodeMatches(node, query) {
|
|
|
46
64
|
* is the list of edges in the order they were reached — enough to read "regression r-1 was caused
|
|
47
65
|
* by scenario x, which implements file y, decided by chat" without a graph database.
|
|
48
66
|
*/
|
|
49
|
-
export function why(root, query, maxDepth =
|
|
67
|
+
export function why(root, query, maxDepth = WHY_DEPTH) {
|
|
50
68
|
const edges = readEdges(root);
|
|
51
69
|
const start = edges.map((e) => [e.from, e.to]).flat().find((n) => nodeMatches(n, query)) ?? null;
|
|
52
70
|
if (!start)
|
|
@@ -76,7 +94,7 @@ export function why(root, query, maxDepth = 3) {
|
|
|
76
94
|
}
|
|
77
95
|
/** Input tokens as they are billed: cache reads at a tenth, cache writes at a quarter more. */
|
|
78
96
|
export function weightedTokens(t) {
|
|
79
|
-
return t.input +
|
|
97
|
+
return t.input + CACHE_READ_WEIGHT * t.cacheRead + CACHE_WRITE_WEIGHT * t.cacheWrite;
|
|
80
98
|
}
|
|
81
99
|
function metricOf(e, metric) {
|
|
82
100
|
if (metric === 'checks')
|
|
@@ -98,7 +116,7 @@ function armPassed(e) {
|
|
|
98
116
|
function pairKey(e, seenPerTask) {
|
|
99
117
|
if (e.pair)
|
|
100
118
|
return e.pair;
|
|
101
|
-
const task = e.task ??
|
|
119
|
+
const task = e.task ?? UNKNOWN;
|
|
102
120
|
const n = seenPerTask.get(task) ?? 0;
|
|
103
121
|
seenPerTask.set(task, n + 1);
|
|
104
122
|
return `${task}#${n}`;
|
|
@@ -125,13 +143,13 @@ function pairedOnly(checks, by) {
|
|
|
125
143
|
}
|
|
126
144
|
return out;
|
|
127
145
|
}
|
|
128
|
-
/** costRecomputed far (more than
|
|
146
|
+
/** costRecomputed far (more than `COST_MISMATCH_FACTOR`) from the client-reported costUsd — a run worth a second look. */
|
|
129
147
|
function costMismatched(e) {
|
|
130
148
|
const a = e.costRecomputed;
|
|
131
149
|
const b = e.costUsd;
|
|
132
150
|
if (typeof a !== 'number' || typeof b !== 'number' || a === 0 || b === 0)
|
|
133
151
|
return false;
|
|
134
|
-
return Math.max(a, b) / Math.min(a, b) >
|
|
152
|
+
return Math.max(a, b) / Math.min(a, b) > COST_MISMATCH_FACTOR;
|
|
135
153
|
}
|
|
136
154
|
function withUsage(e, metric, usageByRun) {
|
|
137
155
|
const own = metricOf(e, metric);
|
|
@@ -168,13 +186,13 @@ function armKey(e, by) {
|
|
|
168
186
|
if (by === 'client')
|
|
169
187
|
return e.client;
|
|
170
188
|
if (by === 'model')
|
|
171
|
-
return e.model ??
|
|
172
|
-
return e.harness ??
|
|
189
|
+
return e.model ?? UNKNOWN;
|
|
190
|
+
return e.harness ?? UNKNOWN;
|
|
173
191
|
}
|
|
174
192
|
/** `ledgerFile` lets a bench keep its own ledger outside any project. `paired` keeps only runs that
|
|
175
193
|
* pair with a passing run in the other arm on the same task (see `pairedOnly`) — for a bench ledger,
|
|
176
194
|
* where efficiency is only comparable between runs that both did the work. */
|
|
177
|
-
export function compare(root, by, metric, minRuns =
|
|
195
|
+
export function compare(root, by, metric, minRuns = MIN_RUNS, ledgerFile, paired = false, filter = {}) {
|
|
178
196
|
const all = ledgerFile ? readJsonl(ledgerFile) : readLedger(root);
|
|
179
197
|
const events = all.filter((e) => (!filter.client || e.client === filter.client) && (!filter.task || e.task === filter.task));
|
|
180
198
|
const allChecks = events.filter((e) => e.event === 'check');
|
|
@@ -182,9 +200,10 @@ export function compare(root, by, metric, minRuns = 5, ledgerFile, paired = fals
|
|
|
182
200
|
const selected = new Set(checks);
|
|
183
201
|
// What the readers and reviewers spent during a run belongs to that run's cost.
|
|
184
202
|
const usageByRun = new Map();
|
|
185
|
-
for (const e of events)
|
|
203
|
+
for (const e of events) {
|
|
186
204
|
if (e.event === 'usage' && e.run && typeof e.costUsd === 'number')
|
|
187
205
|
usageByRun.set(e.run, (usageByRun.get(e.run) ?? 0) + e.costUsd);
|
|
206
|
+
}
|
|
188
207
|
const groups = new Map();
|
|
189
208
|
for (const e of allChecks) {
|
|
190
209
|
const key = armKey(e, by);
|
|
@@ -199,7 +218,7 @@ export function compare(root, by, metric, minRuns = 5, ledgerFile, paired = fals
|
|
|
199
218
|
runs: events.length,
|
|
200
219
|
usable: values.length,
|
|
201
220
|
stalled: input.filter((e) => e.stalled).length,
|
|
202
|
-
scenarioSets: [...new Set(events.map((e) => e.scenarioSet ??
|
|
221
|
+
scenarioSets: [...new Set(events.map((e) => e.scenarioSet ?? UNKNOWN))],
|
|
203
222
|
range: range(values),
|
|
204
223
|
costMismatch: events.filter(costMismatched).length,
|
|
205
224
|
...(parts ? { tokens: parts } : {}),
|
|
@@ -212,21 +231,26 @@ export function compare(root, by, metric, minRuns = 5, ledgerFile, paired = fals
|
|
|
212
231
|
return { ...base, verdict: 'inconclusive', reason: `more than two arms to compare — filter the ledger to exactly two ${by} arms` };
|
|
213
232
|
const [a, b] = arms;
|
|
214
233
|
if (a.usable < minRuns || b.usable < minRuns) {
|
|
215
|
-
|
|
234
|
+
const counts = `${a.arm} ${a.usable}, ${b.arm} ${b.usable}`;
|
|
235
|
+
return { ...base, verdict: 'insufficient-runs', reason: `fewer than ${minRuns} usable runs per arm (${counts})` };
|
|
216
236
|
}
|
|
217
237
|
const setsA = new Set(a.scenarioSets);
|
|
218
238
|
const setsB = new Set(b.scenarioSets);
|
|
219
239
|
if (setsA.size !== 1 || setsB.size !== 1 || [...setsA][0] !== [...setsB][0]) {
|
|
220
|
-
|
|
240
|
+
const reason = 'the arms did not run the same scenario set — results of different work are not comparable';
|
|
241
|
+
return { ...base, verdict: 'mixed-scenario-sets', reason };
|
|
221
242
|
}
|
|
222
243
|
const first = paired ? sameFirst(checks, by) : null;
|
|
223
|
-
if (first)
|
|
224
|
-
|
|
244
|
+
if (first) {
|
|
245
|
+
const reason = `${first} ran first in every pair — order and arm cannot be told apart; run the arms alternating (bench/run.js --harness a,b)`;
|
|
246
|
+
return { ...base, verdict: 'inconclusive', reason };
|
|
247
|
+
}
|
|
225
248
|
const ra = a.range;
|
|
226
249
|
const rb = b.range;
|
|
227
250
|
const overlap = ra.min <= rb.max && rb.min <= ra.max;
|
|
228
251
|
if (overlap)
|
|
229
252
|
return { ...base, verdict: 'inconclusive', reason: 'observed ranges (min–max) overlap — this sample cannot tell a difference' };
|
|
230
|
-
|
|
253
|
+
const reason = 'ranges do not overlap. "a difference was observed", not "one is better"';
|
|
254
|
+
return { ...base, verdict: 'difference-observed', reason, delta: rb.mean - ra.mean };
|
|
231
255
|
}
|
|
232
256
|
//# sourceMappingURL=ledger.js.map
|