@cavelang/cli 0.27.14 → 0.29.1
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/Authors.md +5 -0
- package/License.md +6 -0
- package/README.md +122 -24
- package/dist/internal/act/action.d.ts +69 -0
- package/dist/internal/act/action.d.ts.map +1 -0
- package/dist/internal/act/action.js +201 -0
- package/dist/internal/act/action.js.map +1 -0
- package/dist/internal/act/declare.d.ts +102 -0
- package/dist/internal/act/declare.d.ts.map +1 -0
- package/dist/internal/act/declare.js +270 -0
- package/dist/internal/act/declare.js.map +1 -0
- package/dist/internal/act/engine.d.ts +103 -0
- package/dist/internal/act/engine.d.ts.map +1 -0
- package/dist/internal/act/engine.js +298 -0
- package/dist/internal/act/engine.js.map +1 -0
- package/dist/internal/act/index.d.ts +27 -0
- package/dist/internal/act/index.d.ts.map +1 -0
- package/dist/internal/act/index.js +25 -0
- package/dist/internal/act/index.js.map +1 -0
- package/dist/internal/automate/automation.d.ts +78 -0
- package/dist/internal/automate/automation.d.ts.map +1 -0
- package/dist/internal/automate/automation.js +135 -0
- package/dist/internal/automate/automation.js.map +1 -0
- package/dist/internal/automate/declare.d.ts +84 -0
- package/dist/internal/automate/declare.d.ts.map +1 -0
- package/dist/internal/automate/declare.js +233 -0
- package/dist/internal/automate/declare.js.map +1 -0
- package/dist/internal/automate/engine.d.ts +125 -0
- package/dist/internal/automate/engine.d.ts.map +1 -0
- package/dist/internal/automate/engine.js +388 -0
- package/dist/internal/automate/engine.js.map +1 -0
- package/dist/internal/automate/index.d.ts +28 -0
- package/dist/internal/automate/index.d.ts.map +1 -0
- package/dist/internal/automate/index.js +26 -0
- package/dist/internal/automate/index.js.map +1 -0
- package/dist/internal/automate/main.d.ts +26 -0
- package/dist/internal/automate/main.d.ts.map +1 -0
- package/dist/internal/automate/main.js +298 -0
- package/dist/internal/automate/main.js.map +1 -0
- package/dist/internal/connect/index.d.ts +26 -0
- package/dist/internal/connect/index.d.ts.map +1 -0
- package/dist/internal/connect/index.js +24 -0
- package/dist/internal/connect/index.js.map +1 -0
- package/dist/internal/connect/main.d.ts +23 -0
- package/dist/internal/connect/main.d.ts.map +1 -0
- package/dist/internal/connect/main.js +330 -0
- package/dist/internal/connect/main.js.map +1 -0
- package/dist/internal/connect/run.d.ts +85 -0
- package/dist/internal/connect/run.d.ts.map +1 -0
- package/dist/internal/connect/run.js +242 -0
- package/dist/internal/connect/run.js.map +1 -0
- package/dist/internal/connect/source.d.ts +44 -0
- package/dist/internal/connect/source.d.ts.map +1 -0
- package/dist/internal/connect/source.js +215 -0
- package/dist/internal/connect/source.js.map +1 -0
- package/dist/internal/connect/template.d.ts +69 -0
- package/dist/internal/connect/template.d.ts.map +1 -0
- package/dist/internal/connect/template.js +221 -0
- package/dist/internal/connect/template.js.map +1 -0
- package/dist/internal/eval/index.d.ts +28 -0
- package/dist/internal/eval/index.d.ts.map +1 -0
- package/dist/internal/eval/index.js +27 -0
- package/dist/internal/eval/index.js.map +1 -0
- package/dist/internal/eval/judge.d.ts +30 -0
- package/dist/internal/eval/judge.d.ts.map +1 -0
- package/dist/internal/eval/judge.js +101 -0
- package/dist/internal/eval/judge.js.map +1 -0
- package/dist/internal/eval/loop.d.ts +64 -0
- package/dist/internal/eval/loop.d.ts.map +1 -0
- package/dist/internal/eval/loop.js +123 -0
- package/dist/internal/eval/loop.js.map +1 -0
- package/dist/internal/eval/main.d.ts +17 -0
- package/dist/internal/eval/main.d.ts.map +1 -0
- package/dist/internal/eval/main.js +236 -0
- package/dist/internal/eval/main.js.map +1 -0
- package/dist/internal/eval/queries.d.ts +74 -0
- package/dist/internal/eval/queries.d.ts.map +1 -0
- package/dist/internal/eval/queries.js +161 -0
- package/dist/internal/eval/queries.js.map +1 -0
- package/dist/internal/eval/run.d.ts +143 -0
- package/dist/internal/eval/run.d.ts.map +1 -0
- package/dist/internal/eval/run.js +376 -0
- package/dist/internal/eval/run.js.map +1 -0
- package/dist/internal/eval/score.d.ts +81 -0
- package/dist/internal/eval/score.d.ts.map +1 -0
- package/dist/internal/eval/score.js +126 -0
- package/dist/internal/eval/score.js.map +1 -0
- package/dist/internal/eval/suite.d.ts +66 -0
- package/dist/internal/eval/suite.d.ts.map +1 -0
- package/dist/internal/eval/suite.js +130 -0
- package/dist/internal/eval/suite.js.map +1 -0
- package/dist/internal/ingest/context.d.ts +20 -0
- package/dist/internal/ingest/context.d.ts.map +1 -0
- package/dist/internal/ingest/context.js +59 -0
- package/dist/internal/ingest/context.js.map +1 -0
- package/dist/internal/ingest/files.d.ts +46 -0
- package/dist/internal/ingest/files.d.ts.map +1 -0
- package/dist/internal/ingest/files.js +115 -0
- package/dist/internal/ingest/files.js.map +1 -0
- package/dist/internal/ingest/index.d.ts +31 -0
- package/dist/internal/ingest/index.d.ts.map +1 -0
- package/dist/internal/ingest/index.js +29 -0
- package/dist/internal/ingest/index.js.map +1 -0
- package/dist/internal/ingest/main.d.ts +12 -0
- package/dist/internal/ingest/main.d.ts.map +1 -0
- package/dist/internal/ingest/main.js +180 -0
- package/dist/internal/ingest/main.js.map +1 -0
- package/dist/internal/ingest/prompt.d.ts +32 -0
- package/dist/internal/ingest/prompt.d.ts.map +1 -0
- package/dist/internal/ingest/prompt.js +75 -0
- package/dist/internal/ingest/prompt.js.map +1 -0
- package/dist/internal/ingest/run.d.ts +142 -0
- package/dist/internal/ingest/run.d.ts.map +1 -0
- package/dist/internal/ingest/run.js +350 -0
- package/dist/internal/ingest/run.js.map +1 -0
- package/dist/internal/ingest/web.d.ts +48 -0
- package/dist/internal/ingest/web.d.ts.map +1 -0
- package/dist/internal/ingest/web.js +140 -0
- package/dist/internal/ingest/web.js.map +1 -0
- package/dist/internal/loop/demo.d.ts +22 -0
- package/dist/internal/loop/demo.d.ts.map +1 -0
- package/dist/internal/loop/demo.js +67 -0
- package/dist/internal/loop/demo.js.map +1 -0
- package/dist/internal/loop/index.d.ts +20 -0
- package/dist/internal/loop/index.d.ts.map +1 -0
- package/dist/internal/loop/index.js +17 -0
- package/dist/internal/loop/index.js.map +1 -0
- package/dist/internal/loop/llm.d.ts +99 -0
- package/dist/internal/loop/llm.d.ts.map +1 -0
- package/dist/internal/loop/llm.js +231 -0
- package/dist/internal/loop/llm.js.map +1 -0
- package/dist/internal/loop/reconstruct.d.ts +87 -0
- package/dist/internal/loop/reconstruct.d.ts.map +1 -0
- package/dist/internal/loop/reconstruct.js +157 -0
- package/dist/internal/loop/reconstruct.js.map +1 -0
- package/dist/internal/loop/sqlite.d.ts +13 -0
- package/dist/internal/loop/sqlite.d.ts.map +1 -0
- package/dist/internal/loop/sqlite.js +33 -0
- package/dist/internal/loop/sqlite.js.map +1 -0
- package/dist/internal/loop/store.d.ts +50 -0
- package/dist/internal/loop/store.d.ts.map +1 -0
- package/dist/internal/loop/store.js +100 -0
- package/dist/internal/loop/store.js.map +1 -0
- package/dist/internal/mcp/bin.d.ts +7 -0
- package/dist/internal/mcp/bin.d.ts.map +1 -0
- package/dist/internal/mcp/bin.js +8 -0
- package/dist/internal/mcp/bin.js.map +1 -0
- package/dist/internal/mcp/index.d.ts +25 -0
- package/dist/internal/mcp/index.d.ts.map +1 -0
- package/dist/internal/mcp/index.js +23 -0
- package/dist/internal/mcp/index.js.map +1 -0
- package/dist/internal/mcp/main.d.ts +23 -0
- package/dist/internal/mcp/main.d.ts.map +1 -0
- package/dist/internal/mcp/main.js +156 -0
- package/dist/internal/mcp/main.js.map +1 -0
- package/dist/internal/mcp/server.d.ts +92 -0
- package/dist/internal/mcp/server.d.ts.map +1 -0
- package/dist/internal/mcp/server.js +251 -0
- package/dist/internal/mcp/server.js.map +1 -0
- package/dist/internal/mcp/tools.d.ts +91 -0
- package/dist/internal/mcp/tools.d.ts.map +1 -0
- package/dist/internal/mcp/tools.js +584 -0
- package/dist/internal/mcp/tools.js.map +1 -0
- package/dist/internal/rules/declare.d.ts +58 -0
- package/dist/internal/rules/declare.d.ts.map +1 -0
- package/dist/internal/rules/declare.js +152 -0
- package/dist/internal/rules/declare.js.map +1 -0
- package/dist/internal/rules/engine.d.ts +125 -0
- package/dist/internal/rules/engine.d.ts.map +1 -0
- package/dist/internal/rules/engine.js +575 -0
- package/dist/internal/rules/engine.js.map +1 -0
- package/dist/internal/rules/index.d.ts +23 -0
- package/dist/internal/rules/index.d.ts.map +1 -0
- package/dist/internal/rules/index.js +21 -0
- package/dist/internal/rules/index.js.map +1 -0
- package/dist/internal/rules/rule.d.ts +88 -0
- package/dist/internal/rules/rule.d.ts.map +1 -0
- package/dist/internal/rules/rule.js +221 -0
- package/dist/internal/rules/rule.js.map +1 -0
- package/dist/internal/shape/check.d.ts +118 -0
- package/dist/internal/shape/check.d.ts.map +1 -0
- package/dist/internal/shape/check.js +331 -0
- package/dist/internal/shape/check.js.map +1 -0
- package/dist/internal/shape/client.d.ts +31 -0
- package/dist/internal/shape/client.d.ts.map +1 -0
- package/dist/internal/shape/client.js +170 -0
- package/dist/internal/shape/client.js.map +1 -0
- package/dist/internal/shape/gate.d.ts +33 -0
- package/dist/internal/shape/gate.d.ts.map +1 -0
- package/dist/internal/shape/gate.js +0 -0
- package/dist/internal/shape/gate.js.map +1 -0
- package/dist/internal/shape/index.d.ts +27 -0
- package/dist/internal/shape/index.d.ts.map +1 -0
- package/dist/internal/shape/index.js +23 -0
- package/dist/internal/shape/index.js.map +1 -0
- package/dist/internal/shape/suggest.d.ts +82 -0
- package/dist/internal/shape/suggest.d.ts.map +1 -0
- package/dist/internal/shape/suggest.js +374 -0
- package/dist/internal/shape/suggest.js.map +1 -0
- package/dist/internal/sync/index.d.ts +22 -0
- package/dist/internal/sync/index.d.ts.map +1 -0
- package/dist/internal/sync/index.js +21 -0
- package/dist/internal/sync/index.js.map +1 -0
- package/dist/internal/sync/sync.d.ts +95 -0
- package/dist/internal/sync/sync.d.ts.map +1 -0
- package/dist/internal/sync/sync.js +342 -0
- package/dist/internal/sync/sync.js.map +1 -0
- package/dist/internal/view/api.d.ts +196 -0
- package/dist/internal/view/api.d.ts.map +1 -0
- package/dist/internal/view/api.js +189 -0
- package/dist/internal/view/api.js.map +1 -0
- package/dist/internal/view/index.d.ts +33 -0
- package/dist/internal/view/index.d.ts.map +1 -0
- package/dist/internal/view/index.js +30 -0
- package/dist/internal/view/index.js.map +1 -0
- package/dist/internal/view/main.d.ts +11 -0
- package/dist/internal/view/main.d.ts.map +1 -0
- package/dist/internal/view/main.js +98 -0
- package/dist/internal/view/main.js.map +1 -0
- package/dist/internal/view/page.d.ts +14 -0
- package/dist/internal/view/page.d.ts.map +1 -0
- package/dist/internal/view/page.js +370 -0
- package/dist/internal/view/page.js.map +1 -0
- package/dist/internal/view/report.d.ts +52 -0
- package/dist/internal/view/report.d.ts.map +1 -0
- package/dist/internal/view/report.js +367 -0
- package/dist/internal/view/report.js.map +1 -0
- package/dist/internal/view/scope.d.ts +11 -0
- package/dist/internal/view/scope.d.ts.map +1 -0
- package/dist/internal/view/scope.js +41 -0
- package/dist/internal/view/scope.js.map +1 -0
- package/dist/internal/view/server.d.ts +35 -0
- package/dist/internal/view/server.d.ts.map +1 -0
- package/dist/internal/view/server.js +141 -0
- package/dist/internal/view/server.js.map +1 -0
- package/dist/src/act.d.ts +3 -0
- package/dist/src/act.d.ts.map +1 -0
- package/dist/src/act.js +3 -0
- package/dist/src/act.js.map +1 -0
- package/dist/src/automate.d.ts +3 -0
- package/dist/src/automate.d.ts.map +1 -0
- package/dist/src/automate.js +3 -0
- package/dist/src/automate.js.map +1 -0
- package/dist/src/cli.d.ts +24 -17
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +408 -107
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands.d.ts +104 -0
- package/dist/src/commands.d.ts.map +1 -0
- package/dist/src/commands.js +33 -0
- package/dist/src/commands.js.map +1 -0
- package/dist/src/connect.d.ts +3 -0
- package/dist/src/connect.d.ts.map +1 -0
- package/dist/src/connect.js +3 -0
- package/dist/src/connect.js.map +1 -0
- package/dist/src/dispatch.d.ts +14 -0
- package/dist/src/dispatch.d.ts.map +1 -0
- package/dist/src/dispatch.js +116 -0
- package/dist/src/dispatch.js.map +1 -0
- package/dist/src/doctor.d.ts +45 -0
- package/dist/src/doctor.d.ts.map +1 -0
- package/dist/src/doctor.js +284 -0
- package/dist/src/doctor.js.map +1 -0
- package/dist/src/eval.d.ts +3 -0
- package/dist/src/eval.d.ts.map +1 -0
- package/dist/src/eval.js +3 -0
- package/dist/src/eval.js.map +1 -0
- package/dist/src/index.d.ts +9 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/ingest.d.ts +3 -0
- package/dist/src/ingest.d.ts.map +1 -0
- package/dist/src/ingest.js +3 -0
- package/dist/src/ingest.js.map +1 -0
- package/dist/src/loop.d.ts +3 -0
- package/dist/src/loop.d.ts.map +1 -0
- package/dist/src/loop.js +3 -0
- package/dist/src/loop.js.map +1 -0
- package/dist/src/main.d.ts +1 -1
- package/dist/src/main.d.ts.map +1 -1
- package/dist/src/main.js +3 -75
- package/dist/src/main.js.map +1 -1
- package/dist/src/mcp.d.ts +3 -0
- package/dist/src/mcp.d.ts.map +1 -0
- package/dist/src/mcp.js +3 -0
- package/dist/src/mcp.js.map +1 -0
- package/dist/src/rules.d.ts +3 -0
- package/dist/src/rules.d.ts.map +1 -0
- package/dist/src/rules.js +3 -0
- package/dist/src/rules.js.map +1 -0
- package/dist/src/shape.d.ts +3 -0
- package/dist/src/shape.d.ts.map +1 -0
- package/dist/src/shape.js +3 -0
- package/dist/src/shape.js.map +1 -0
- package/dist/src/sync.d.ts +3 -0
- package/dist/src/sync.d.ts.map +1 -0
- package/dist/src/sync.js +3 -0
- package/dist/src/sync.js.map +1 -0
- package/dist/src/view.d.ts +3 -0
- package/dist/src/view.d.ts.map +1 -0
- package/dist/src/view.js +3 -0
- package/dist/src/view.js.map +1 -0
- package/package.json +81 -21
- package/src/act.ts +2 -0
- package/src/automate.ts +2 -0
- package/src/cli.ts +416 -102
- package/src/commands.ts +48 -0
- package/src/connect.ts +2 -0
- package/src/dispatch.ts +141 -0
- package/src/doctor.ts +370 -0
- package/src/eval.ts +2 -0
- package/src/index.ts +9 -2
- package/src/ingest.ts +2 -0
- package/src/loop.ts +2 -0
- package/src/main.ts +3 -66
- package/src/mcp.ts +2 -0
- package/src/rules.ts +2 -0
- package/src/shape.ts +2 -0
- package/src/sync.ts +2 -0
- package/src/view.ts +2 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claim scoring — the produced extraction against the golden (roadmap
|
|
3
|
+
* item 9).
|
|
4
|
+
*
|
|
5
|
+
* Both sides run through the same pipeline: parse → canonicalize → strip
|
|
6
|
+
* actor stamps → re-key → keep the last claim per key. Actor stamps are
|
|
7
|
+
* the `@src:` contexts appended by the engine itself under spec §9.5
|
|
8
|
+
* (`@src:cli`, `@src:agent/<name>`, `@src:ingest`) — which actor
|
|
9
|
+
* happened to write a claim must not shift its key away from the golden's,
|
|
10
|
+
* while *content* sources the fixture author wrote (`@src:maria`,
|
|
11
|
+
* `@src:notes.md`) stay part of claim identity: the golden decides which
|
|
12
|
+
* contexts extraction is expected to produce.
|
|
13
|
+
*
|
|
14
|
+
* A golden claim *matches* a produced claim when their normalized keys are
|
|
15
|
+
* equal and their values agree — numerically within a relative tolerance
|
|
16
|
+
* (units must agree; `~` approximation is metadata), textually otherwise.
|
|
17
|
+
* Relation and existence claims carry their object in the key, so the key
|
|
18
|
+
* alone decides. Confidence, tags, `+/-` uncertainty, importance and
|
|
19
|
+
* comments are metadata and never scored; a key that matches with a
|
|
20
|
+
* disagreeing value is counted separately (`valueOff`) — the right fact,
|
|
21
|
+
* the wrong value.
|
|
22
|
+
*/
|
|
23
|
+
import { Claim, Key, Value } from '@cavelang/core';
|
|
24
|
+
import { canonicalizeText, emitClaim, standardRegistry } from '@cavelang/canonical';
|
|
25
|
+
import { Files } from '@cavelang/cli/ingest';
|
|
26
|
+
/** Actor-stamp sources appended by the engine (spec §9.5), ignored in scoring. */
|
|
27
|
+
const actorStampRe = /^src:(?:cli$|agent\/|ingest$)/;
|
|
28
|
+
/** @returns the claim without engine-appended actor stamps. */
|
|
29
|
+
export const normalize = (claim) => {
|
|
30
|
+
const contexts = claim.contexts.filter(context => !actorStampRe.test(context));
|
|
31
|
+
return contexts.length === claim.contexts.length ? claim : { ...claim, contexts };
|
|
32
|
+
};
|
|
33
|
+
/** @returns the claim key of the normalized claim. */
|
|
34
|
+
export const keyOf = (claim) => Key.of(normalize(claim));
|
|
35
|
+
/**
|
|
36
|
+
* @returns one fact per normalized key, the last claim winning — the same
|
|
37
|
+
* latest-wins semantics the store gives a belief series (spec §9.1).
|
|
38
|
+
*/
|
|
39
|
+
export const factsOf = (claims) => {
|
|
40
|
+
const byKey = new Map();
|
|
41
|
+
for (const claim of claims) {
|
|
42
|
+
byKey.set(keyOf(claim), claim);
|
|
43
|
+
}
|
|
44
|
+
return [...byKey].map(([key, claim]) => ({ key, claim }));
|
|
45
|
+
};
|
|
46
|
+
/** Parses a golden document into facts; parse problems are fixture problems. */
|
|
47
|
+
export const goldenFacts = (text, registry = standardRegistry) => {
|
|
48
|
+
const result = canonicalizeText(text, registry);
|
|
49
|
+
return {
|
|
50
|
+
facts: factsOf(result.claims.map(entry => entry.claim)),
|
|
51
|
+
problems: result.problems.map(problem => `golden line ${problem.line}: ${problem.message}`)
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* @returns the facts an extraction run produced — the store's current
|
|
56
|
+
* beliefs minus the orchestrator's own `ingest-digest` provenance claims
|
|
57
|
+
* (`@cavelang/cli/ingest` bookkeeping, not extracted knowledge).
|
|
58
|
+
*/
|
|
59
|
+
export const producedFacts = (store) => factsOf(store.currentBeliefs()
|
|
60
|
+
.filter(row => row.attribute !== Files.digestAttribute)
|
|
61
|
+
.map(row => store.toClaim(row)));
|
|
62
|
+
const valueOf = (claim) => claim.payload.kind === 'attribute' ? claim.payload.value :
|
|
63
|
+
claim.payload.kind === 'metric' ? claim.payload.value :
|
|
64
|
+
undefined;
|
|
65
|
+
/**
|
|
66
|
+
* @returns whether the produced value agrees with the golden's: equal
|
|
67
|
+
* numbers (within `tolerance`, relative to the golden) under equal units,
|
|
68
|
+
* or the exact same canonical text. Claims without a value (relations,
|
|
69
|
+
* existence) always agree — their key already carries the object.
|
|
70
|
+
*/
|
|
71
|
+
export const valueAgrees = (golden, produced, tolerance = 0) => {
|
|
72
|
+
const goldenValue = valueOf(golden);
|
|
73
|
+
const producedValue = valueOf(produced);
|
|
74
|
+
if (goldenValue === undefined || producedValue === undefined) {
|
|
75
|
+
return goldenValue === producedValue;
|
|
76
|
+
}
|
|
77
|
+
if (goldenValue.num !== undefined && producedValue.num !== undefined) {
|
|
78
|
+
if ((goldenValue.unit ?? '') !== (producedValue.unit ?? '')) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
return goldenValue.num === producedValue.num ||
|
|
82
|
+
Math.abs(producedValue.num - goldenValue.num) <= tolerance * Math.abs(goldenValue.num);
|
|
83
|
+
}
|
|
84
|
+
return Value.format(goldenValue) === Value.format(producedValue);
|
|
85
|
+
};
|
|
86
|
+
const ratio = (numerator, denominator) => denominator === 0 ? 0 : numerator / denominator;
|
|
87
|
+
/** @returns the F1 of a precision/recall pair, 0 when both are 0. */
|
|
88
|
+
export const f1Of = (precision, recall) => precision + recall === 0 ? 0 : (2 * precision * recall) / (precision + recall);
|
|
89
|
+
/** Compares produced facts against golden facts. */
|
|
90
|
+
export const compare = (golden, produced, options = {}) => {
|
|
91
|
+
const byKey = new Map(produced.map(fact => [fact.key, fact]));
|
|
92
|
+
const misses = [];
|
|
93
|
+
const matchedKeys = new Set();
|
|
94
|
+
let matched = 0;
|
|
95
|
+
let valueOff = 0;
|
|
96
|
+
for (const fact of golden) {
|
|
97
|
+
const candidate = byKey.get(fact.key);
|
|
98
|
+
if (candidate !== undefined && valueAgrees(fact.claim, candidate.claim, options.tolerance)) {
|
|
99
|
+
matched += 1;
|
|
100
|
+
matchedKeys.add(fact.key);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
if (candidate !== undefined) {
|
|
104
|
+
valueOff += 1;
|
|
105
|
+
}
|
|
106
|
+
misses.push(fact);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const extras = produced.filter(fact => !matchedKeys.has(fact.key));
|
|
110
|
+
const precision = ratio(matched, produced.length);
|
|
111
|
+
const recall = ratio(matched, golden.length);
|
|
112
|
+
return {
|
|
113
|
+
golden: golden.length,
|
|
114
|
+
produced: produced.length,
|
|
115
|
+
matched,
|
|
116
|
+
valueOff,
|
|
117
|
+
misses,
|
|
118
|
+
extras,
|
|
119
|
+
precision,
|
|
120
|
+
recall,
|
|
121
|
+
f1: f1Of(precision, recall)
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
/** @returns the canonical line of a fact, for reports and judge prompts. */
|
|
125
|
+
export const lineOf = (fact) => emitClaim(normalize(fact.claim));
|
|
126
|
+
//# sourceMappingURL=score.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"score.js","sourceRoot":"","sources":["../../src/score.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Suite discovery — eval fixtures as plain files.
|
|
3
|
+
*
|
|
4
|
+
* A suite is any directory; a *case* is named by its golden file:
|
|
5
|
+
*
|
|
6
|
+
* ```
|
|
7
|
+
* suite/
|
|
8
|
+
* instructions.md (optional, shared by the suite)
|
|
9
|
+
* family-history.md the source the agent extracts from
|
|
10
|
+
* family-history.golden.cave the expected extraction
|
|
11
|
+
* family-history.queries.cave (optional) CAVE-Q behavioral checks
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* For `<stem>.golden.cave` the source is the single sibling `<stem>.<ext>`
|
|
15
|
+
* whose extension has no further dots — so goldens, queries and
|
|
16
|
+
* instructions of this or other cases never masquerade as sources, while
|
|
17
|
+
* `design.notes.md` still pairs with `design.notes.golden.cave`. Zero or
|
|
18
|
+
* several candidates is a fixture problem, reported instead of guessed.
|
|
19
|
+
*
|
|
20
|
+
* A `<stem>.loop.cave` sibling makes the case a *reconstruction* case
|
|
21
|
+
* (spec §18): the source is the knowledge (CAVE text), the loop
|
|
22
|
+
* file declares seeds and budgets, and the golden is the expected
|
|
23
|
+
* reconstruction — see `loop.ts`.
|
|
24
|
+
*
|
|
25
|
+
* Instructions resolve nearest-first: an explicit path (CLI `--instructions`)
|
|
26
|
+
* beats `<stem>.instructions.md` beats the case directory's
|
|
27
|
+
* `instructions.md` beats the suite root's.
|
|
28
|
+
*/
|
|
29
|
+
export declare const goldenSuffix = ".golden.cave";
|
|
30
|
+
export declare const queriesSuffix = ".queries.cave";
|
|
31
|
+
export declare const loopSuffix = ".loop.cave";
|
|
32
|
+
export declare const instructionsSuffix = ".instructions.md";
|
|
33
|
+
/** Suite-shared instructions file name. */
|
|
34
|
+
export declare const sharedInstructions = "instructions.md";
|
|
35
|
+
export type Case = {
|
|
36
|
+
/** Display name — the golden's path relative to `cwd`, suffix dropped. */
|
|
37
|
+
readonly name: string;
|
|
38
|
+
/**
|
|
39
|
+
* Absolute source file: what the agent extracts from — or, for a
|
|
40
|
+
* reconstruction case, the knowledge the loop runs over.
|
|
41
|
+
*/
|
|
42
|
+
readonly source: string;
|
|
43
|
+
/** Absolute golden `.cave` path. */
|
|
44
|
+
readonly golden: string;
|
|
45
|
+
/** Absolute queries file path, when the case has one. */
|
|
46
|
+
readonly queries?: string;
|
|
47
|
+
/** Absolute loop file path — present on reconstruction cases (item 10). */
|
|
48
|
+
readonly loop?: string;
|
|
49
|
+
/** Absolute instructions markdown path, when one resolves. */
|
|
50
|
+
readonly instructions?: string;
|
|
51
|
+
};
|
|
52
|
+
export type Suite = {
|
|
53
|
+
/** Discovered cases, sorted by name. */
|
|
54
|
+
readonly cases: readonly Case[];
|
|
55
|
+
/** Fixture problems — goldens that could not become cases. */
|
|
56
|
+
readonly problems: readonly string[];
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Discovers the cases of one or more suites. Each root may be a directory
|
|
60
|
+
* (searched recursively for `*.golden.cave`) or a single golden file.
|
|
61
|
+
*/
|
|
62
|
+
export declare const discover: (roots: readonly string[], options?: {
|
|
63
|
+
instructions?: string;
|
|
64
|
+
cwd?: string;
|
|
65
|
+
}) => Suite;
|
|
66
|
+
//# sourceMappingURL=suite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suite.d.ts","sourceRoot":"","sources":["../../src/suite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAKH,eAAO,MAAM,YAAY,iBAAiB,CAAA;AAC1C,eAAO,MAAM,aAAa,kBAAkB,CAAA;AAC5C,eAAO,MAAM,UAAU,eAAe,CAAA;AACtC,eAAO,MAAM,kBAAkB,qBAAqB,CAAA;AAEpD,2CAA2C;AAC3C,eAAO,MAAM,kBAAkB,oBAAoB,CAAA;AAEnD,MAAM,MAAM,IAAI,GAAG;IACjB,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,oCAAoC;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,yDAAyD;IACzD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,8DAA8D;IAC9D,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,KAAK,GAAG;IAClB,wCAAwC;IACxC,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAA;IAC/B,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CACrC,CAAA;AAyDD;;;GAGG;AACH,eAAO,MAAM,QAAQ,GACnB,OAAO,SAAS,MAAM,EAAE,EACxB,UAAS;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,KACpD,KAuCF,CAAA"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Suite discovery — eval fixtures as plain files.
|
|
3
|
+
*
|
|
4
|
+
* A suite is any directory; a *case* is named by its golden file:
|
|
5
|
+
*
|
|
6
|
+
* ```
|
|
7
|
+
* suite/
|
|
8
|
+
* instructions.md (optional, shared by the suite)
|
|
9
|
+
* family-history.md the source the agent extracts from
|
|
10
|
+
* family-history.golden.cave the expected extraction
|
|
11
|
+
* family-history.queries.cave (optional) CAVE-Q behavioral checks
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* For `<stem>.golden.cave` the source is the single sibling `<stem>.<ext>`
|
|
15
|
+
* whose extension has no further dots — so goldens, queries and
|
|
16
|
+
* instructions of this or other cases never masquerade as sources, while
|
|
17
|
+
* `design.notes.md` still pairs with `design.notes.golden.cave`. Zero or
|
|
18
|
+
* several candidates is a fixture problem, reported instead of guessed.
|
|
19
|
+
*
|
|
20
|
+
* A `<stem>.loop.cave` sibling makes the case a *reconstruction* case
|
|
21
|
+
* (spec §18): the source is the knowledge (CAVE text), the loop
|
|
22
|
+
* file declares seeds and budgets, and the golden is the expected
|
|
23
|
+
* reconstruction — see `loop.ts`.
|
|
24
|
+
*
|
|
25
|
+
* Instructions resolve nearest-first: an explicit path (CLI `--instructions`)
|
|
26
|
+
* beats `<stem>.instructions.md` beats the case directory's
|
|
27
|
+
* `instructions.md` beats the suite root's.
|
|
28
|
+
*/
|
|
29
|
+
import { existsSync, globSync, readdirSync, statSync } from 'node:fs';
|
|
30
|
+
import { basename, dirname, join, relative, resolve } from 'node:path';
|
|
31
|
+
export const goldenSuffix = '.golden.cave';
|
|
32
|
+
export const queriesSuffix = '.queries.cave';
|
|
33
|
+
export const loopSuffix = '.loop.cave';
|
|
34
|
+
export const instructionsSuffix = '.instructions.md';
|
|
35
|
+
/** Suite-shared instructions file name. */
|
|
36
|
+
export const sharedInstructions = 'instructions.md';
|
|
37
|
+
/** @returns source candidates: `<stem>.<ext>` siblings with a dot-free extension. */
|
|
38
|
+
const sourcesOf = (golden) => {
|
|
39
|
+
const dir = dirname(golden);
|
|
40
|
+
const stem = basename(golden).slice(0, -goldenSuffix.length);
|
|
41
|
+
return readdirSync(dir)
|
|
42
|
+
.filter(name => {
|
|
43
|
+
if (!name.startsWith(`${stem}.`)) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
const extension = name.slice(stem.length + 1);
|
|
47
|
+
return extension !== '' && !extension.includes('.') && statSync(join(dir, name)).isFile();
|
|
48
|
+
})
|
|
49
|
+
.sort()
|
|
50
|
+
.map(name => join(dir, name));
|
|
51
|
+
};
|
|
52
|
+
const instructionsOf = (golden, root, explicit) => {
|
|
53
|
+
const candidates = [
|
|
54
|
+
explicit,
|
|
55
|
+
`${golden.slice(0, -goldenSuffix.length)}${instructionsSuffix}`,
|
|
56
|
+
join(dirname(golden), sharedInstructions),
|
|
57
|
+
join(root, sharedInstructions)
|
|
58
|
+
];
|
|
59
|
+
return candidates.find(path => path !== undefined && existsSync(path));
|
|
60
|
+
};
|
|
61
|
+
const caseOf = (golden, root, cwd, explicit) => {
|
|
62
|
+
const sources = sourcesOf(golden);
|
|
63
|
+
const name = relative(cwd, golden).slice(0, -goldenSuffix.length);
|
|
64
|
+
if (sources.length === 0) {
|
|
65
|
+
return { problem: `${name}: no source file — expected a single ${basename(golden).slice(0, -goldenSuffix.length)}.<ext> beside ${basename(golden)}` };
|
|
66
|
+
}
|
|
67
|
+
if (sources.length > 1) {
|
|
68
|
+
return { problem: `${name}: ambiguous source — ${sources.map(source => basename(source)).join(', ')}` };
|
|
69
|
+
}
|
|
70
|
+
const queries = `${golden.slice(0, -goldenSuffix.length)}${queriesSuffix}`;
|
|
71
|
+
const loop = `${golden.slice(0, -goldenSuffix.length)}${loopSuffix}`;
|
|
72
|
+
const instructions = instructionsOf(golden, root, explicit);
|
|
73
|
+
return {
|
|
74
|
+
kase: {
|
|
75
|
+
name,
|
|
76
|
+
source: sources[0],
|
|
77
|
+
golden,
|
|
78
|
+
...existsSync(queries) ? { queries } : {},
|
|
79
|
+
...existsSync(loop) ? { loop } : {},
|
|
80
|
+
...instructions === undefined ? {} : { instructions }
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Discovers the cases of one or more suites. Each root may be a directory
|
|
86
|
+
* (searched recursively for `*.golden.cave`) or a single golden file.
|
|
87
|
+
*/
|
|
88
|
+
export const discover = (roots, options = {}) => {
|
|
89
|
+
const cwd = options.cwd ?? process.cwd();
|
|
90
|
+
const explicit = options.instructions === undefined ? undefined : resolve(cwd, options.instructions);
|
|
91
|
+
const cases = [];
|
|
92
|
+
const problems = [];
|
|
93
|
+
for (const root of roots) {
|
|
94
|
+
const absolute = resolve(cwd, root);
|
|
95
|
+
if (!existsSync(absolute)) {
|
|
96
|
+
problems.push(`${root}: no such file or directory`);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (statSync(absolute).isFile()) {
|
|
100
|
+
if (!absolute.endsWith(goldenSuffix)) {
|
|
101
|
+
problems.push(`${root}: not a suite directory or ${goldenSuffix} file`);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const outcome = caseOf(absolute, dirname(absolute), cwd, explicit);
|
|
105
|
+
if ('kase' in outcome) {
|
|
106
|
+
cases.push(outcome.kase);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
problems.push(outcome.problem);
|
|
110
|
+
}
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const goldens = globSync(`**/*${goldenSuffix}`, { cwd: absolute }).sort();
|
|
114
|
+
if (goldens.length === 0) {
|
|
115
|
+
problems.push(`${root}: no ${goldenSuffix} cases found`);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
for (const golden of goldens) {
|
|
119
|
+
const outcome = caseOf(join(absolute, golden), absolute, cwd, explicit);
|
|
120
|
+
if ('kase' in outcome) {
|
|
121
|
+
cases.push(outcome.kase);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
problems.push(outcome.problem);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return { cases: cases.sort((a, b) => a.name.localeCompare(b.name)), problems };
|
|
129
|
+
};
|
|
130
|
+
//# sourceMappingURL=suite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suite.js","sourceRoot":"","sources":["../../src/suite.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Existing-knowledge context for an ingestion batch.
|
|
3
|
+
*
|
|
4
|
+
* Neither extreme works: dumping the whole database into every prompt
|
|
5
|
+
* stops scaling almost immediately, and tools-only leaves the model blind
|
|
6
|
+
* to established naming conventions and prone to duplicates. The middle
|
|
7
|
+
* road injected here is a small *relevant* slice — store statistics, the
|
|
8
|
+
* most-connected entities (naming anchors), and claims matching the batch
|
|
9
|
+
* files' path tokens — while the agent keeps full API access through the
|
|
10
|
+
* `cave_*` MCP tools for anything deeper.
|
|
11
|
+
*/
|
|
12
|
+
import type { Store } from '@cavelang/store';
|
|
13
|
+
/** Tokens worth searching for, derived from a file path or URL. */
|
|
14
|
+
export declare const pathTokens: (path: string) => string[];
|
|
15
|
+
/**
|
|
16
|
+
* @returns a compact knowledge-context block for the batch, capped at
|
|
17
|
+
* `limit` claim lines; `undefined` for an empty store.
|
|
18
|
+
*/
|
|
19
|
+
export declare const contextFor: (store: Store, paths: readonly string[], limit?: number) => undefined | string;
|
|
20
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAE5C,mEAAmE;AACnE,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,MAAM,EAO/C,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,KAAK,EAAE,OAAO,SAAS,MAAM,EAAE,EAAE,cAAU,KAAG,SAAS,GAAG,MAgC3F,CAAA"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Existing-knowledge context for an ingestion batch.
|
|
3
|
+
*
|
|
4
|
+
* Neither extreme works: dumping the whole database into every prompt
|
|
5
|
+
* stops scaling almost immediately, and tools-only leaves the model blind
|
|
6
|
+
* to established naming conventions and prone to duplicates. The middle
|
|
7
|
+
* road injected here is a small *relevant* slice — store statistics, the
|
|
8
|
+
* most-connected entities (naming anchors), and claims matching the batch
|
|
9
|
+
* files' path tokens — while the agent keeps full API access through the
|
|
10
|
+
* `cave_*` MCP tools for anything deeper.
|
|
11
|
+
*/
|
|
12
|
+
import { emitClaim } from '@cavelang/canonical';
|
|
13
|
+
/** Tokens worth searching for, derived from a file path or URL. */
|
|
14
|
+
export const pathTokens = (path) => {
|
|
15
|
+
const parts = path
|
|
16
|
+
.split(/[/\\?#&=]/)
|
|
17
|
+
.flatMap(segment => segment.split('.'))
|
|
18
|
+
.filter(token => token.length >= 3 &&
|
|
19
|
+
!/^(src|test|index|json|md|ts|js|tsx|jsx|txt|yaml|yml|https?:|www|com|net|org|html|htm)$/.test(token));
|
|
20
|
+
return [...new Set(parts)];
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* @returns a compact knowledge-context block for the batch, capped at
|
|
24
|
+
* `limit` claim lines; `undefined` for an empty store.
|
|
25
|
+
*/
|
|
26
|
+
export const contextFor = (store, paths, limit = 40) => {
|
|
27
|
+
const current = store.currentBeliefs();
|
|
28
|
+
if (current.length === 0) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
const degree = new Map();
|
|
32
|
+
for (const row of current) {
|
|
33
|
+
degree.set(row.subject, (degree.get(row.subject) ?? 0) + 1);
|
|
34
|
+
if (row.object !== null) {
|
|
35
|
+
degree.set(row.object, (degree.get(row.object) ?? 0) + 1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const topEntities = [...degree.entries()]
|
|
39
|
+
.sort((a, b) => b[1] - a[1])
|
|
40
|
+
.slice(0, 15)
|
|
41
|
+
.map(([entity, count]) => `${entity} (${count})`);
|
|
42
|
+
const related = new Map();
|
|
43
|
+
for (const token of paths.flatMap(pathTokens)) {
|
|
44
|
+
for (const row of store.search(token, { limit: 5 })) {
|
|
45
|
+
if (related.size >= limit) {
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
related.set(row.claim_key, emitClaim(store.toClaim(row)));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return [
|
|
52
|
+
`The database currently holds ${current.length} current belief(s).`,
|
|
53
|
+
`Established entities (use these names, do not invent variants): ${topEntities.join(', ')}`,
|
|
54
|
+
...related.size > 0 ?
|
|
55
|
+
['Existing claims related to this batch:', ...[...related.values()].map(line => ` ${line}`)] :
|
|
56
|
+
[]
|
|
57
|
+
].join('\n');
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File selection for ingestion: glob expansion, batching, and the
|
|
3
|
+
* incremental-skip bookkeeping.
|
|
4
|
+
*
|
|
5
|
+
* Ingestion provenance is recorded as ordinary CAVE claims —
|
|
6
|
+
* `<path> HAS ingest-digest: <sha256/12> @src:cave-ingest` — so "which
|
|
7
|
+
* files are already ingested at which content version" lives in the same
|
|
8
|
+
* append-only store as the knowledge itself, and re-running `cave ingest`
|
|
9
|
+
* over a monorepo only processes files whose content changed.
|
|
10
|
+
*/
|
|
11
|
+
import type { Store } from '@cavelang/store';
|
|
12
|
+
/** Digest attribute name used in provenance claims. */
|
|
13
|
+
export declare const digestAttribute = "ingest-digest";
|
|
14
|
+
/** Context marking provenance claims. */
|
|
15
|
+
export declare const provenanceContext = "src:cave-ingest";
|
|
16
|
+
/** @returns matching regular-file paths — globs expanded, directories dropped, deduplicated, sorted. */
|
|
17
|
+
export declare const expand: (patterns: readonly string[], cwd?: string) => string[];
|
|
18
|
+
/** @returns first 12 hex chars of the content's sha256. */
|
|
19
|
+
export declare const digestOf: (content: string) => string;
|
|
20
|
+
export type Selected = {
|
|
21
|
+
readonly path: string;
|
|
22
|
+
readonly digest: string;
|
|
23
|
+
/** Pre-fetched content (URL sources); files are read from disk instead. */
|
|
24
|
+
readonly content?: string;
|
|
25
|
+
};
|
|
26
|
+
export type Selection = {
|
|
27
|
+
readonly files: readonly Selected[];
|
|
28
|
+
/** Files skipped because their current digest claim matches. */
|
|
29
|
+
readonly skipped: readonly string[];
|
|
30
|
+
};
|
|
31
|
+
/** @returns whether the source's current `ingest-digest` belief matches. */
|
|
32
|
+
export declare const isIngested: (store: Store, path: string, digest: string) => boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Reads and digests candidate files (paths relative to `cwd`), skipping
|
|
35
|
+
* the ones whose current `ingest-digest` belief already matches (pass
|
|
36
|
+
* `force` to re-ingest all).
|
|
37
|
+
*/
|
|
38
|
+
export declare const select: (store: Store, paths: readonly string[], options?: {
|
|
39
|
+
force?: boolean;
|
|
40
|
+
cwd?: string;
|
|
41
|
+
}) => Selection;
|
|
42
|
+
/** Records provenance claims for successfully ingested files. */
|
|
43
|
+
export declare const recordDigests: (store: Store, files: readonly Selected[]) => void;
|
|
44
|
+
/** @returns `files` split into batches of at most `size`. */
|
|
45
|
+
export declare const batch: <T>(files: readonly T[], size: number) => T[][];
|
|
46
|
+
//# sourceMappingURL=files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/files.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAE5C,uDAAuD;AACvD,eAAO,MAAM,eAAe,kBAAkB,CAAA;AAE9C,yCAAyC;AACzC,eAAO,MAAM,iBAAiB,oBAAoB,CAAA;AAiClD,wGAAwG;AACxG,eAAO,MAAM,MAAM,GAAI,UAAU,SAAS,MAAM,EAAE,EAAE,MAAK,MAAsB,KAAG,MAAM,EAKvF,CAAA;AAED,2DAA2D;AAC3D,eAAO,MAAM,QAAQ,GAAI,SAAS,MAAM,KAAG,MACsB,CAAA;AAMjE,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAA;IACnC,gEAAgE;IAChE,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CACpC,CAAA;AAED,4EAA4E;AAC5E,eAAO,MAAM,UAAU,GAAI,OAAO,KAAK,EAAE,MAAM,MAAM,EAAE,QAAQ,MAAM,KAAG,OAGvE,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,MAAM,GACjB,OAAO,KAAK,EACZ,OAAO,SAAS,MAAM,EAAE,EACxB,UAAS;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,KAC9C,SAaF,CAAA;AAED,iEAAiE;AACjE,eAAO,MAAM,aAAa,GAAI,OAAO,KAAK,EAAE,OAAO,SAAS,QAAQ,EAAE,KAAG,IAkBxE,CAAA;AAED,6DAA6D;AAC7D,eAAO,MAAM,KAAK,GAAI,CAAC,EAAE,OAAO,SAAS,CAAC,EAAE,EAAE,MAAM,MAAM,KAAG,CAAC,EAAE,EAS/D,CAAA"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File selection for ingestion: glob expansion, batching, and the
|
|
3
|
+
* incremental-skip bookkeeping.
|
|
4
|
+
*
|
|
5
|
+
* Ingestion provenance is recorded as ordinary CAVE claims —
|
|
6
|
+
* `<path> HAS ingest-digest: <sha256/12> @src:cave-ingest` — so "which
|
|
7
|
+
* files are already ingested at which content version" lives in the same
|
|
8
|
+
* append-only store as the knowledge itself, and re-running `cave ingest`
|
|
9
|
+
* over a monorepo only processes files whose content changed.
|
|
10
|
+
*/
|
|
11
|
+
import { createHash } from 'node:crypto';
|
|
12
|
+
import { globSync, readFileSync, statSync } from 'node:fs';
|
|
13
|
+
import { resolve as resolvePath } from 'node:path';
|
|
14
|
+
import { Key, Claim, Value } from '@cavelang/core';
|
|
15
|
+
/** Digest attribute name used in provenance claims. */
|
|
16
|
+
export const digestAttribute = 'ingest-digest';
|
|
17
|
+
/** Context marking provenance claims. */
|
|
18
|
+
export const provenanceContext = 'src:cave-ingest';
|
|
19
|
+
/**
|
|
20
|
+
* File paths normally remain entity atoms for compatibility with existing
|
|
21
|
+
* provenance. Paths that would be split or interpreted as metadata use a
|
|
22
|
+
* code literal so their exact spelling round-trips through CAVE text.
|
|
23
|
+
*/
|
|
24
|
+
const provenanceSubject = (path) => {
|
|
25
|
+
const isEntityAtom = path !== '' &&
|
|
26
|
+
!/[\s"`;]/u.test(path) &&
|
|
27
|
+
!/^(?:[@#]|\+\/-|!$|\(\d+(?:\.\d+)?σ\)$)/u.test(path);
|
|
28
|
+
if (isEntityAtom) {
|
|
29
|
+
return Claim.entity(path);
|
|
30
|
+
}
|
|
31
|
+
// Prefer a code literal for path-like data; use text when the path itself
|
|
32
|
+
// contains a backtick. CAVE has no literal escape syntax, so a path with
|
|
33
|
+
// both delimiters needs a deterministic encoded representation to remain
|
|
34
|
+
// valid through canonical export/import.
|
|
35
|
+
if (path.includes('`')) {
|
|
36
|
+
return path.includes('"') ? Claim.code(`percent-encoded:${encodeURIComponent(path)}`) : Claim.text(path);
|
|
37
|
+
}
|
|
38
|
+
return Claim.code(path);
|
|
39
|
+
};
|
|
40
|
+
/** One construction path keeps digest lookup and storage identities identical. */
|
|
41
|
+
const provenanceClaim = (path, digest) => Claim.of({
|
|
42
|
+
subject: provenanceSubject(path),
|
|
43
|
+
verb: 'HAS',
|
|
44
|
+
payload: Claim.attribute(digestAttribute, Value.parse(digest)),
|
|
45
|
+
contexts: [provenanceContext]
|
|
46
|
+
});
|
|
47
|
+
/** @returns matching regular-file paths — globs expanded, directories dropped, deduplicated, sorted. */
|
|
48
|
+
export const expand = (patterns, cwd = process.cwd()) => {
|
|
49
|
+
const matched = patterns.flatMap(pattern => globSync(pattern, { cwd }));
|
|
50
|
+
return [...new Set(matched)]
|
|
51
|
+
.filter(path => statSync(resolvePath(cwd, path)).isFile())
|
|
52
|
+
.sort();
|
|
53
|
+
};
|
|
54
|
+
/** @returns first 12 hex chars of the content's sha256. */
|
|
55
|
+
export const digestOf = (content) => createHash('sha256').update(content).digest('hex').slice(0, 12);
|
|
56
|
+
/** Claim key of a file's provenance claim (value excluded by design, §9.2). */
|
|
57
|
+
const provenanceKey = (path) => Key.of(provenanceClaim(path, 'x'));
|
|
58
|
+
/** @returns whether the source's current `ingest-digest` belief matches. */
|
|
59
|
+
export const isIngested = (store, path, digest) => {
|
|
60
|
+
const known = store.currentBelief(provenanceKey(path));
|
|
61
|
+
return known !== undefined && known.value_text === digest && known.conf > 0;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Reads and digests candidate files (paths relative to `cwd`), skipping
|
|
65
|
+
* the ones whose current `ingest-digest` belief already matches (pass
|
|
66
|
+
* `force` to re-ingest all).
|
|
67
|
+
*/
|
|
68
|
+
export const select = (store, paths, options = {}) => {
|
|
69
|
+
const files = [];
|
|
70
|
+
const skipped = [];
|
|
71
|
+
const cwd = options.cwd ?? process.cwd();
|
|
72
|
+
for (const path of paths) {
|
|
73
|
+
const digest = digestOf(readFileSync(resolvePath(cwd, path), 'utf8'));
|
|
74
|
+
if (options.force !== true && isIngested(store, path, digest)) {
|
|
75
|
+
skipped.push(path);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
files.push({ path, digest });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return { files, skipped };
|
|
82
|
+
};
|
|
83
|
+
/** Records provenance claims for successfully ingested files. */
|
|
84
|
+
export const recordDigests = (store, files) => {
|
|
85
|
+
if (files.length === 0) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
store.insertResult({
|
|
90
|
+
claims: files.map((file, index) => ({
|
|
91
|
+
line: index + 1,
|
|
92
|
+
claim: provenanceClaim(file.path, file.digest)
|
|
93
|
+
})),
|
|
94
|
+
edges: [],
|
|
95
|
+
registry: store.registry(),
|
|
96
|
+
problems: []
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
const sources = files.map(file => JSON.stringify(file.path)).join(', ');
|
|
101
|
+
throw new Error(`failed to record ingest digest(s) for ${sources}`, { cause: error });
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
/** @returns `files` split into batches of at most `size`. */
|
|
105
|
+
export const batch = (files, size) => {
|
|
106
|
+
if (!(size >= 1)) {
|
|
107
|
+
throw new Error(`batch size must be >= 1, got ${size}`);
|
|
108
|
+
}
|
|
109
|
+
const batches = [];
|
|
110
|
+
for (let at = 0; at < files.length; at += size) {
|
|
111
|
+
batches.push(files.slice(at, at + size));
|
|
112
|
+
}
|
|
113
|
+
return batches;
|
|
114
|
+
};
|
|
115
|
+
//# sourceMappingURL=files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/files.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@cavelang/cli/ingest` — LLM-driven knowledge ingestion.
|
|
3
|
+
*
|
|
4
|
+
* ```sh
|
|
5
|
+
* cave ingest 'src/**' https://example.com/design-notes --db k.db \
|
|
6
|
+
* --agent 'claude -p --mcp-config {mcp-config} --allowedTools "mcp__cave__*"'
|
|
7
|
+
* ```
|
|
8
|
+
*
|
|
9
|
+
* Library API for SDK scripts:
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { run } from '@cavelang/cli/ingest'
|
|
13
|
+
* import { open } from '@cavelang/store'
|
|
14
|
+
*
|
|
15
|
+
* const store = open('k.db')
|
|
16
|
+
* await run({
|
|
17
|
+
* db: 'k.db', store, patterns: ['docs/**'], mode: 'stdout', embed: true,
|
|
18
|
+
* agent: async prompt => callYourSdk(prompt), // returns CAVE text
|
|
19
|
+
* // policy: 'lenient' // strict is the default
|
|
20
|
+
* })
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export * as Context from './context.ts';
|
|
24
|
+
export * as Files from './files.ts';
|
|
25
|
+
export * as Web from './web.ts';
|
|
26
|
+
export { buildPrompt, extractionRules, readInstructions } from './prompt.ts';
|
|
27
|
+
export type { Mode, PromptInput } from './prompt.ts';
|
|
28
|
+
export { caveTextOf, promptFor, run, runShellAgent, selectBatches, writeMcpConfig } from './run.ts';
|
|
29
|
+
export type { Agent, AgentContext, Batch, BatchReport, Options, Policy, Report, SourceReport, SourceStatus } from './run.ts';
|
|
30
|
+
export { runIngest } from './main.ts';
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC5E,YAAY,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACnG,YAAY,EACV,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAC7F,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA"}
|