@tangle-network/agent-knowledge 11.0.0 → 12.0.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/AGENTS.md +7 -0
- package/CHANGELOG.md +50 -0
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +126 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{inspect-yYqLQuM4.js → inspect-BUp9GUKO.js} +266 -89
- package/dist/inspect-BUp9GUKO.js.map +1 -0
- package/package.json +1 -1
- package/dist/inspect-yYqLQuM4.js.map +0 -1
|
@@ -797,16 +797,19 @@ var KnowledgeLockLostError = class extends Error {
|
|
|
797
797
|
this.name = "KnowledgeLockLostError";
|
|
798
798
|
}
|
|
799
799
|
};
|
|
800
|
+
/**
|
|
801
|
+
* Whether the current async context already holds the store lock for `root`.
|
|
802
|
+
*
|
|
803
|
+
* A caller that must decide between taking the lock and joining the one it is inside reads this
|
|
804
|
+
* rather than guessing; taking a held lock from inside its own scope would block against itself.
|
|
805
|
+
*/
|
|
806
|
+
function isKnowledgeMutationHeld(root) {
|
|
807
|
+
return activeRoots.getStore()?.get(resolve(root))?.active === true;
|
|
808
|
+
}
|
|
800
809
|
async function withKnowledgeMutation(root, mutate, options = {}) {
|
|
801
810
|
const resolvedRoot = resolve(root);
|
|
802
|
-
const
|
|
803
|
-
|
|
804
|
-
if (existing?.active) {
|
|
805
|
-
existing.lock.assertOwned();
|
|
806
|
-
const result = await mutate(existing.lock);
|
|
807
|
-
existing.lock.assertOwned();
|
|
808
|
-
return result;
|
|
809
|
-
}
|
|
811
|
+
const existing = activeRoots.getStore()?.get(resolvedRoot);
|
|
812
|
+
if (existing?.active) return await runInlineMutation(existing.lock, mutate);
|
|
810
813
|
return withSafeDirectory(resolvedRoot, ".agent-knowledge", true, async (cacheDir) => {
|
|
811
814
|
const acquired = await acquireDurableFileLock(resolvedRoot, {
|
|
812
815
|
lockfilePath: join(cacheDir, "mutation.lock.durable"),
|
|
@@ -819,77 +822,110 @@ async function withKnowledgeMutation(root, mutate, options = {}) {
|
|
|
819
822
|
randomize: true
|
|
820
823
|
}
|
|
821
824
|
});
|
|
822
|
-
let recovery;
|
|
823
|
-
const mutationLock = {
|
|
824
|
-
transactionRoot: join(cacheDir, "file-transactions"),
|
|
825
|
-
get recovery() {
|
|
826
|
-
return recovery;
|
|
827
|
-
},
|
|
828
|
-
assertOwned: acquired.assertOwned
|
|
829
|
-
};
|
|
830
|
-
const scope = {
|
|
831
|
-
active: true,
|
|
832
|
-
lock: mutationLock
|
|
833
|
-
};
|
|
834
825
|
try {
|
|
835
|
-
|
|
836
|
-
root: resolvedRoot,
|
|
837
|
-
transactionRoot: mutationLock.transactionRoot
|
|
838
|
-
});
|
|
839
|
-
const pending = pendingState?.transaction ?? null;
|
|
840
|
-
const resume = pending ? assertKnowledgeTransactionResume(pending, options.resumeTransaction) : void 0;
|
|
841
|
-
const locks = new Map(active);
|
|
842
|
-
locks.set(resolvedRoot, scope);
|
|
843
|
-
return await activeRoots.run(locks, async () => {
|
|
844
|
-
const epoch = await beginMutationEpoch(cacheDir);
|
|
845
|
-
const finishEpoch = async (completed) => {
|
|
846
|
-
mutationLock.assertOwned();
|
|
847
|
-
const stillPending = await loadKnowledgeFileTransaction({
|
|
848
|
-
root: resolvedRoot,
|
|
849
|
-
transactionRoot: mutationLock.transactionRoot
|
|
850
|
-
});
|
|
851
|
-
if (completed && stillPending) throw new Error("knowledge mutation returned with an unfinished transaction");
|
|
852
|
-
if (!stillPending) await finishMutationEpoch(cacheDir, epoch);
|
|
853
|
-
};
|
|
854
|
-
try {
|
|
855
|
-
if (pending) {
|
|
856
|
-
if (!resume) throw new Error(`knowledge transaction '${pending.purpose}' requires its owner to resume`);
|
|
857
|
-
await recoverKnowledgeFileTransaction({
|
|
858
|
-
root: resolvedRoot,
|
|
859
|
-
transactionRoot: mutationLock.transactionRoot,
|
|
860
|
-
expectedPurpose: resume.purpose,
|
|
861
|
-
direction: resume.direction,
|
|
862
|
-
finish: resume.deferFinish !== true,
|
|
863
|
-
validate: resume.validate,
|
|
864
|
-
assertOwned: acquired.assertOwned
|
|
865
|
-
});
|
|
866
|
-
recovery = Object.freeze({
|
|
867
|
-
transactionId: pending.transactionId,
|
|
868
|
-
purpose: pending.purpose,
|
|
869
|
-
direction: resume.direction ?? pendingState?.direction ?? "apply",
|
|
870
|
-
transaction: pending
|
|
871
|
-
});
|
|
872
|
-
}
|
|
873
|
-
mutationLock.assertOwned();
|
|
874
|
-
const result = await mutate(mutationLock);
|
|
875
|
-
mutationLock.assertOwned();
|
|
876
|
-
await finishEpoch(true);
|
|
877
|
-
return result;
|
|
878
|
-
} catch (error) {
|
|
879
|
-
try {
|
|
880
|
-
await finishEpoch(false);
|
|
881
|
-
} catch (finishError) {
|
|
882
|
-
throw new AggregateError([error, finishError], "knowledge mutation failed and its durable state could not be inspected");
|
|
883
|
-
}
|
|
884
|
-
throw error;
|
|
885
|
-
}
|
|
886
|
-
});
|
|
826
|
+
return await runOwnedMutation(resolvedRoot, cacheDir, acquired, options, mutate);
|
|
887
827
|
} finally {
|
|
888
|
-
scope.active = false;
|
|
889
828
|
await acquired.release();
|
|
890
829
|
}
|
|
891
830
|
});
|
|
892
831
|
}
|
|
832
|
+
/**
|
|
833
|
+
* Run `body` inside this package's mutation scope for `root`, on a lock the caller already holds.
|
|
834
|
+
*
|
|
835
|
+
* The caller owns acquiring and releasing that lock; this package owns the scope, the file
|
|
836
|
+
* transaction it opens, and the epoch a concurrent reader watches. Inside `body`, every
|
|
837
|
+
* lock-taking function in this package sees the root as held and runs inline, which is what makes
|
|
838
|
+
* a consumer's own read-modify-write composable with this package instead of exclusive of it.
|
|
839
|
+
*
|
|
840
|
+
* The hold is asked `assertOwned()` at the same points a lock this package acquired is asked, so
|
|
841
|
+
* an externally held lock carries the same guarantee and not a weaker one. Entering a scope for a
|
|
842
|
+
* lock the caller does not actually hold is the one way to defeat the store's single-writer rule;
|
|
843
|
+
* the hold is required, rather than assumed, so that is a statement the caller has to make.
|
|
844
|
+
*/
|
|
845
|
+
async function runInKnowledgeMutationScope(root, hold, body, options = {}) {
|
|
846
|
+
const resolvedRoot = resolve(root);
|
|
847
|
+
const existing = activeRoots.getStore()?.get(resolvedRoot);
|
|
848
|
+
if (existing?.active) return await runInlineMutation(existing.lock, body);
|
|
849
|
+
return withSafeDirectory(resolvedRoot, ".agent-knowledge", true, (cacheDir) => runOwnedMutation(resolvedRoot, cacheDir, hold, options, body));
|
|
850
|
+
}
|
|
851
|
+
/** The reentrant path: the root is already held in this async context, so no lock is taken. */
|
|
852
|
+
async function runInlineMutation(lock, mutate) {
|
|
853
|
+
lock.assertOwned();
|
|
854
|
+
const result = await mutate(lock);
|
|
855
|
+
lock.assertOwned();
|
|
856
|
+
return result;
|
|
857
|
+
}
|
|
858
|
+
/** The owning path, shared by a lock this package acquired and a lock the caller supplies. */
|
|
859
|
+
async function runOwnedMutation(resolvedRoot, cacheDir, hold, options, mutate) {
|
|
860
|
+
let recovery;
|
|
861
|
+
const mutationLock = {
|
|
862
|
+
transactionRoot: join(cacheDir, "file-transactions"),
|
|
863
|
+
get recovery() {
|
|
864
|
+
return recovery;
|
|
865
|
+
},
|
|
866
|
+
assertOwned: () => hold.assertOwned()
|
|
867
|
+
};
|
|
868
|
+
const scope = {
|
|
869
|
+
active: true,
|
|
870
|
+
lock: mutationLock
|
|
871
|
+
};
|
|
872
|
+
try {
|
|
873
|
+
const pendingState = await inspectKnowledgeFileTransaction({
|
|
874
|
+
root: resolvedRoot,
|
|
875
|
+
transactionRoot: mutationLock.transactionRoot
|
|
876
|
+
});
|
|
877
|
+
const pending = pendingState?.transaction ?? null;
|
|
878
|
+
const resume = pending ? assertKnowledgeTransactionResume(pending, options.resumeTransaction) : void 0;
|
|
879
|
+
const locks = new Map(activeRoots.getStore());
|
|
880
|
+
locks.set(resolvedRoot, scope);
|
|
881
|
+
return await activeRoots.run(locks, async () => {
|
|
882
|
+
const epoch = await beginMutationEpoch(cacheDir);
|
|
883
|
+
const finishEpoch = async (completed) => {
|
|
884
|
+
mutationLock.assertOwned();
|
|
885
|
+
const stillPending = await loadKnowledgeFileTransaction({
|
|
886
|
+
root: resolvedRoot,
|
|
887
|
+
transactionRoot: mutationLock.transactionRoot
|
|
888
|
+
});
|
|
889
|
+
if (completed && stillPending) throw new Error("knowledge mutation returned with an unfinished transaction");
|
|
890
|
+
if (!stillPending) await finishMutationEpoch(cacheDir, epoch);
|
|
891
|
+
};
|
|
892
|
+
try {
|
|
893
|
+
if (pending) {
|
|
894
|
+
if (!resume) throw new Error(`knowledge transaction '${pending.purpose}' requires its owner to resume`);
|
|
895
|
+
await recoverKnowledgeFileTransaction({
|
|
896
|
+
root: resolvedRoot,
|
|
897
|
+
transactionRoot: mutationLock.transactionRoot,
|
|
898
|
+
expectedPurpose: resume.purpose,
|
|
899
|
+
direction: resume.direction,
|
|
900
|
+
finish: resume.deferFinish !== true,
|
|
901
|
+
validate: resume.validate,
|
|
902
|
+
assertOwned: mutationLock.assertOwned
|
|
903
|
+
});
|
|
904
|
+
recovery = Object.freeze({
|
|
905
|
+
transactionId: pending.transactionId,
|
|
906
|
+
purpose: pending.purpose,
|
|
907
|
+
direction: resume.direction ?? pendingState?.direction ?? "apply",
|
|
908
|
+
transaction: pending
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
mutationLock.assertOwned();
|
|
912
|
+
const result = await mutate(mutationLock);
|
|
913
|
+
mutationLock.assertOwned();
|
|
914
|
+
await finishEpoch(true);
|
|
915
|
+
return result;
|
|
916
|
+
} catch (error) {
|
|
917
|
+
try {
|
|
918
|
+
await finishEpoch(false);
|
|
919
|
+
} catch (finishError) {
|
|
920
|
+
throw new AggregateError([error, finishError], "knowledge mutation failed and its durable state could not be inspected");
|
|
921
|
+
}
|
|
922
|
+
throw error;
|
|
923
|
+
}
|
|
924
|
+
});
|
|
925
|
+
} finally {
|
|
926
|
+
scope.active = false;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
893
929
|
async function inspectPendingKnowledgeMutation(root) {
|
|
894
930
|
const resolvedRoot = resolve(root);
|
|
895
931
|
const pending = await inspectKnowledgeFileTransaction({
|
|
@@ -2811,7 +2847,7 @@ const NO_CHECK_NOTE = "a claim at this rung asserts that a command reproduces a
|
|
|
2811
2847
|
const NO_EXPECTATION_NOTE = "exit code alone cannot verify a claim at this rung — record the value the check must print";
|
|
2812
2848
|
const CONSTANT_EMITTER_NOTE = "the check is a constant emitter: it prints a fixed string and exits zero whatever the claim describes, so it can never fail — record a command that reads the artifact the claim is about";
|
|
2813
2849
|
const MULTILINE_EXPECTATION_NOTE = "the expected value spans multiple lines, but the grader performs one contiguous-substring comparison — record one decisive single-line value per claim";
|
|
2814
|
-
const
|
|
2850
|
+
const SELF_CERTIFYING_NOTE = "the check text contains the expected value, so the check carries the answer it is graded against and prints a value the claim did not have to produce — record a command that reads the artifact and prints the value it finds there";
|
|
2815
2851
|
const LONG_FIRST_WORD_NOTE = "the check begins with a shell word longer than 200 characters; this is the escaped-newline failure shape where \\n text was recorded instead of real line breaks — write the script to a file or record a real heredoc and a short invocation";
|
|
2816
2852
|
const INVALID_SHELL_SYNTAX_NOTE = "the recorded check does not parse under bash and would fail independently of the claim — record the exact command only after bash -n accepts it";
|
|
2817
2853
|
/**
|
|
@@ -2841,28 +2877,56 @@ var UncheckableClaimError = class extends Error {
|
|
|
2841
2877
|
* `gradeFor` grades `uncheckable`: no check, a check that cannot fail, an unusable expectation,
|
|
2842
2878
|
* or the escaped-newline command shape. Below the threshold nothing is refused.
|
|
2843
2879
|
*
|
|
2844
|
-
*
|
|
2845
|
-
* from multiline expectations,
|
|
2846
|
-
*
|
|
2847
|
-
*
|
|
2848
|
-
*
|
|
2880
|
+
* Three additional rules are calibrated on downstream losses, not taste: four correct claims
|
|
2881
|
+
* died from multiline expectations, one campaign recorded an enormous first word made of literal
|
|
2882
|
+
* `\\n` sequences, and a 299-run fleet autopsy reduced ten reported grader failures to checks that
|
|
2883
|
+
* were never executed before their authors disappeared. The dynamic half of that last rule is
|
|
2884
|
+
* `verifyGradeableEvidence` below.
|
|
2849
2885
|
*/
|
|
2850
2886
|
function assertGradeableEvidence(evidence) {
|
|
2851
2887
|
if (evidence.rung < 4) return evidence;
|
|
2852
|
-
const note = checkRefusalNote(evidence.check) ?? expectationRefusalNote(evidence.expect);
|
|
2888
|
+
const note = checkRefusalNote(evidence.check) ?? selfCertifyingNote(evidence) ?? expectationRefusalNote(evidence.expect);
|
|
2853
2889
|
if (note) throw new UncheckableClaimError(evidence.rung, note);
|
|
2854
2890
|
return evidence;
|
|
2855
2891
|
}
|
|
2856
|
-
/**
|
|
2857
|
-
|
|
2892
|
+
/**
|
|
2893
|
+
* The output signatures that mean the check never reached what the claim is about.
|
|
2894
|
+
*
|
|
2895
|
+
* Matched case-insensitively, because a tool that prints its own diagnostic chooses its own case,
|
|
2896
|
+
* and read from the OUTPUT rather than from the exit status. A shell pipeline exits with the
|
|
2897
|
+
* status of its last stage, so `sha256sum <missing path> | cut -d' ' -f1` prints
|
|
2898
|
+
* "No such file or directory" and exits 0; reading only the status calls that a refutation of
|
|
2899
|
+
* research that was never run. Swept over 272 grade files, 29 of 61 recorded refutations were
|
|
2900
|
+
* this shape: 7 a malformed check body, 7 a shell that could not parse the check, 6 a solver that
|
|
2901
|
+
* could not open its problem file, 5 `Permission denied`, 4 `cannot create directory`.
|
|
2902
|
+
*/
|
|
2903
|
+
const UNRUNNABLE_SIGNATURES = /No such file|FileNotFoundError|ModuleNotFoundError|command not found|ENOENT|AbortError|timed out|ERR_CHILD_PROCESS_STDIO_MAXBUFFER|Permission denied|EACCES|cannot create directory|cannot open|SyntaxError|unexpected EOF while looking for matching|syntax error near unexpected token/i;
|
|
2904
|
+
/**
|
|
2905
|
+
* The exit status a deadline kill reports: `timeout(1)`'s status, and the one a bounded process
|
|
2906
|
+
* runner forces so a killed child that closes with 0 cannot read as a pass. A grader that has
|
|
2907
|
+
* only an exit status reports this one; a grader that knows it killed the process sets
|
|
2908
|
+
* `CheckExecution.timedOut` instead, which is unambiguous.
|
|
2909
|
+
*/
|
|
2910
|
+
const DEADLINE_EXIT_CODE = 124;
|
|
2911
|
+
const DEADLINE_NOTE = "the check was killed at its deadline, so it never tested the claim — a deadline is a budget, not a verdict; raise the budget or record a check that decides within it";
|
|
2912
|
+
const UNREACHED_INPUT_NOTE = "the check never reached what the claim is about, so this is a verdict on the environment and not on the claim";
|
|
2858
2913
|
/**
|
|
2859
2914
|
* The calibrated verdict function, pure so every grader shares one semantics. Callers execute the
|
|
2860
2915
|
* check however their environment requires and pass the observation; this function only judges.
|
|
2916
|
+
*
|
|
2917
|
+
* Three rules decide a verdict before the expectation is compared, and each one exists because
|
|
2918
|
+
* comparing first blamed the claim for something the claim did not do:
|
|
2919
|
+
*
|
|
2920
|
+
* - a check that carries its own expected value is refused, because its output is authored
|
|
2921
|
+
* rather than measured;
|
|
2922
|
+
* - a check killed at its deadline is `unrunnable`, because a budget is not a verdict;
|
|
2923
|
+
* - a check whose output says it never reached its input is `unrunnable` whatever its exit
|
|
2924
|
+
* status, because a pipeline hides the failing stage's status behind its last stage.
|
|
2861
2925
|
*/
|
|
2862
2926
|
function gradeFor(evidence, execution) {
|
|
2863
2927
|
const mustBeCheckable = evidence.rung >= 4;
|
|
2864
2928
|
if (mustBeCheckable) {
|
|
2865
|
-
const note = checkRefusalNote(evidence.check);
|
|
2929
|
+
const note = checkRefusalNote(evidence.check) ?? selfCertifyingNote(evidence);
|
|
2866
2930
|
if (note) return {
|
|
2867
2931
|
verdict: "uncheckable",
|
|
2868
2932
|
note
|
|
@@ -2870,7 +2934,11 @@ function gradeFor(evidence, execution) {
|
|
|
2870
2934
|
}
|
|
2871
2935
|
if (!execution) return { verdict: "unrunnable" };
|
|
2872
2936
|
const output = `${execution.stdout}\n${execution.stderr}`.trim();
|
|
2873
|
-
if (execution.exitCode
|
|
2937
|
+
if (execution.timedOut || execution.exitCode === 124) return {
|
|
2938
|
+
verdict: "unrunnable",
|
|
2939
|
+
note: DEADLINE_NOTE
|
|
2940
|
+
};
|
|
2941
|
+
if (execution.exitCode !== 0) return refutation(output, evidence.expect);
|
|
2874
2942
|
if (mustBeCheckable) {
|
|
2875
2943
|
const note = expectationRefusalNote(evidence.expect);
|
|
2876
2944
|
if (note) return {
|
|
@@ -2878,9 +2946,88 @@ function gradeFor(evidence, execution) {
|
|
|
2878
2946
|
note
|
|
2879
2947
|
};
|
|
2880
2948
|
}
|
|
2881
|
-
if (evidence.expect && !output.includes(evidence.expect))
|
|
2949
|
+
if (evidence.expect && !output.includes(evidence.expect)) {
|
|
2950
|
+
if (output === "") return { verdict: "silent-check" };
|
|
2951
|
+
return refutation(output, evidence.expect);
|
|
2952
|
+
}
|
|
2882
2953
|
return { verdict: "verified" };
|
|
2883
2954
|
}
|
|
2955
|
+
/**
|
|
2956
|
+
* Decide between a claim verdict and an environment verdict for output that failed to establish
|
|
2957
|
+
* the claim. The signature list only ever downgrades a refutation to `unrunnable`: it can turn a
|
|
2958
|
+
* measurement that did not happen into an honest "not measured", and it can never turn a real
|
|
2959
|
+
* failure into a pass.
|
|
2960
|
+
*
|
|
2961
|
+
* The expectation is consulted first. A claim that PREDICTED the error is genuinely contradicted
|
|
2962
|
+
* when the error does not appear, so an expectation naming a signature switches this guard off
|
|
2963
|
+
* for that claim rather than letting it hide the one case it would grade backwards.
|
|
2964
|
+
*/
|
|
2965
|
+
function refutation(output, expect) {
|
|
2966
|
+
if (expect && UNRUNNABLE_SIGNATURES.test(expect)) return { verdict: "contradicted" };
|
|
2967
|
+
const hit = UNRUNNABLE_SIGNATURES.exec(output);
|
|
2968
|
+
if (!hit) return { verdict: "contradicted" };
|
|
2969
|
+
return {
|
|
2970
|
+
verdict: "unrunnable",
|
|
2971
|
+
note: `${UNREACHED_INPUT_NOTE} (${hit[0]})`
|
|
2972
|
+
};
|
|
2973
|
+
}
|
|
2974
|
+
/**
|
|
2975
|
+
* Grade one pass of claims and flag the repeats within it.
|
|
2976
|
+
*
|
|
2977
|
+
* `gradeFor` judges one claim and cannot see a second claim carrying the same check, so a run
|
|
2978
|
+
* that recorded one verification under several titles reports as several independent
|
|
2979
|
+
* verifications. This function grades each claim exactly as `gradeFor` does and marks the later
|
|
2980
|
+
* claim with `duplicateOf`, leaving the verdict and the count untouched: the flag is for a reader
|
|
2981
|
+
* deciding how much evidence a run really produced.
|
|
2982
|
+
*/
|
|
2983
|
+
function gradeClaims(claims) {
|
|
2984
|
+
const firstSeen = /* @__PURE__ */ new Map();
|
|
2985
|
+
return claims.map((claim) => {
|
|
2986
|
+
const grade = gradeFor(claim.evidence, claim.execution);
|
|
2987
|
+
const key = claimCheckKey({
|
|
2988
|
+
...claim.evidence,
|
|
2989
|
+
title: claim.title
|
|
2990
|
+
});
|
|
2991
|
+
if (!key) return {
|
|
2992
|
+
id: claim.id,
|
|
2993
|
+
...grade
|
|
2994
|
+
};
|
|
2995
|
+
const seenAt = `${key}\u0000${grade.verdict}`;
|
|
2996
|
+
const canonical = firstSeen.get(seenAt);
|
|
2997
|
+
if (canonical === void 0) {
|
|
2998
|
+
firstSeen.set(seenAt, claim.id);
|
|
2999
|
+
return {
|
|
3000
|
+
id: claim.id,
|
|
3001
|
+
...grade
|
|
3002
|
+
};
|
|
3003
|
+
}
|
|
3004
|
+
return {
|
|
3005
|
+
id: claim.id,
|
|
3006
|
+
...grade,
|
|
3007
|
+
duplicateOf: canonical
|
|
3008
|
+
};
|
|
3009
|
+
});
|
|
3010
|
+
}
|
|
3011
|
+
/**
|
|
3012
|
+
* The identity two claims must share to be one verification counted twice: the same command, the
|
|
3013
|
+
* same expectation, and the same sentence. A check shared across claims that say different things
|
|
3014
|
+
* is one instrument used several times, which is not a duplicate.
|
|
3015
|
+
*
|
|
3016
|
+
* Returns `undefined` when the claim cannot be keyed at all — no check, or no title to compare —
|
|
3017
|
+
* so an unkeyable claim is never flagged as a repeat of another unkeyable one. The key is JSON
|
|
3018
|
+
* rather than a joined string, so no separator can collide with text inside a check.
|
|
3019
|
+
*/
|
|
3020
|
+
function claimCheckKey(claim) {
|
|
3021
|
+
const check = claim.check?.trim();
|
|
3022
|
+
if (!check) return void 0;
|
|
3023
|
+
const title = claim.title?.trim().replace(/\s+/g, " ").toLowerCase().replace(/\.md$/, "");
|
|
3024
|
+
if (!title) return void 0;
|
|
3025
|
+
return JSON.stringify([
|
|
3026
|
+
check,
|
|
3027
|
+
claim.expect?.trim() ?? "",
|
|
3028
|
+
title
|
|
3029
|
+
]);
|
|
3030
|
+
}
|
|
2884
3031
|
/** The verdict alone, for graders that report a lattice member and not a reason. */
|
|
2885
3032
|
function verdictFor(evidence, execution) {
|
|
2886
3033
|
return gradeFor(evidence, execution).verdict;
|
|
@@ -2914,6 +3061,35 @@ async function verifyGradeableEvidence(evidence, options) {
|
|
|
2914
3061
|
grade: gradeFor(accepted, execution)
|
|
2915
3062
|
};
|
|
2916
3063
|
}
|
|
3064
|
+
const WORD_CHARACTER = /[A-Za-z0-9_]/;
|
|
3065
|
+
/**
|
|
3066
|
+
* Whether the check text carries the value it is graded against.
|
|
3067
|
+
*
|
|
3068
|
+
* A check that contains its own expectation prints a value the claim's subject did not have to
|
|
3069
|
+
* produce, so the comparison that follows tests the author's typing rather than the artifact.
|
|
3070
|
+
* The test is the whole trimmed expectation appearing verbatim in the command, which is narrow
|
|
3071
|
+
* on purpose: it costs an author only a rewrite of the command, and it catches the shape
|
|
3072
|
+
* `isConstantEmitter` cannot, where a real command's arguments already spell the answer.
|
|
3073
|
+
*
|
|
3074
|
+
* An occurrence glued to a word character on a side where the expectation is itself a word
|
|
3075
|
+
* character does not count. Without that, a short expectation refuses the check that reads it:
|
|
3076
|
+
* `expect: 6` appears inside `node report6.mjs`, and refusing a correct claim is the cost this
|
|
3077
|
+
* file's rules are calibrated to avoid.
|
|
3078
|
+
*/
|
|
3079
|
+
function selfCertifyingNote(evidence) {
|
|
3080
|
+
const wanted = evidence.expect?.trim();
|
|
3081
|
+
const check = evidence.check;
|
|
3082
|
+
if (!check || !wanted) return void 0;
|
|
3083
|
+
const startsInsideWord = WORD_CHARACTER.test(wanted[0]);
|
|
3084
|
+
const endsInsideWord = WORD_CHARACTER.test(wanted[wanted.length - 1]);
|
|
3085
|
+
for (let at = check.indexOf(wanted); at !== -1; at = check.indexOf(wanted, at + 1)) {
|
|
3086
|
+
const before = check[at - 1];
|
|
3087
|
+
const after = check[at + wanted.length];
|
|
3088
|
+
if (startsInsideWord && before !== void 0 && WORD_CHARACTER.test(before)) continue;
|
|
3089
|
+
if (endsInsideWord && after !== void 0 && WORD_CHARACTER.test(after)) continue;
|
|
3090
|
+
return SELF_CERTIFYING_NOTE;
|
|
3091
|
+
}
|
|
3092
|
+
}
|
|
2917
3093
|
function checkRefusalNote(check) {
|
|
2918
3094
|
if (!check) return NO_CHECK_NOTE;
|
|
2919
3095
|
if (isConstantEmitter(check)) return CONSTANT_EMITTER_NOTE;
|
|
@@ -2922,7 +3098,6 @@ function checkRefusalNote(check) {
|
|
|
2922
3098
|
function expectationRefusalNote(expect) {
|
|
2923
3099
|
if (!expect?.trim()) return NO_EXPECTATION_NOTE;
|
|
2924
3100
|
if (expect.includes("\n") || expect.includes("\r")) return MULTILINE_EXPECTATION_NOTE;
|
|
2925
|
-
if (expect.trim().split(/\s+/).filter((token) => token.includes("=")).length >= 3) return MULTI_VALUE_EXPECTATION_NOTE;
|
|
2926
3101
|
}
|
|
2927
3102
|
async function runBash(args, options) {
|
|
2928
3103
|
const { execFile } = await import("node:child_process");
|
|
@@ -2936,10 +3111,12 @@ async function runBash(args, options) {
|
|
|
2936
3111
|
encoding: "utf8"
|
|
2937
3112
|
}, (error, stdout, stderr) => {
|
|
2938
3113
|
const diagnostic = error && typeof error.code !== "number" ? `${stderr}\n${error}` : stderr;
|
|
3114
|
+
const timedOut = error?.killed === true && error.name !== "AbortError";
|
|
2939
3115
|
resolve({
|
|
2940
3116
|
exitCode: typeof error?.code === "number" ? error.code : error ? 127 : 0,
|
|
2941
3117
|
stdout: String(stdout ?? ""),
|
|
2942
|
-
stderr: String(diagnostic ?? "")
|
|
3118
|
+
stderr: String(diagnostic ?? ""),
|
|
3119
|
+
...timedOut ? { timedOut: true } : {}
|
|
2943
3120
|
});
|
|
2944
3121
|
});
|
|
2945
3122
|
});
|
|
@@ -3794,6 +3971,6 @@ function explainKnowledgeTarget(index, target) {
|
|
|
3794
3971
|
};
|
|
3795
3972
|
}
|
|
3796
3973
|
//#endregion
|
|
3797
|
-
export {
|
|
3974
|
+
export { formatKnowledgeCitationReference as $, inspectPendingKnowledgeMutation as $t, addSourceText as A, writeJsonDurableWithinRoot as An, ResearchSourceVersionSchema as At, KB_STORE_DIR as B, claimId as Bt, gradeClaims as C, renameDurable as Cn, KnowledgePageSchema as Ct, buildKnowledgeIndex as D, writeFileDurable as Dn, ResearchClaimEvidenceSchema as Dt, verifyGradeableEvidence as E, withSafeDirectory as En, KnowledgeRelationSchema as Et, ClaimLedgerMigrationRequiredError as F, assertDeepQuestionIntegrity as Ft, KnowledgeCitationAuditError as G, materializeRegisteredClaimEvidence as Gt, assertClaimLedgerId as H, deepQuestionId as Ht, FileSystemKbStore as I, assertResearchClaimEvidenceIntegrity as It, assertKnowledgeCitationAudit as J, normalizeClaimText as Jt, KnowledgeCitationResolutionError as K, mergeClaimLedgers as Kt, KB_CLAIM_LEDGER_DIR as L, assertResearchClaimLedgerIntegrity as Lt, snapshotSourceTextInput as M, textSourceAdapter as Mn, SourceRecordSchema as Mt, sourceRegistryPath as N, KNOWLEDGE_EVENT_TYPES as Nt, writeKnowledgeIndex as O, writeFileDurableWithinRoot as On, ResearchClaimLedgerSchema as Ot, writeSourceRegistry as P, ClaimLedgerGoalConflictError as Pt, auditKnowledgeCitations as Q, acquireDurableFileLock as Qt, KB_EVENTS_PATH as R, assertTrackedClaimIntegrity as Rt, claimCheckKey as S, removeDurable as Sn, KnowledgePageInvalidationSchema as St, verdictFor as T, withSafeDescendant as Tn, KnowledgeRelationNodeSchema as Tt, buildKnowledgeGraph as U, emptyClaimLedger as Ut, MemoryKbStore as V, claimSourceHost as Vt, knowledgePageRelations as W, linkClaimContradictions as Wt, assertRunScopedCitationsResolved as X, formatFrontmatter as Xt, assertKnowledgeCitationsResolved as Y, researchSourceVersionKey as Yt, auditCurrentRunCitations as Z, parseFrontmatter as Zt, lintKnowledgeIndex as _, isMissingFile as _n, KnowledgeBaseCandidateSchema as _t, applyKnowledgeWriteBlocksFile as a, applyKnowledgeFileTransaction as an, SCAFFOLD_PAGE_BASENAMES as at, UncheckableClaimError as b, readRegularFileWithinRoot as bn, KnowledgeGraphNodeSchema as bt, KnowledgeDuplicateIntakeError as c, finishKnowledgeFileTransaction as cn, isScaffoldPath as ct, createFileRunLineageAuthority as d, rollbackKnowledgeFileTransaction as dn, loadKnowledgePages as dt, isKnowledgeMutationHeld as en, parseKnowledgeCitationReference as et, createRunScopedStores as f, DEFAULT_PAGES_DIRECTORY as fn, writeJson as ft, validateKnowledgeIndex as g, isKernelAnchoredPath as gn, DeepQuestionSchema as gt, normalizePageText as h, canonicalRelativeWithinRoot as hn, normalizeLinkTarget as ht, applyKnowledgeWriteBlocks as i, withKnowledgeRead as in, resolveRunScopedCitations as it, loadSourceRegistry as j, mediaTypeFor$1 as jn, SourceAnchorSchema as jt, addSourcePath as k, writeJsonDurable as kn, ResearchClaimRecordSchema as kt, assertKnowledgeWriteIntake as l, knowledgeFileTransactionPlanHash as ln, knowledgePageFromMarkdown as lt, detectNearDuplicatePages as m, canonicalPathsEqual as mn, extractWikilinks as mt, inspectKnowledgeIndex as n, runInKnowledgeMutationScope as nn, resolveKnowledgeCitations as nt, isSafeKnowledgePath as o, assertKnowledgeMutationPath as on, initKnowledgeBase as ot, originatedPages as p, normalizePagesDirectory as pn, WIKILINK_REGEX as pt, assertCurrentRunCitationsResolved as q, mergeTrackedClaims as qt, stringMetadata as r, withKnowledgeMutation as rn, resolveRunScopedCitation as rt, parseKnowledgeWriteBlocks as s, commitKnowledgeFileMutations as sn, isKnowledgePagePath as st, explainKnowledgeTarget as t, recoverPendingKnowledgeMutation as tn, resolveKnowledgeCitation as tt, RUN_LINEAGE_BASENAME as u, prepareKnowledgeFileTransaction as un, layoutFor as ut, CHECKABLE_RUNG_THRESHOLD as v, listRegularFilesWithinRoot as vn, KnowledgeEventSchema as vt, gradeFor as w, syncDirectory as wn, KnowledgeRelationGraphSchema as wt, assertGradeableEvidence as x, relativeWithinRoot as xn, KnowledgeIndexSchema as xt, DEADLINE_EXIT_CODE as y, readRegularFileNoFollow as yn, KnowledgeGraphEdgeSchema as yt, KB_INDEX_PATH as z, claimEvidenceId as zt };
|
|
3798
3975
|
|
|
3799
|
-
//# sourceMappingURL=inspect-
|
|
3976
|
+
//# sourceMappingURL=inspect-BUp9GUKO.js.map
|