@davesheffer/hunch 1.10.7 → 1.10.8
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/dist/cli/index.js +11 -0
- package/dist/core/premises.js +9 -0
- package/dist/mcp/server.js +12 -7
- package/dist/store/hunchStore.js +11 -1
- package/package.json +1 -1
- package/server.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -4939,6 +4939,17 @@ program
|
|
|
4939
4939
|
console.log(`· ${f.id} — ${f.detail}`);
|
|
4940
4940
|
console.log(`\nHeal: run \`hunch wiki --heal\` — regenerates only the stale pages (the wiki is a derived view; never edit it by hand).\n`);
|
|
4941
4941
|
}
|
|
4942
|
+
// Every drift kind heals here — see bug_drift_heal_asymmetry above. premise-stale
|
|
4943
|
+
// shipped in the drift report without a section here, so a repo whose ONLY drift
|
|
4944
|
+
// was a dead premise got "N findings" from `hunch drift` and a bare closing line
|
|
4945
|
+
// from `hunch heal` — exactly the broken loop that bug is about.
|
|
4946
|
+
const premiseStale = kind("premise-stale");
|
|
4947
|
+
if (premiseStale.length) {
|
|
4948
|
+
console.log(`${premiseStale.length} decision(s) rest on a premise that no longer holds (world≠graph):\n`);
|
|
4949
|
+
for (const f of premiseStale)
|
|
4950
|
+
console.log(`· ${f.id} — ${f.detail}`);
|
|
4951
|
+
console.log(`\nHeal: this is a HUMAN call — the decision's authority is unchanged until you make it. Re-attest (update the premise's review_by/attested), supersede via /capture, or retire the decision. Keeping it for consistency is a valid answer.\n`);
|
|
4952
|
+
}
|
|
4942
4953
|
console.log(`Hunch never rewrites prose for you; this is a read-only reconciliation report.`);
|
|
4943
4954
|
}
|
|
4944
4955
|
finally {
|
package/dist/core/premises.js
CHANGED
|
@@ -20,6 +20,15 @@ function checkPath(claim, rel, wantExists, env) {
|
|
|
20
20
|
: { claim, holds: true, reason: `"${rel}" still absent` };
|
|
21
21
|
}
|
|
22
22
|
function checkOne(p, env) {
|
|
23
|
+
// The clock is an INJECTED input, so it is an unevaluable case like any other.
|
|
24
|
+
// `Date.parse("nope")` is NaN, and `NaN > due` is false — which fell through to
|
|
25
|
+
// "attested until …", i.e. HOLDS. The module's hard rule ("cannot-evaluate is
|
|
26
|
+
// never holds") was enforced for a bad review_by but not for a bad now, and the
|
|
27
|
+
// unenforced half is the one a future caller can get wrong. Checked once, here,
|
|
28
|
+
// so it covers every check kind rather than only the dated one.
|
|
29
|
+
if (!Number.isFinite(Date.parse(env.now))) {
|
|
30
|
+
return { claim: p.claim, holds: false, reason: `unevaluable: caller supplied a non-ISO clock ("${env.now}")` };
|
|
31
|
+
}
|
|
23
32
|
if (p.path_absent !== undefined)
|
|
24
33
|
return checkPath(p.claim, p.path_absent, false, env);
|
|
25
34
|
if (p.path_exists !== undefined)
|
package/dist/mcp/server.js
CHANGED
|
@@ -731,14 +731,19 @@ export function buildServerWithRootControl(initialRoot) {
|
|
|
731
731
|
related_files: z.array(z.string()).optional(),
|
|
732
732
|
related_components: z.array(z.string()).optional(),
|
|
733
733
|
topic: z.string().optional().describe("decision-grounding anchor — one topic per decision; enables doc≠graph drift detection for it. Omit to leave un-anchored."),
|
|
734
|
+
// FLAT, matching PremiseSchema exactly. A nested { check: {...} } shape is
|
|
735
|
+
// silently STRIPPED by Zod, leaving a claim-only premise — and a claim-only
|
|
736
|
+
// premise is "documented only (no check attached)", which ALWAYS HOLDS. An
|
|
737
|
+
// agent following a wrong schema would record a premise that can never fire:
|
|
738
|
+
// the exact fail-open this feature exists to prevent. Keep in lockstep with
|
|
739
|
+
// PremiseSchema in src/core/types.ts.
|
|
734
740
|
premises: z.array(z.object({
|
|
735
|
-
claim: z.string().describe("the
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
})).optional().describe("the checkable reasons this decision rests on. A dead premise NEVER changes authority — it raises an escalation for the human. Omit on re-record to keep the incumbent's premises."),
|
|
741
|
+
claim: z.string().min(1).describe("the human-readable reason this decision rests on"),
|
|
742
|
+
path_absent: z.string().optional().describe("premise holds while this repo-relative path does NOT exist"),
|
|
743
|
+
path_exists: z.string().optional().describe("premise holds while this repo-relative path exists"),
|
|
744
|
+
review_by: z.string().optional().describe("dated attestation: premise holds until this ISO date, then needs re-attesting"),
|
|
745
|
+
attested: z.string().optional().describe("ISO date a human last attested the claim (informational)"),
|
|
746
|
+
})).optional().describe("the checkable reasons this decision rests on — at most ONE check per premise (path_absent | path_exists | review_by). A dead premise NEVER changes authority; it raises an escalation for the human. Omit on re-record to keep the incumbent's premises."),
|
|
742
747
|
status: z.enum(["proposed", "accepted", "rejected", "superseded"]).optional(),
|
|
743
748
|
commit: z.string().optional(),
|
|
744
749
|
supersedes: z.string().optional().describe("id of a decision this one replaces — closes its valid-time window (invalidate, don't delete)"),
|
package/dist/store/hunchStore.js
CHANGED
|
@@ -571,7 +571,17 @@ export class HunchStore {
|
|
|
571
571
|
if (m) {
|
|
572
572
|
if (m.dead)
|
|
573
573
|
w *= 0.6;
|
|
574
|
-
|
|
574
|
+
// agent_recorded sits BETWEEN human_confirmed and llm_draft. It is testimony —
|
|
575
|
+
// a human directed the capture but did not countersign it through /capture — so
|
|
576
|
+
// it must not carry human authority (strict/veto gates key on human_confirmed).
|
|
577
|
+
// But it is a deliberate, human-prompted write, and the unlabelled tier (0.75)
|
|
578
|
+
// is for extracted/inferred machine output. Without this it fell to 0.75 and
|
|
579
|
+
// ranked BELOW an llm_draft the model produced unprompted, which inverts what
|
|
580
|
+
// the authorship stamp is trying to express.
|
|
581
|
+
w *= m.provenance.includes("human_confirmed") ? 1
|
|
582
|
+
: m.provenance.includes("agent_recorded") ? 0.9
|
|
583
|
+
: m.provenance.includes("llm_draft") ? 0.85
|
|
584
|
+
: 0.75;
|
|
575
585
|
if (m.at) {
|
|
576
586
|
const ageDays = Math.max(0, now - Date.parse(m.at)) / 86400000;
|
|
577
587
|
if (Number.isFinite(ageDays))
|
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
9
|
"websiteUrl": "https://hunch-pi.vercel.app",
|
|
10
|
-
"version": "1.10.
|
|
10
|
+
"version": "1.10.8",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
15
15
|
"identifier": "@davesheffer/hunch",
|
|
16
|
-
"version": "1.10.
|
|
16
|
+
"version": "1.10.8",
|
|
17
17
|
"runtimeHint": "npx",
|
|
18
18
|
"packageArguments": [
|
|
19
19
|
{
|