@cavelang/cli 0.34.0 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +225 -13
- package/dist/internal/act/action.js +2 -1
- package/dist/internal/act/action.js.map +1 -1
- package/dist/internal/act/declare.d.ts.map +1 -1
- package/dist/internal/act/declare.js +82 -53
- package/dist/internal/act/declare.js.map +1 -1
- package/dist/internal/act/engine.d.ts +4 -3
- package/dist/internal/act/engine.d.ts.map +1 -1
- package/dist/internal/act/engine.js +121 -32
- package/dist/internal/act/engine.js.map +1 -1
- package/dist/internal/automate/cancellation.d.ts +3 -0
- package/dist/internal/automate/cancellation.d.ts.map +1 -0
- package/dist/internal/automate/cancellation.js +38 -0
- package/dist/internal/automate/cancellation.js.map +1 -0
- package/dist/internal/automate/declare.d.ts.map +1 -1
- package/dist/internal/automate/declare.js +49 -24
- package/dist/internal/automate/declare.js.map +1 -1
- package/dist/internal/automate/engine.d.ts +7 -3
- package/dist/internal/automate/engine.d.ts.map +1 -1
- package/dist/internal/automate/engine.js +196 -93
- package/dist/internal/automate/engine.js.map +1 -1
- package/dist/internal/automate/error-message.d.ts +3 -0
- package/dist/internal/automate/error-message.d.ts.map +1 -0
- package/dist/internal/automate/error-message.js +10 -0
- package/dist/internal/automate/error-message.js.map +1 -0
- package/dist/internal/automate/main.d.ts.map +1 -1
- package/dist/internal/automate/main.js +240 -35
- package/dist/internal/automate/main.js.map +1 -1
- package/dist/internal/automate/options.d.ts +4 -0
- package/dist/internal/automate/options.d.ts.map +1 -0
- package/dist/internal/automate/options.js +19 -0
- package/dist/internal/automate/options.js.map +1 -0
- package/dist/internal/connect/declared.d.ts +204 -0
- package/dist/internal/connect/declared.d.ts.map +1 -0
- package/dist/internal/connect/declared.js +610 -0
- package/dist/internal/connect/declared.js.map +1 -0
- package/dist/internal/connect/error-message.d.ts +3 -0
- package/dist/internal/connect/error-message.d.ts.map +1 -0
- package/dist/internal/connect/error-message.js +10 -0
- package/dist/internal/connect/error-message.js.map +1 -0
- package/dist/internal/connect/federation.d.ts +9 -0
- package/dist/internal/connect/federation.d.ts.map +1 -0
- package/dist/internal/connect/federation.js +19 -0
- package/dist/internal/connect/federation.js.map +1 -0
- package/dist/internal/connect/fetch-failure.d.ts +3 -0
- package/dist/internal/connect/fetch-failure.d.ts.map +1 -0
- package/dist/internal/connect/fetch-failure.js +36 -0
- package/dist/internal/connect/fetch-failure.js.map +1 -0
- package/dist/internal/connect/index.d.ts +4 -2
- package/dist/internal/connect/index.d.ts.map +1 -1
- package/dist/internal/connect/index.js +3 -1
- package/dist/internal/connect/index.js.map +1 -1
- package/dist/internal/connect/main.d.ts +1 -0
- package/dist/internal/connect/main.d.ts.map +1 -1
- package/dist/internal/connect/main.js +575 -59
- package/dist/internal/connect/main.js.map +1 -1
- package/dist/internal/connect/options.d.ts +3 -0
- package/dist/internal/connect/options.d.ts.map +1 -0
- package/dist/internal/connect/options.js +9 -0
- package/dist/internal/connect/options.js.map +1 -0
- package/dist/internal/connect/records.d.ts +3 -0
- package/dist/internal/connect/records.d.ts.map +1 -0
- package/dist/internal/connect/records.js +21 -0
- package/dist/internal/connect/records.js.map +1 -0
- package/dist/internal/connect/run.d.ts +48 -19
- package/dist/internal/connect/run.d.ts.map +1 -1
- package/dist/internal/connect/run.js +185 -77
- package/dist/internal/connect/run.js.map +1 -1
- package/dist/internal/connect/source.d.ts +36 -3
- package/dist/internal/connect/source.d.ts.map +1 -1
- package/dist/internal/connect/source.js +378 -39
- package/dist/internal/connect/source.js.map +1 -1
- package/dist/internal/connect/template.d.ts +20 -2
- package/dist/internal/connect/template.d.ts.map +1 -1
- package/dist/internal/connect/template.js +53 -9
- package/dist/internal/connect/template.js.map +1 -1
- package/dist/internal/connect/utf8.d.ts +3 -0
- package/dist/internal/connect/utf8.d.ts.map +1 -0
- package/dist/internal/connect/utf8.js +12 -0
- package/dist/internal/connect/utf8.js.map +1 -0
- package/dist/internal/eval/cleanup.d.ts +5 -0
- package/dist/internal/eval/cleanup.d.ts.map +1 -0
- package/dist/internal/eval/cleanup.js +50 -0
- package/dist/internal/eval/cleanup.js.map +1 -0
- package/dist/internal/eval/error-message.d.ts +3 -0
- package/dist/internal/eval/error-message.d.ts.map +1 -0
- package/dist/internal/eval/error-message.js +10 -0
- package/dist/internal/eval/error-message.js.map +1 -0
- package/dist/internal/eval/judge.d.ts.map +1 -1
- package/dist/internal/eval/judge.js +3 -31
- package/dist/internal/eval/judge.js.map +1 -1
- package/dist/internal/eval/loop.d.ts.map +1 -1
- package/dist/internal/eval/loop.js +18 -4
- package/dist/internal/eval/loop.js.map +1 -1
- package/dist/internal/eval/main.d.ts.map +1 -1
- package/dist/internal/eval/main.js +22 -10
- package/dist/internal/eval/main.js.map +1 -1
- package/dist/internal/eval/options.d.ts +6 -0
- package/dist/internal/eval/options.d.ts.map +1 -0
- package/dist/internal/eval/options.js +31 -0
- package/dist/internal/eval/options.js.map +1 -0
- package/dist/internal/eval/queries.d.ts.map +1 -1
- package/dist/internal/eval/queries.js +9 -6
- package/dist/internal/eval/queries.js.map +1 -1
- package/dist/internal/eval/run.d.ts.map +1 -1
- package/dist/internal/eval/run.js +112 -24
- package/dist/internal/eval/run.js.map +1 -1
- package/dist/internal/eval/score.d.ts.map +1 -1
- package/dist/internal/eval/score.js +9 -2
- package/dist/internal/eval/score.js.map +1 -1
- package/dist/internal/eval/suite.d.ts.map +1 -1
- package/dist/internal/eval/suite.js +14 -2
- package/dist/internal/eval/suite.js.map +1 -1
- package/dist/internal/ingest/cleanup.d.ts +5 -0
- package/dist/internal/ingest/cleanup.d.ts.map +1 -0
- package/dist/internal/ingest/cleanup.js +50 -0
- package/dist/internal/ingest/cleanup.js.map +1 -0
- package/dist/internal/ingest/content.d.ts +6 -0
- package/dist/internal/ingest/content.d.ts.map +1 -0
- package/dist/internal/ingest/content.js +25 -0
- package/dist/internal/ingest/content.js.map +1 -0
- package/dist/internal/ingest/context.d.ts.map +1 -1
- package/dist/internal/ingest/context.js +25 -7
- package/dist/internal/ingest/context.js.map +1 -1
- package/dist/internal/ingest/error-message.d.ts +3 -0
- package/dist/internal/ingest/error-message.d.ts.map +1 -0
- package/dist/internal/ingest/error-message.js +10 -0
- package/dist/internal/ingest/error-message.js.map +1 -0
- package/dist/internal/ingest/files.d.ts +4 -12
- package/dist/internal/ingest/files.d.ts.map +1 -1
- package/dist/internal/ingest/files.js +22 -10
- package/dist/internal/ingest/files.js.map +1 -1
- package/dist/internal/ingest/main.d.ts.map +1 -1
- package/dist/internal/ingest/main.js +48 -17
- package/dist/internal/ingest/main.js.map +1 -1
- package/dist/internal/ingest/options.d.ts +6 -0
- package/dist/internal/ingest/options.d.ts.map +1 -0
- package/dist/internal/ingest/options.js +27 -0
- package/dist/internal/ingest/options.js.map +1 -0
- package/dist/internal/ingest/prompt.d.ts.map +1 -1
- package/dist/internal/ingest/prompt.js +14 -10
- package/dist/internal/ingest/prompt.js.map +1 -1
- package/dist/internal/ingest/run.d.ts +9 -2
- package/dist/internal/ingest/run.d.ts.map +1 -1
- package/dist/internal/ingest/run.js +206 -62
- package/dist/internal/ingest/run.js.map +1 -1
- package/dist/internal/ingest/timeout.d.ts +3 -0
- package/dist/internal/ingest/timeout.d.ts.map +1 -0
- package/dist/internal/ingest/timeout.js +14 -0
- package/dist/internal/ingest/timeout.js.map +1 -0
- package/dist/internal/ingest/web.d.ts +2 -11
- package/dist/internal/ingest/web.d.ts.map +1 -1
- package/dist/internal/ingest/web.js +131 -25
- package/dist/internal/ingest/web.js.map +1 -1
- package/dist/internal/loop/budgets.d.ts +3 -0
- package/dist/internal/loop/budgets.d.ts.map +1 -0
- package/dist/internal/loop/budgets.js +10 -0
- package/dist/internal/loop/budgets.js.map +1 -0
- package/dist/internal/loop/index.d.ts +2 -0
- package/dist/internal/loop/index.d.ts.map +1 -1
- package/dist/internal/loop/index.js +2 -0
- package/dist/internal/loop/index.js.map +1 -1
- package/dist/internal/loop/json-answer.d.ts +7 -0
- package/dist/internal/loop/json-answer.d.ts.map +1 -0
- package/dist/internal/loop/json-answer.js +79 -0
- package/dist/internal/loop/json-answer.js.map +1 -0
- package/dist/internal/loop/json-spans.d.ts +3 -0
- package/dist/internal/loop/json-spans.d.ts.map +1 -0
- package/dist/internal/loop/json-spans.js +88 -0
- package/dist/internal/loop/json-spans.js.map +1 -0
- package/dist/internal/loop/llm.d.ts +3 -2
- package/dist/internal/loop/llm.d.ts.map +1 -1
- package/dist/internal/loop/llm.js +115 -32
- package/dist/internal/loop/llm.js.map +1 -1
- package/dist/internal/loop/process.d.ts +3 -1
- package/dist/internal/loop/process.d.ts.map +1 -1
- package/dist/internal/loop/process.js +159 -59
- package/dist/internal/loop/process.js.map +1 -1
- package/dist/internal/loop/read-snapshot.d.ts +4 -0
- package/dist/internal/loop/read-snapshot.d.ts.map +1 -0
- package/dist/internal/loop/read-snapshot.js +29 -0
- package/dist/internal/loop/read-snapshot.js.map +1 -0
- package/dist/internal/loop/reconstruct.d.ts +6 -5
- package/dist/internal/loop/reconstruct.d.ts.map +1 -1
- package/dist/internal/loop/reconstruct.js +19 -8
- package/dist/internal/loop/reconstruct.js.map +1 -1
- package/dist/internal/loop/score-settings.d.ts +5 -0
- package/dist/internal/loop/score-settings.d.ts.map +1 -0
- package/dist/internal/loop/score-settings.js +14 -0
- package/dist/internal/loop/score-settings.js.map +1 -0
- package/dist/internal/loop/sqlite.d.ts.map +1 -1
- package/dist/internal/loop/sqlite.js +15 -7
- package/dist/internal/loop/sqlite.js.map +1 -1
- package/dist/internal/loop/store.d.ts.map +1 -1
- package/dist/internal/loop/store.js +11 -7
- package/dist/internal/loop/store.js.map +1 -1
- package/dist/internal/loop/timeout.d.ts +3 -0
- package/dist/internal/loop/timeout.d.ts.map +1 -0
- package/dist/internal/loop/timeout.js +13 -0
- package/dist/internal/loop/timeout.js.map +1 -0
- package/dist/internal/mcp/error-message.d.ts +3 -0
- package/dist/internal/mcp/error-message.d.ts.map +1 -0
- package/dist/internal/mcp/error-message.js +10 -0
- package/dist/internal/mcp/error-message.js.map +1 -0
- package/dist/internal/mcp/main.d.ts.map +1 -1
- package/dist/internal/mcp/main.js +44 -27
- package/dist/internal/mcp/main.js.map +1 -1
- package/dist/internal/mcp/read-snapshot.d.ts +4 -0
- package/dist/internal/mcp/read-snapshot.d.ts.map +1 -0
- package/dist/internal/mcp/read-snapshot.js +22 -0
- package/dist/internal/mcp/read-snapshot.js.map +1 -0
- package/dist/internal/mcp/server.d.ts.map +1 -1
- package/dist/internal/mcp/server.js +181 -21
- package/dist/internal/mcp/server.js.map +1 -1
- package/dist/internal/mcp/source.d.ts +3 -0
- package/dist/internal/mcp/source.d.ts.map +1 -0
- package/dist/internal/mcp/source.js +13 -0
- package/dist/internal/mcp/source.js.map +1 -0
- package/dist/internal/mcp/tools.d.ts.map +1 -1
- package/dist/internal/mcp/tools.js +135 -72
- package/dist/internal/mcp/tools.js.map +1 -1
- package/dist/internal/rules/declarations.d.ts +6 -0
- package/dist/internal/rules/declarations.d.ts.map +1 -0
- package/dist/internal/rules/declarations.js +14 -0
- package/dist/internal/rules/declarations.js.map +1 -0
- package/dist/internal/rules/declare.d.ts.map +1 -1
- package/dist/internal/rules/declare.js +30 -16
- package/dist/internal/rules/declare.js.map +1 -1
- package/dist/internal/rules/engine.d.ts +8 -7
- package/dist/internal/rules/engine.d.ts.map +1 -1
- package/dist/internal/rules/engine.js +150 -44
- package/dist/internal/rules/engine.js.map +1 -1
- package/dist/internal/rules/rule.d.ts.map +1 -1
- package/dist/internal/rules/rule.js +1 -22
- package/dist/internal/rules/rule.js.map +1 -1
- package/dist/internal/shape/alias-root.d.ts +3 -0
- package/dist/internal/shape/alias-root.d.ts.map +1 -0
- package/dist/internal/shape/alias-root.js +13 -0
- package/dist/internal/shape/alias-root.js.map +1 -0
- package/dist/internal/shape/check.d.ts +15 -3
- package/dist/internal/shape/check.d.ts.map +1 -1
- package/dist/internal/shape/check.js +230 -100
- package/dist/internal/shape/check.js.map +1 -1
- package/dist/internal/shape/client.d.ts.map +1 -1
- package/dist/internal/shape/client.js +42 -20
- package/dist/internal/shape/client.js.map +1 -1
- package/dist/internal/shape/constraints.d.ts +8 -0
- package/dist/internal/shape/constraints.d.ts.map +1 -0
- package/dist/internal/shape/constraints.js +17 -0
- package/dist/internal/shape/constraints.js.map +1 -0
- package/dist/internal/shape/edit-distance.d.ts +3 -0
- package/dist/internal/shape/edit-distance.d.ts.map +1 -0
- package/dist/internal/shape/edit-distance.js +33 -0
- package/dist/internal/shape/edit-distance.js.map +1 -0
- package/dist/internal/shape/gate.d.ts.map +1 -1
- package/dist/internal/shape/gate.js +0 -0
- package/dist/internal/shape/gate.js.map +1 -1
- package/dist/internal/shape/snapshot.d.ts +4 -0
- package/dist/internal/shape/snapshot.d.ts.map +1 -0
- package/dist/internal/shape/snapshot.js +20 -0
- package/dist/internal/shape/snapshot.js.map +1 -0
- package/dist/internal/shape/suggest.d.ts +8 -6
- package/dist/internal/shape/suggest.d.ts.map +1 -1
- package/dist/internal/shape/suggest.js +208 -92
- package/dist/internal/shape/suggest.js.map +1 -1
- package/dist/internal/sync/error-message.d.ts +3 -0
- package/dist/internal/sync/error-message.d.ts.map +1 -0
- package/dist/internal/sync/error-message.js +10 -0
- package/dist/internal/sync/error-message.js.map +1 -0
- package/dist/internal/sync/index.d.ts +3 -2
- package/dist/internal/sync/index.d.ts.map +1 -1
- package/dist/internal/sync/index.js +3 -2
- package/dist/internal/sync/index.js.map +1 -1
- package/dist/internal/sync/sync.d.ts +8 -5
- package/dist/internal/sync/sync.d.ts.map +1 -1
- package/dist/internal/sync/sync.js +322 -65
- package/dist/internal/sync/sync.js.map +1 -1
- package/dist/internal/view/api.d.ts +3 -1
- package/dist/internal/view/api.d.ts.map +1 -1
- package/dist/internal/view/api.js +154 -90
- package/dist/internal/view/api.js.map +1 -1
- package/dist/internal/view/error-message.d.ts +3 -0
- package/dist/internal/view/error-message.d.ts.map +1 -0
- package/dist/internal/view/error-message.js +10 -0
- package/dist/internal/view/error-message.js.map +1 -0
- package/dist/internal/view/main.d.ts.map +1 -1
- package/dist/internal/view/main.js +63 -9
- package/dist/internal/view/main.js.map +1 -1
- package/dist/internal/view/page.d.ts.map +1 -1
- package/dist/internal/view/page.js +119 -20
- package/dist/internal/view/page.js.map +1 -1
- package/dist/internal/view/report.d.ts.map +1 -1
- package/dist/internal/view/report.js +180 -145
- package/dist/internal/view/report.js.map +1 -1
- package/dist/internal/view/scope.d.ts +6 -2
- package/dist/internal/view/scope.d.ts.map +1 -1
- package/dist/internal/view/scope.js +107 -24
- package/dist/internal/view/scope.js.map +1 -1
- package/dist/internal/view/sensitivity.d.ts +4 -0
- package/dist/internal/view/sensitivity.d.ts.map +1 -0
- package/dist/internal/view/sensitivity.js +11 -0
- package/dist/internal/view/sensitivity.js.map +1 -0
- package/dist/internal/view/server.d.ts.map +1 -1
- package/dist/internal/view/server.js +57 -20
- package/dist/internal/view/server.js.map +1 -1
- package/dist/src/atomic-output.d.ts +3 -0
- package/dist/src/atomic-output.d.ts.map +1 -0
- package/dist/src/atomic-output.js +67 -0
- package/dist/src/atomic-output.js.map +1 -0
- package/dist/src/cli.d.ts +17 -2
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +333 -195
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands.d.ts +2 -2
- package/dist/src/commands.js +2 -2
- package/dist/src/commands.js.map +1 -1
- package/dist/src/dispatch.d.ts.map +1 -1
- package/dist/src/dispatch.js +10 -3
- package/dist/src/dispatch.js.map +1 -1
- package/dist/src/doctor.d.ts +1 -1
- package/dist/src/doctor.d.ts.map +1 -1
- package/dist/src/doctor.js +192 -91
- package/dist/src/doctor.js.map +1 -1
- package/dist/src/error-message.d.ts +3 -0
- package/dist/src/error-message.d.ts.map +1 -0
- package/dist/src/error-message.js +20 -0
- package/dist/src/error-message.js.map +1 -0
- package/dist/src/hooks-config.d.ts +3 -0
- package/dist/src/hooks-config.d.ts.map +1 -0
- package/dist/src/hooks-config.js +23 -0
- package/dist/src/hooks-config.js.map +1 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/package.json +23 -20
- package/src/atomic-output.ts +47 -0
- package/src/cli.ts +345 -171
- package/src/commands.ts +2 -2
- package/src/dispatch.ts +10 -3
- package/src/doctor.ts +207 -100
- package/src/error-message.ts +13 -0
- package/src/hooks-config.ts +22 -0
- package/src/index.ts +1 -1
|
@@ -11,8 +11,10 @@
|
|
|
11
11
|
* prelude) appends nothing.
|
|
12
12
|
*/
|
|
13
13
|
import { Claim, Key, Value } from '@cavelang/core';
|
|
14
|
+
import { canonicalizeText } from '@cavelang/canonical';
|
|
14
15
|
import { Row } from '@cavelang/store';
|
|
15
16
|
import * as Rule from "./rule.js";
|
|
17
|
+
import { currentDeclarations, declarationText } from "./declarations.js";
|
|
16
18
|
import { provenanceContext, ruleAttribute, ruleSubject } from "./engine.js";
|
|
17
19
|
/** Subject of the prelude digest bookkeeping claim. */
|
|
18
20
|
const preludeSubject = 'derive/prelude';
|
|
@@ -33,6 +35,7 @@ export const declareRules = (store, text) => {
|
|
|
33
35
|
const problems = [];
|
|
34
36
|
const rules = [];
|
|
35
37
|
const preludeLines = [];
|
|
38
|
+
const preludeSourceLines = [];
|
|
36
39
|
const ruleLines = [];
|
|
37
40
|
text.split(/\r?\n/).forEach((line, index) => {
|
|
38
41
|
if (Rule.isRuleLine(line)) {
|
|
@@ -40,17 +43,27 @@ export const declareRules = (store, text) => {
|
|
|
40
43
|
}
|
|
41
44
|
else {
|
|
42
45
|
preludeLines.push(line);
|
|
46
|
+
preludeSourceLines.push(index + 1);
|
|
43
47
|
}
|
|
44
48
|
});
|
|
45
49
|
return store.transaction(() => {
|
|
50
|
+
store.registry();
|
|
46
51
|
let prelude = 0;
|
|
47
52
|
const preludeText = preludeLines.join('\n');
|
|
48
53
|
if (preludeText.trim() !== '') {
|
|
54
|
+
// Validate even cached input: older versions cached failed preludes too.
|
|
55
|
+
const canonical = canonicalizeText(preludeText, store.registry());
|
|
56
|
+
if (canonical.problems.length > 0) {
|
|
57
|
+
for (const problem of canonical.problems)
|
|
58
|
+
problems.push({
|
|
59
|
+
...problem, line: preludeSourceLines[problem.line - 1] ?? problem.line
|
|
60
|
+
});
|
|
61
|
+
return { declared: 0, unchanged: 0, prelude: 0, rules, problems };
|
|
62
|
+
}
|
|
49
63
|
const digest = Rule.digestOf(preludeText);
|
|
50
64
|
const known = store.currentBelief(declarationKey(preludeSubject, preludeDigestAttribute));
|
|
51
65
|
if (known === undefined || known.conf <= 0 || known.value_text !== digest) {
|
|
52
|
-
const result = store.
|
|
53
|
-
problems.push(...result.problems);
|
|
66
|
+
const result = store.insertResult(canonical, { source: 'cave-derive' });
|
|
54
67
|
prelude = result.ids.length;
|
|
55
68
|
store.ingest(`${preludeSubject} HAS ${preludeDigestAttribute}: ${digest} @${provenanceContext}`);
|
|
56
69
|
}
|
|
@@ -60,7 +73,8 @@ export const declareRules = (store, text) => {
|
|
|
60
73
|
for (const { line, at } of ruleLines) {
|
|
61
74
|
const parsed = Rule.parse(line);
|
|
62
75
|
if (!parsed.ok) {
|
|
63
|
-
|
|
76
|
+
for (const message of parsed.problems)
|
|
77
|
+
problems.push({ line: at, message });
|
|
64
78
|
continue;
|
|
65
79
|
}
|
|
66
80
|
const rule = parsed.rule;
|
|
@@ -85,10 +99,10 @@ export const declareRules = (store, text) => {
|
|
|
85
99
|
});
|
|
86
100
|
};
|
|
87
101
|
/** Current positive rules of a store, in declaration order. */
|
|
88
|
-
export const listRules = (store) => store
|
|
89
|
-
.filter(row => row.
|
|
102
|
+
export const listRules = (store) => currentDeclarations(store, ruleAttribute)
|
|
103
|
+
.filter(row => row.value_text !== null)
|
|
90
104
|
.map(row => {
|
|
91
|
-
const text =
|
|
105
|
+
const text = declarationText(row);
|
|
92
106
|
const parsed = Rule.parse(text);
|
|
93
107
|
const label = (parsed.ok ? parsed.rule.label : undefined) ?? row.comment ?? undefined;
|
|
94
108
|
return {
|
|
@@ -105,17 +119,17 @@ export const listRules = (store) => store.currentBeliefs()
|
|
|
105
119
|
* justification does not outlive its rule.
|
|
106
120
|
*/
|
|
107
121
|
export const retractRule = (store, ref) => {
|
|
108
|
-
const declarations = store.currentBeliefs().filter(row => row.verb === 'HAS' && row.attribute === ruleAttribute && row.negated === 0 && row.conf > 0);
|
|
109
|
-
const matches = declarations.filter(row => row.subject === ref || row.subject === ruleSubject(ref) ||
|
|
110
|
-
(ref.length >= 4 && row.subject.startsWith(ruleSubject(ref))));
|
|
111
|
-
const subjects = [...new Set(matches.map(row => row.subject))];
|
|
112
|
-
if (subjects.length === 0) {
|
|
113
|
-
return { ok: false, error: `no current rule matches ${JSON.stringify(ref)}` };
|
|
114
|
-
}
|
|
115
|
-
if (subjects.length > 1) {
|
|
116
|
-
return { ok: false, error: `${JSON.stringify(ref)} is ambiguous — matches ${subjects.join(', ')}` };
|
|
117
|
-
}
|
|
118
122
|
return store.transaction(() => {
|
|
123
|
+
const declarations = currentDeclarations(store, ruleAttribute);
|
|
124
|
+
const matches = declarations.filter(row => row.subject === ref || row.subject === ruleSubject(ref) ||
|
|
125
|
+
(ref.length >= 4 && row.subject.startsWith(ruleSubject(ref))));
|
|
126
|
+
const subjects = [...new Set(matches.map(row => row.subject))];
|
|
127
|
+
if (subjects.length === 0) {
|
|
128
|
+
return { ok: false, error: `no current rule matches ${JSON.stringify(ref)}` };
|
|
129
|
+
}
|
|
130
|
+
if (subjects.length > 1) {
|
|
131
|
+
return { ok: false, error: `${JSON.stringify(ref)} is ambiguous — matches ${subjects.join(', ')}` };
|
|
132
|
+
}
|
|
119
133
|
let derived = 0;
|
|
120
134
|
for (const declaration of matches) {
|
|
121
135
|
store.insertResult({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"declare.js","sourceRoot":"","sources":["../../src/declare.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,EAAE,GAAG,EAAc,MAAM,iBAAiB,CAAA;AACjD,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE3E,uDAAuD;AACvD,MAAM,cAAc,GAAG,gBAAgB,CAAA;AAEvC,MAAM,sBAAsB,GAAG,eAAe,CAAA;AAE9C,MAAM,mBAAmB,GAAG,CAAC,iBAAiB,CAAC,CAAA;AAE/C,MAAM,cAAc,GAAG,CAAC,OAAe,EAAE,SAAiB,EAAU,EAAE,CACpE,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;IACd,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC;IAC9B,IAAI,EAAE,KAAK;IACX,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACrD,QAAQ,EAAE,mBAAmB;CAC9B,CAAC,CAAC,CAAA;AAaL;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAY,EAAE,IAAY,EAAe,EAAE;IACtE,MAAM,QAAQ,GAAwC,EAAE,CAAA;IACxD,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,MAAM,YAAY,GAAa,EAAE,CAAA;IACjC,MAAM,SAAS,GAAmC,EAAE,CAAA;IACpD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC1C,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,CAAA;QACzC,CAAC;aAAM,CAAC;YACN,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"declare.js","sourceRoot":"","sources":["../../src/declare.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
* declaration row (§24.3);
|
|
23
23
|
* - re-runs are idempotent — a conclusion equal to current belief appends
|
|
24
24
|
* nothing — and incremental by per-rule tx watermark claims: a rule
|
|
25
|
-
* re-fires
|
|
26
|
-
*
|
|
25
|
+
* re-fires when newer rows could change a premise match or the active
|
|
26
|
+
* vocabulary/evaluation-policy fingerprint differs. A watermark predating the rule's current
|
|
27
27
|
* declaration row is stale — a re-declared rule fires from scratch
|
|
28
28
|
* (§24.4);
|
|
29
29
|
* - support is recomputed on every firing: previously-derived claims the
|
|
@@ -67,16 +67,17 @@ export type RuleOutcome = {
|
|
|
67
67
|
readonly label?: string;
|
|
68
68
|
/** `false` when every pass skipped the rule — watermark said nothing new. */
|
|
69
69
|
fired: boolean;
|
|
70
|
+
/** Attempted evaluations, including evaluations in rolled-back reconciliation. */
|
|
70
71
|
evaluations: number;
|
|
71
|
-
/** Solutions of the rule's final evaluation. */
|
|
72
|
+
/** Solutions of the rule's final attempted evaluation. */
|
|
72
73
|
solutions: number;
|
|
73
|
-
/**
|
|
74
|
+
/** Retained first assertions (or re-assertions); excludes rolled-back reconciliation. */
|
|
74
75
|
appended: number;
|
|
75
|
-
/**
|
|
76
|
+
/** Retained confidence/value updates; excludes rolled-back reconciliation. */
|
|
76
77
|
updated: number;
|
|
77
|
-
/**
|
|
78
|
+
/** Attempted idempotent skips, including during rolled-back reconciliation (§24.4). */
|
|
78
79
|
unchanged: number;
|
|
79
|
-
/**
|
|
80
|
+
/** Retained retractions for lost support; excludes rolled-back reconciliation (§24.5). */
|
|
80
81
|
retracted: number;
|
|
81
82
|
readonly problems: string[];
|
|
82
83
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
* declaration row (§24.3);
|
|
23
23
|
* - re-runs are idempotent — a conclusion equal to current belief appends
|
|
24
24
|
* nothing — and incremental by per-rule tx watermark claims: a rule
|
|
25
|
-
* re-fires
|
|
26
|
-
*
|
|
25
|
+
* re-fires when newer rows could change a premise match or the active
|
|
26
|
+
* vocabulary/evaluation-policy fingerprint differs. A watermark predating the rule's current
|
|
27
27
|
* declaration row is stale — a re-declared rule fires from scratch
|
|
28
28
|
* (§24.4);
|
|
29
29
|
* - support is recomputed on every firing: previously-derived claims the
|
|
@@ -33,16 +33,19 @@
|
|
|
33
33
|
* retracts the whole dependent chain, mutually-supporting cycles
|
|
34
34
|
* included (§24.5).
|
|
35
35
|
*/
|
|
36
|
-
import {
|
|
36
|
+
import { createHash } from 'node:crypto';
|
|
37
|
+
import { Claim, Context, Key, Value, Verb } from '@cavelang/core';
|
|
37
38
|
import * as Canonical from '@cavelang/canonical';
|
|
38
39
|
import { noisyAndIndependent } from '@cavelang/fusion';
|
|
39
40
|
import { Row } from '@cavelang/store';
|
|
40
41
|
import { match } from '@cavelang/query';
|
|
41
42
|
import * as Rule from "./rule.js";
|
|
43
|
+
import { currentDeclarations, declarationText } from "./declarations.js";
|
|
42
44
|
/** Attribute of rule declaration claims: `rule/<digest> HAS rule: …`. */
|
|
43
45
|
export const ruleAttribute = 'rule';
|
|
44
46
|
/** Attribute of per-rule watermark claims (§24.4). */
|
|
45
47
|
export const watermarkAttribute = 'derive-watermark';
|
|
48
|
+
const vocabularyAttribute = 'derive-vocabulary';
|
|
46
49
|
/** Source context stamped on declarations and bookkeeping (like `src:cave-connect`). */
|
|
47
50
|
export const provenanceContext = 'src:cave-derive';
|
|
48
51
|
/** Declaration subject of a rule: its digest under the `rule/` scope. */
|
|
@@ -64,6 +67,21 @@ const bookkeepingKey = (subject, attribute) => Key.of(Claim.of({
|
|
|
64
67
|
contexts: [provenanceContext]
|
|
65
68
|
}));
|
|
66
69
|
const maxTx = (store) => store.db.prepare('SELECT MAX(tx) AS t FROM cave_claim').get().t ?? undefined;
|
|
70
|
+
// Registry values are immutable. Cache per identity, but hash sorted semantic
|
|
71
|
+
// contents so reopening or replaying an equivalent registry retains the mark.
|
|
72
|
+
const vocabularyCache = new WeakMap();
|
|
73
|
+
const vocabularyOf = (store) => {
|
|
74
|
+
const registry = store.registry();
|
|
75
|
+
const cached = vocabularyCache.get(registry);
|
|
76
|
+
if (cached !== undefined)
|
|
77
|
+
return cached;
|
|
78
|
+
const pairs = [...registry.pairs].map(([name, pair]) => [name, pair.primary, pair.inverse]).sort();
|
|
79
|
+
const text = JSON.stringify([pairs, [...registry.declared].sort(),
|
|
80
|
+
[...registry.storage].sort(), [...registry.preferred].sort(), [...registry.renames].sort()]);
|
|
81
|
+
const fingerprint = `v1-${createHash('sha256').update(text).digest('hex')}`;
|
|
82
|
+
vocabularyCache.set(registry, fingerprint);
|
|
83
|
+
return fingerprint;
|
|
84
|
+
};
|
|
67
85
|
/** Latest row per claim key among `rows` — the series current beliefs. */
|
|
68
86
|
const latestPerKey = (rows) => {
|
|
69
87
|
const latest = new Map();
|
|
@@ -93,9 +111,9 @@ const loadRules = (store) => {
|
|
|
93
111
|
const problems = [];
|
|
94
112
|
const notes = [];
|
|
95
113
|
const byDigest = new Map();
|
|
96
|
-
const declarations = store
|
|
114
|
+
const declarations = currentDeclarations(store, ruleAttribute).filter(row => row.value_text !== null);
|
|
97
115
|
for (const row of declarations) {
|
|
98
|
-
const text =
|
|
116
|
+
const text = declarationText(row);
|
|
99
117
|
const parsed = Rule.parse(text);
|
|
100
118
|
if (!parsed.ok) {
|
|
101
119
|
problems.push({ subject: row.subject, problems: parsed.problems });
|
|
@@ -132,7 +150,7 @@ const loadRules = (store) => {
|
|
|
132
150
|
/**
|
|
133
151
|
* Could a row recorded after `mark` extend a match of one of the rule's
|
|
134
152
|
* premises? A *shape* test — subject/verb/object/attribute/negated plus
|
|
135
|
-
* context
|
|
153
|
+
* context membership; mutable values, tags and confidence are ignored, so a
|
|
136
154
|
* retraction row re-fires the rules its claim used to feed (§24.5).
|
|
137
155
|
* Over-matching costs a harmless re-evaluation; under-matching would be a
|
|
138
156
|
* correctness bug — under `aliases`, entity terms are dropped from the
|
|
@@ -140,6 +158,12 @@ const loadRules = (store) => {
|
|
|
140
158
|
* fires too.
|
|
141
159
|
*/
|
|
142
160
|
const shapeMatchesSince = (store, rule, mark, aliases) => {
|
|
161
|
+
// A new mapping can make old facts match a different premise direction.
|
|
162
|
+
// Their fact timestamps do not move, so ordinary shape probes miss it.
|
|
163
|
+
if (store.db.prepare(`SELECT 1 FROM cave_claim
|
|
164
|
+
WHERE tx > ? AND (verb IN ('REVERSE', 'RENAMED-TO') OR (verb = 'IS' AND object = 'verb'))
|
|
165
|
+
LIMIT 1`).get(mark) !== undefined)
|
|
166
|
+
return true;
|
|
143
167
|
const registry = store.registry();
|
|
144
168
|
for (const premise of rule.premises) {
|
|
145
169
|
if (premise.kind !== 'pattern') {
|
|
@@ -178,33 +202,32 @@ const shapeMatchesSince = (store, rule, mark, aliases) => {
|
|
|
178
202
|
params.push(subjectSlot.text);
|
|
179
203
|
}
|
|
180
204
|
if (objectSlot?.kind === 'term' && !aliases) {
|
|
181
|
-
//
|
|
182
|
-
|
|
183
|
-
|
|
205
|
+
// Metric values share a claim key across changes. A replacement that
|
|
206
|
+
// stops matching must still wake the rule to retract its conclusions.
|
|
207
|
+
conditions.push('(c.object = ? OR c.object IS NULL)');
|
|
208
|
+
params.push(objectSlot.text);
|
|
184
209
|
}
|
|
185
210
|
if (premise.pattern.payload.kind === 'attribute') {
|
|
186
211
|
conditions.push('c.attribute = ?');
|
|
187
212
|
params.push(premise.pattern.payload.attribute);
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
params.push(premise.pattern.payload.value.text);
|
|
191
|
-
}
|
|
213
|
+
// Attribute values are mutable within a series. Do not restrict the
|
|
214
|
+
// wake-up probe to either their spelling or their normalized value.
|
|
192
215
|
}
|
|
193
216
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
for (const tag of premise.pattern.tags) {
|
|
199
|
-
if (tag.value === undefined) {
|
|
200
|
-
conditions.push('EXISTS (SELECT 1 FROM cave_tag t WHERE t.claim_id = c.id AND t.key = ? AND t.value IS NULL)');
|
|
201
|
-
params.push(tag.key);
|
|
202
|
-
}
|
|
203
|
-
else {
|
|
204
|
-
conditions.push('EXISTS (SELECT 1 FROM cave_tag t WHERE t.claim_id = c.id AND t.key = ? AND t.value = ?)');
|
|
205
|
-
params.push(tag.key, tag.value);
|
|
217
|
+
if (premise.pattern.contexts.length <= 16) {
|
|
218
|
+
for (const context of premise.pattern.contexts) {
|
|
219
|
+
conditions.push('EXISTS (SELECT 1 FROM cave_context x WHERE x.claim_id = c.id AND x.context = ?)');
|
|
220
|
+
params.push(context);
|
|
206
221
|
}
|
|
207
222
|
}
|
|
223
|
+
else {
|
|
224
|
+
conditions.push(`NOT EXISTS (SELECT 1 FROM json_each(?) required
|
|
225
|
+
WHERE NOT EXISTS (SELECT 1 FROM cave_context x
|
|
226
|
+
WHERE x.claim_id = c.id AND x.context = required.value))`);
|
|
227
|
+
params.push(JSON.stringify(premise.pattern.contexts));
|
|
228
|
+
}
|
|
229
|
+
// Tags are metadata, not identity: removing a required tag can invalidate
|
|
230
|
+
// prior conclusions just as adding it can enable a new match.
|
|
208
231
|
const row = store.db.prepare(`SELECT 1 AS hit FROM cave_claim c WHERE ${conditions.join(' AND ')} LIMIT 1`)
|
|
209
232
|
.get(...params);
|
|
210
233
|
if (row !== undefined) {
|
|
@@ -228,11 +251,11 @@ const shapeMatchesSince = (store, rule, mark, aliases) => {
|
|
|
228
251
|
* no row can match.
|
|
229
252
|
*/
|
|
230
253
|
export const specialize = (pattern, bindings) => {
|
|
231
|
-
const slot = (candidate) => candidate.kind === 'var' && bindings[candidate.name] !== undefined ?
|
|
254
|
+
const slot = (candidate) => candidate.kind === 'var' && Object.hasOwn(bindings, candidate.name) && bindings[candidate.name] !== undefined ?
|
|
232
255
|
{ kind: 'term', text: bindings[candidate.name] } :
|
|
233
256
|
candidate;
|
|
234
257
|
let verb = pattern.verb;
|
|
235
|
-
if (verb.kind === 'var' && bindings[verb.name] !== undefined) {
|
|
258
|
+
if (verb.kind === 'var' && Object.hasOwn(bindings, verb.name) && bindings[verb.name] !== undefined) {
|
|
236
259
|
const name = bindings[verb.name];
|
|
237
260
|
if (!Verb.isVerbToken(name)) {
|
|
238
261
|
return undefined;
|
|
@@ -318,7 +341,7 @@ const conclude = (rule, solution, registry) => {
|
|
|
318
341
|
else if (payload.kind === 'metric' && payload.value.kind === 'atom' && payload.value.raw.startsWith('?')) {
|
|
319
342
|
payload = Claim.metric(Row.parseValue(solution.bindings[payload.value.raw.slice(1)]));
|
|
320
343
|
}
|
|
321
|
-
const conf =
|
|
344
|
+
const conf = noisyAndIndependent(rule.conf, solution.rows.map(row => row.conf));
|
|
322
345
|
const draft = Claim.of({
|
|
323
346
|
subject: term(template.subject, 'subject'),
|
|
324
347
|
verb: template.verb,
|
|
@@ -352,9 +375,37 @@ const rollback = Symbol('cave-derive dry run');
|
|
|
352
375
|
* transaction.
|
|
353
376
|
*/
|
|
354
377
|
export const derive = (store, options = {}) => {
|
|
378
|
+
const suppliedMinConf = options.minConf;
|
|
379
|
+
const minConf = suppliedMinConf === undefined ? defaultMinConf : suppliedMinConf;
|
|
380
|
+
if (!Number.isFinite(minConf) || minConf < 0 || minConf > 1) {
|
|
381
|
+
throw new Error('minConf must be finite and in 0..1');
|
|
382
|
+
}
|
|
383
|
+
const suppliedMaxPasses = options.maxPasses;
|
|
384
|
+
const maxPasses = suppliedMaxPasses === undefined ? defaultMaxPasses : suppliedMaxPasses;
|
|
385
|
+
if (!Number.isSafeInteger(maxPasses) || maxPasses < 1) {
|
|
386
|
+
throw new Error('maxPasses must be a positive safe integer');
|
|
387
|
+
}
|
|
388
|
+
options = { minConf, maxPasses, full: options.full, dryRun: options.dryRun, aliases: options.aliases };
|
|
389
|
+
for (const key of ['full', 'dryRun', 'aliases']) {
|
|
390
|
+
if (options[key] !== undefined && typeof options[key] !== 'boolean') {
|
|
391
|
+
throw new Error(`${key} must be a boolean`);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
return store.transaction(() => {
|
|
395
|
+
store.registry();
|
|
396
|
+
return deriveLocked(store, options);
|
|
397
|
+
});
|
|
398
|
+
};
|
|
399
|
+
/** Read declarations and watermarks only after reserving the write transaction. */
|
|
400
|
+
const deriveLocked = (store, options) => {
|
|
355
401
|
const minConf = options.minConf ?? defaultMinConf;
|
|
356
402
|
const maxPasses = options.maxPasses ?? defaultMaxPasses;
|
|
357
403
|
const aliases = options.aliases === true;
|
|
404
|
+
// The persisted vocabulary companion also identifies the evaluation policy:
|
|
405
|
+
// unchanged rows can gain or lose support when these options change.
|
|
406
|
+
// v3 re-evaluates conclusions formerly rounded to two percentage decimals.
|
|
407
|
+
const evaluationFingerprint = () => 'v3-' + createHash('sha256')
|
|
408
|
+
.update(JSON.stringify([vocabularyOf(store), aliases, minConf])).digest('hex');
|
|
358
409
|
const { loaded, problems, notes } = loadRules(store);
|
|
359
410
|
let passes = 0;
|
|
360
411
|
const supported = new Set();
|
|
@@ -364,6 +415,8 @@ export const derive = (store, options = {}) => {
|
|
|
364
415
|
/** Per-rule scan mark: rows at or before it are fully accounted for. */
|
|
365
416
|
const marks = new Map();
|
|
366
417
|
const storedMarks = new Map();
|
|
418
|
+
const vocabularies = new Map();
|
|
419
|
+
const storedVocabularies = new Map();
|
|
367
420
|
let complete = true;
|
|
368
421
|
for (const { rule, row } of loaded) {
|
|
369
422
|
const watermark = store.currentBelief(bookkeepingKey(ruleSubject(rule.digest), watermarkAttribute));
|
|
@@ -376,6 +429,11 @@ export const derive = (store, options = {}) => {
|
|
|
376
429
|
const stored = watermark !== undefined && watermark.conf > 0 && watermark.tx > row.tx ?
|
|
377
430
|
watermark.value_text ?? undefined :
|
|
378
431
|
undefined;
|
|
432
|
+
const vocabulary = store.currentBelief(bookkeepingKey(ruleSubject(rule.digest), vocabularyAttribute));
|
|
433
|
+
const storedVocabulary = vocabulary !== undefined && vocabulary.conf > 0 && vocabulary.tx > row.tx
|
|
434
|
+
? vocabulary.value_text ?? undefined : undefined;
|
|
435
|
+
storedVocabularies.set(rule.digest, storedVocabulary);
|
|
436
|
+
vocabularies.set(rule.digest, storedVocabulary);
|
|
379
437
|
storedMarks.set(rule.digest, stored);
|
|
380
438
|
marks.set(rule.digest, options.full === true ? undefined : stored);
|
|
381
439
|
}
|
|
@@ -440,18 +498,17 @@ export const derive = (store, options = {}) => {
|
|
|
440
498
|
}
|
|
441
499
|
const current = store.currentBelief(conclusion.key);
|
|
442
500
|
const columns = Row.toColumns(conclusion.claim);
|
|
443
|
-
if (current !== undefined && current.conf
|
|
444
|
-
Math.abs(current.conf - conclusion.conf) < 1e-9 && current.value_text === columns.valueText) {
|
|
501
|
+
if (current !== undefined && current.conf === conclusion.conf && current.value_text === columns.valueText) {
|
|
445
502
|
outcome.unchanged += 1;
|
|
446
503
|
continue;
|
|
447
504
|
}
|
|
448
|
-
const
|
|
449
|
-
//
|
|
450
|
-
//
|
|
451
|
-
//
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
}
|
|
505
|
+
const registry = store.registry();
|
|
506
|
+
// Extend the current registry, not the snapshot used to construct a
|
|
507
|
+
// batch of conclusions. Canonicalization preserves first-declaration-
|
|
508
|
+
// wins behavior for competing declarations from that batch.
|
|
509
|
+
const nextRegistry = isDeclarationClaim(conclusion.claim) ?
|
|
510
|
+
Canonical.canonicalizeText(Canonical.emitClaim(conclusion.claim), registry).registry : registry;
|
|
511
|
+
const inserted = store.insertResult({ claims: [{ claim: conclusion.claim, line: 0 }], edges: [], registry: nextRegistry, problems: [] }, { source: ruleSubject(rule.digest), lifecycle: true });
|
|
455
512
|
const id = inserted.ids[0];
|
|
456
513
|
const premiseIds = [...new Set(conclusion.rows.map(premiseRow => premiseRow.id))];
|
|
457
514
|
store.appendEdges([
|
|
@@ -468,23 +525,30 @@ export const derive = (store, options = {}) => {
|
|
|
468
525
|
}
|
|
469
526
|
return progress;
|
|
470
527
|
};
|
|
471
|
-
|
|
528
|
+
let reconciling = false;
|
|
529
|
+
const incompleteReconciliation = Symbol('cave-derive incomplete reconciliation');
|
|
530
|
+
const run = (resumeRetraction = false) => {
|
|
472
531
|
const truncate = () => {
|
|
473
532
|
complete = false;
|
|
474
533
|
notes.push(`stopped at ${maxPasses} passes before reaching a fixpoint — no unsupported conclusions were retracted and no watermarks were advanced; re-run to continue, or raise maxPasses`);
|
|
475
534
|
};
|
|
476
535
|
for (;;) {
|
|
477
536
|
// Pass loop: evaluate until no rule writes or extends support.
|
|
478
|
-
|
|
537
|
+
// The single recursive entry resumes at the first retraction under a
|
|
538
|
+
// savepoint; it must not repeat evaluation or charge an extra pass.
|
|
539
|
+
let quiescent = resumeRetraction;
|
|
540
|
+
resumeRetraction = false;
|
|
479
541
|
while (!quiescent && passes < maxPasses) {
|
|
480
542
|
passes += 1;
|
|
481
543
|
let progress = false;
|
|
482
544
|
for (const entry of loaded) {
|
|
483
545
|
const mark = marks.get(entry.rule.digest);
|
|
484
|
-
const
|
|
485
|
-
if (mark !== undefined &&
|
|
546
|
+
const vocabulary = evaluationFingerprint();
|
|
547
|
+
if (mark !== undefined && vocabularies.get(entry.rule.digest) === vocabulary &&
|
|
548
|
+
!shapeMatchesSince(store, entry.rule, mark, aliases)) {
|
|
486
549
|
continue;
|
|
487
550
|
}
|
|
551
|
+
const now = maxTx(store);
|
|
488
552
|
if (!fired.has(entry.rule.digest)) {
|
|
489
553
|
fired.add(entry.rule.digest);
|
|
490
554
|
entry.outcome.fired = true;
|
|
@@ -494,6 +558,19 @@ export const derive = (store, options = {}) => {
|
|
|
494
558
|
progress = true;
|
|
495
559
|
}
|
|
496
560
|
marks.set(entry.rule.digest, now);
|
|
561
|
+
vocabularies.set(entry.rule.digest, vocabulary);
|
|
562
|
+
if (evaluationFingerprint() !== vocabulary) {
|
|
563
|
+
// A proof established under the old mapping is no longer valid.
|
|
564
|
+
// Re-suspend all current derivations on the next bounded pass,
|
|
565
|
+
// including conclusions written earlier in this invocation.
|
|
566
|
+
supported.clear();
|
|
567
|
+
suspended.clear();
|
|
568
|
+
fired.clear();
|
|
569
|
+
marks.clear();
|
|
570
|
+
vocabularies.clear();
|
|
571
|
+
progress = true;
|
|
572
|
+
break;
|
|
573
|
+
}
|
|
497
574
|
}
|
|
498
575
|
quiescent = !progress;
|
|
499
576
|
}
|
|
@@ -504,6 +581,32 @@ export const derive = (store, options = {}) => {
|
|
|
504
581
|
truncate();
|
|
505
582
|
return;
|
|
506
583
|
}
|
|
584
|
+
if (!reconciling) {
|
|
585
|
+
if (![...suspended.values()].some(({ row }) => !supported.has(row.claim_key)))
|
|
586
|
+
return;
|
|
587
|
+
// Keep additions from initial evaluation, but commit destructive support
|
|
588
|
+
// reconciliation only if all subsequent evaluation/retraction settles.
|
|
589
|
+
// The recursive call enters this savepoint once, regardless of depth
|
|
590
|
+
// of the dependency chain; subsequent passes use the ordinary loop.
|
|
591
|
+
const counts = loaded.map(({ outcome }) => ({
|
|
592
|
+
appended: outcome.appended, updated: outcome.updated, retracted: outcome.retracted
|
|
593
|
+
}));
|
|
594
|
+
reconciling = true;
|
|
595
|
+
try {
|
|
596
|
+
store.transaction(() => {
|
|
597
|
+
run(true);
|
|
598
|
+
if (!complete)
|
|
599
|
+
throw incompleteReconciliation;
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
catch (error) {
|
|
603
|
+
if (error !== incompleteReconciliation)
|
|
604
|
+
throw error;
|
|
605
|
+
for (let i = 0; i < loaded.length; i++)
|
|
606
|
+
Object.assign(loaded[i].outcome, counts[i]);
|
|
607
|
+
}
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
507
610
|
// Retraction phase (§24.5): suspended rows never re-supported lost
|
|
508
611
|
// their premises. Retraction rows are ordinary appends — the loop
|
|
509
612
|
// re-enters so dependent rules see them and cascade.
|
|
@@ -534,10 +637,13 @@ export const derive = (store, options = {}) => {
|
|
|
534
637
|
continue;
|
|
535
638
|
}
|
|
536
639
|
const mark = marks.get(entry.rule.digest);
|
|
537
|
-
if (mark
|
|
538
|
-
|
|
640
|
+
if (mark !== undefined && mark !== storedMarks.get(entry.rule.digest)) {
|
|
641
|
+
store.ingest(`${ruleSubject(entry.rule.digest)} HAS ${watermarkAttribute}: ${mark} @${provenanceContext}`);
|
|
642
|
+
}
|
|
643
|
+
const vocabulary = vocabularies.get(entry.rule.digest);
|
|
644
|
+
if (vocabulary !== undefined && vocabulary !== storedVocabularies.get(entry.rule.digest)) {
|
|
645
|
+
store.ingest(`${ruleSubject(entry.rule.digest)} HAS ${vocabularyAttribute}: ${vocabulary} @${provenanceContext}`);
|
|
539
646
|
}
|
|
540
|
-
store.ingest(`${ruleSubject(entry.rule.digest)} HAS ${watermarkAttribute}: ${mark} @${provenanceContext}`);
|
|
541
647
|
}
|
|
542
648
|
};
|
|
543
649
|
if (options.dryRun === true) {
|