@davesheffer/hunch 1.31.1 → 1.32.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 +1 -0
- package/dist/cli/automaticReviewMemory.d.ts +13 -0
- package/dist/cli/dna.d.ts +2 -0
- package/dist/cli/index.d.ts +16 -0
- package/dist/cli/index.js +602 -43
- package/dist/cli/integrations.d.ts +2 -0
- package/dist/cli/integrations.js +5 -2
- package/dist/cli/invocation.d.ts +35 -0
- package/dist/cli/preflight.d.ts +1 -0
- package/dist/cli/reviewMemory.d.ts +4 -0
- package/dist/cli/reviewMemoryProvider.d.ts +14 -0
- package/dist/cli/serve.d.ts +2 -0
- package/dist/cli/taskReport.d.ts +6 -0
- package/dist/cli/taskReport.js +124 -0
- package/dist/cli/update.d.ts +14 -0
- package/dist/client/state.d.ts +248 -0
- package/dist/constitution/adapters.d.ts +29 -0
- package/dist/constitution/behaviorAttestationBinding.d.ts +3 -0
- package/dist/constitution/behaviorEvaluator.d.ts +8 -0
- package/dist/constitution/behaviorProof.d.ts +9 -0
- package/dist/constitution/behaviorWorkspace.d.ts +25 -0
- package/dist/constitution/bootstrap.d.ts +30 -0
- package/dist/constitution/canonical.d.ts +15 -0
- package/dist/constitution/card.d.ts +58 -0
- package/dist/constitution/compiler.d.ts +52 -0
- package/dist/constitution/composition.d.ts +10 -0
- package/dist/constitution/corpus.d.ts +7 -0
- package/dist/constitution/correctionPolicyMaterializer.d.ts +57 -0
- package/dist/constitution/delta.d.ts +4 -0
- package/dist/constitution/disposition.d.ts +20 -0
- package/dist/constitution/evaluator.d.ts +47 -0
- package/dist/constitution/experiment.d.ts +466 -0
- package/dist/constitution/experimentRunner.d.ts +7 -0
- package/dist/constitution/g2.d.ts +209 -0
- package/dist/constitution/g2BehaviorAttestation.d.ts +45 -0
- package/dist/constitution/g2BehaviorCandidates.d.ts +123 -0
- package/dist/constitution/g2BehaviorDependencies.d.ts +83 -0
- package/dist/constitution/g2BehaviorMaterialization.d.ts +77 -0
- package/dist/constitution/g2BehaviorPolicyMaterializer.d.ts +48 -0
- package/dist/constitution/g2CandidateAttestation.d.ts +43 -0
- package/dist/constitution/g2Candidates.d.ts +80 -0
- package/dist/constitution/g2Drills.d.ts +33 -0
- package/dist/constitution/g3.d.ts +311 -0
- package/dist/constitution/g3Conformance.d.ts +33 -0
- package/dist/constitution/lifecycle.d.ts +25 -0
- package/dist/constitution/mutation.d.ts +15 -0
- package/dist/constitution/nodeTestEvidence.d.ts +13 -0
- package/dist/constitution/plan.d.ts +18 -0
- package/dist/constitution/policyRuntime.d.ts +5 -0
- package/dist/constitution/proof.d.ts +11 -0
- package/dist/constitution/repairPolicies.d.ts +34 -0
- package/dist/constitution/replacementFreeGit.d.ts +14 -0
- package/dist/constitution/replay.d.ts +40 -0
- package/dist/constitution/replayCache.d.ts +14 -0
- package/dist/constitution/replayWorker.d.ts +1 -0
- package/dist/constitution/repository.d.ts +129 -0
- package/dist/constitution/safeCheckout.d.ts +9 -0
- package/dist/constitution/schema.d.ts +1763 -0
- package/dist/constitution/scorecard.d.ts +219 -0
- package/dist/constitution/service.d.ts +398 -0
- package/dist/constitution/shadow.d.ts +54 -0
- package/dist/constitution/sourceMutation.d.ts +15 -0
- package/dist/constitution/staticGraphBaseline.d.ts +13 -0
- package/dist/constitution/structural.d.ts +64 -0
- package/dist/core/agenthook.d.ts +63 -0
- package/dist/core/agenthook.js +1 -0
- package/dist/core/automaticReviewMemory.d.ts +60 -0
- package/dist/core/autoreview.d.ts +66 -0
- package/dist/core/canonicalOrder.d.ts +3 -0
- package/dist/core/capturetoken.d.ts +19 -0
- package/dist/core/changeIdentity.d.ts +22 -0
- package/dist/core/changeProof.d.ts +14 -0
- package/dist/core/checkreport.d.ts +140 -0
- package/dist/core/commitrepair.d.ts +171 -0
- package/dist/core/commitrepair.js +238 -0
- package/dist/core/compare.d.ts +21 -0
- package/dist/core/config.d.ts +20 -0
- package/dist/core/conformance.d.ts +35 -0
- package/dist/core/constraintmatch.d.ts +54 -0
- package/dist/core/correction.d.ts +42 -0
- package/dist/core/correctionStage.d.ts +224 -0
- package/dist/core/declarationClusters.d.ts +149 -0
- package/dist/core/delivery.d.ts +110 -0
- package/dist/core/docanchors.d.ts +32 -0
- package/dist/core/docscan.d.ts +26 -0
- package/dist/core/drift.d.ts +13 -0
- package/dist/core/drift.js +31 -1
- package/dist/core/dupdetect.d.ts +43 -0
- package/dist/core/escalations.d.ts +129 -0
- package/dist/core/escalations.js +165 -0
- package/dist/core/events.d.ts +29 -0
- package/dist/core/evidenceMap.d.ts +164 -0
- package/dist/core/externalImports.d.ts +8 -0
- package/dist/core/format.d.ts +13 -0
- package/dist/core/glob.d.ts +9 -0
- package/dist/core/groundingLag.d.ts +84 -0
- package/dist/core/groundingLag.js +16 -2
- package/dist/core/groundingMerge.d.ts +15 -0
- package/dist/core/groundingMerge.js +95 -0
- package/dist/core/hookcache.d.ts +10 -0
- package/dist/core/hookpolicy.d.ts +47 -0
- package/dist/core/ids.d.ts +36 -0
- package/dist/core/importReview.d.ts +30 -0
- package/dist/core/io.d.ts +23 -0
- package/dist/core/jsonc.d.ts +4 -0
- package/dist/core/landscapeAdoption.d.ts +66 -0
- package/dist/core/landscapeDelivery.d.ts +76 -0
- package/dist/core/memorylog.d.ts +37 -0
- package/dist/core/migrate.d.ts +28 -0
- package/dist/core/outcomeExperience.d.ts +89 -0
- package/dist/core/overlaySafety.d.ts +24 -0
- package/dist/core/overlaySafety.js +7 -1
- package/dist/core/paths.d.ts +31 -0
- package/dist/core/pipeline.d.ts +289 -0
- package/dist/core/premises.d.ts +43 -0
- package/dist/core/provenance.d.ts +21 -0
- package/dist/core/publication.d.ts +54 -0
- package/dist/core/refrepair.d.ts +24 -0
- package/dist/core/refrepair.js +1 -1
- package/dist/core/relativeImports.d.ts +11 -0
- package/dist/core/repair.d.ts +44 -0
- package/dist/core/repairqueue.d.ts +40 -0
- package/dist/core/repairqueue.js +133 -0
- package/dist/core/reviewMemory.d.ts +40 -0
- package/dist/core/reviewqueue.d.ts +54 -0
- package/dist/core/safeRepoFile.d.ts +20 -0
- package/dist/core/served.d.ts +57 -0
- package/dist/core/served.js +14 -0
- package/dist/core/stateContract.d.ts +979 -0
- package/dist/core/stateDelivery.d.ts +78 -0
- package/dist/core/stateRecords.d.ts +383 -0
- package/dist/core/stats.d.ts +88 -0
- package/dist/core/strictgate.d.ts +33 -0
- package/dist/core/taskReport.d.ts +226 -0
- package/dist/core/taskReport.js +514 -0
- package/dist/core/taskReportCapture.d.ts +8 -0
- package/dist/core/taskReportCapture.js +36 -0
- package/dist/core/taskReportEvidence.d.ts +26 -0
- package/dist/core/taskReportEvidence.js +268 -0
- package/dist/core/taskReportHook.d.ts +20 -0
- package/dist/core/taskReportHook.js +76 -0
- package/dist/core/taskReportPaths.d.ts +3 -0
- package/dist/core/taskReportPaths.js +23 -0
- package/dist/core/taskReportPublic.d.ts +31 -0
- package/dist/core/taskReportPublic.js +45 -0
- package/dist/core/taskReportRender.d.ts +6 -0
- package/dist/core/taskReportRender.js +97 -0
- package/dist/core/topics.d.ts +73 -0
- package/dist/core/types.d.ts +1239 -0
- package/dist/core/version.d.ts +10 -0
- package/dist/eval/guards.d.ts +45 -0
- package/dist/eval/harness.d.ts +58 -0
- package/dist/extractors/adrImport.d.ts +59 -0
- package/dist/extractors/comments.d.ts +7 -0
- package/dist/extractors/correctionSources.d.ts +11 -0
- package/dist/extractors/diff.d.ts +40 -0
- package/dist/extractors/git.d.ts +304 -0
- package/dist/extractors/git.js +208 -20
- package/dist/extractors/helm.d.ts +31 -0
- package/dist/extractors/indexer.d.ts +55 -0
- package/dist/extractors/landscapeDiscovery.d.ts +41 -0
- package/dist/extractors/languages.d.ts +77 -0
- package/dist/extractors/nativeTreeSitter.d.ts +16 -0
- package/dist/extractors/parse.d.ts +54 -0
- package/dist/extractors/php.d.ts +26 -0
- package/dist/extractors/repoSource.d.ts +53 -0
- package/dist/extractors/testreport.d.ts +36 -0
- package/dist/integrations/ciAction.d.ts +8 -0
- package/dist/integrations/claudeConfig.d.ts +44 -0
- package/dist/integrations/claudemd.d.ts +13 -0
- package/dist/integrations/claudemd.js +11 -2
- package/dist/integrations/gitignore.d.ts +16 -0
- package/dist/integrations/gitignore.js +7 -0
- package/dist/integrations/health.d.ts +74 -0
- package/dist/integrations/hooks.d.ts +41 -0
- package/dist/integrations/hooks.js +92 -66
- package/dist/integrations/madrExport.d.ts +39 -0
- package/dist/integrations/madrManifest.d.ts +69 -0
- package/dist/integrations/mergeDriver.d.ts +3 -0
- package/dist/integrations/mergeDriver.js +25 -8
- package/dist/integrations/probe.d.ts +4 -0
- package/dist/integrations/providers.d.ts +103 -0
- package/dist/integrations/scaffold.d.ts +29 -0
- package/dist/integrations/sync.d.ts +30 -0
- package/dist/integrations/sync.js +3 -2
- package/dist/integrations/team.d.ts +70 -0
- package/dist/integrations/worktree.d.ts +8 -0
- package/dist/mcp/roots.d.ts +16 -0
- package/dist/mcp/server.d.ts +36 -0
- package/dist/mcp/server.js +74 -22
- package/dist/mcp/taskReportTools.d.ts +3 -0
- package/dist/mcp/taskReportTools.js +106 -0
- package/dist/serve/app.d.ts +36 -0
- package/dist/serve/config.d.ts +100 -0
- package/dist/serve/writelock.d.ts +22 -0
- package/dist/store/changeLedger.d.ts +132 -0
- package/dist/store/compact.d.ts +33 -0
- package/dist/store/db.d.ts +9 -0
- package/dist/store/embedder.d.ts +32 -0
- package/dist/store/hunchStore.d.ts +624 -0
- package/dist/store/hunchStore.js +6 -3
- package/dist/store/jsonStore.d.ts +125 -0
- package/dist/store/merge.d.ts +39 -0
- package/dist/store/privateMigrate.d.ts +24 -0
- package/dist/store/replay.d.ts +56 -0
- package/dist/store/schema.d.ts +17 -0
- package/dist/store/stateBinding.d.ts +145 -0
- package/dist/store/stateCapture.d.ts +15 -0
- package/dist/synthesis/cliAdapter.d.ts +22 -0
- package/dist/synthesis/initiator.d.ts +13 -0
- package/dist/synthesis/provider.d.ts +307 -0
- package/dist/synthesis/synthesize.d.ts +117 -0
- package/dist/synthesis/tripwires.d.ts +9 -0
- package/dist/taskReports.d.ts +76 -0
- package/dist/taskReports.js +67 -0
- package/dist/wiki/adopt.d.ts +22 -0
- package/dist/wiki/graph.d.ts +87 -0
- package/dist/wiki/wiki.d.ts +242 -0
- package/package.json +6 -5
- package/server.json +2 -2
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local-only queue of commit-provenance repairs detected opportunistically
|
|
3
|
+
* (typically by the post-merge hook, src/integrations/hooks.ts) but not yet
|
|
4
|
+
* applied. `.hunch/pending-commit-repairs.json` is gitignored the same way
|
|
5
|
+
* `.hunch/local.json` is — never committed, never pushed. It exists because
|
|
6
|
+
* the opportunistic detection window is narrow: `ORIG_HEAD` gets overwritten
|
|
7
|
+
* by the next merge, and the matched-away commit can eventually be gc'd —
|
|
8
|
+
* queuing the exact {id, from, to} triple here lets a human confirm the match
|
|
9
|
+
* later (`hunch repair-provenance --apply`) without losing it.
|
|
10
|
+
*
|
|
11
|
+
* `.hunch/dropped-commit-repairs.json` is the sibling tombstone file: a human
|
|
12
|
+
* rejecting a queued match via `--drop` records the exact {id, from, to}
|
|
13
|
+
* triple here, durably, so detection re-deriving the identical match on a
|
|
14
|
+
* later merge doesn't re-queue what was already rejected — a genuinely
|
|
15
|
+
* different replacement (`to`) for the same still-orphaned commit is a new
|
|
16
|
+
* proposal and still surfaces (see commitrepair.ts's withoutDropped). Same
|
|
17
|
+
* local-only, gitignored discipline as the queue.
|
|
18
|
+
*/
|
|
19
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
20
|
+
import { join } from "node:path";
|
|
21
|
+
import { writeFileAtomic } from "./io.js";
|
|
22
|
+
import { withoutDropped, withheldForUnresolvableTo } from "./commitrepair.js";
|
|
23
|
+
import { commitsExist } from "../extractors/git.js";
|
|
24
|
+
function queuePath(root) {
|
|
25
|
+
return join(root, ".hunch", "pending-commit-repairs.json");
|
|
26
|
+
}
|
|
27
|
+
function droppedPath(root) {
|
|
28
|
+
return join(root, ".hunch", "dropped-commit-repairs.json");
|
|
29
|
+
}
|
|
30
|
+
function isCommitRewrite(value) {
|
|
31
|
+
if (!value || typeof value !== "object")
|
|
32
|
+
return false;
|
|
33
|
+
const { id, from, to } = value;
|
|
34
|
+
// Non-empty, and to !== from — an empty target is never a useful rewrite,
|
|
35
|
+
// and a no-op entry would apply "successfully" while accomplishing nothing.
|
|
36
|
+
// Deliberately NOT a hex-shape check: from/to are opaque strings elsewhere
|
|
37
|
+
// in this codebase's test fixtures, and repairDecisionCommit's own
|
|
38
|
+
// `d.commit === mine.from` guard already makes a garbage `from` inert (it
|
|
39
|
+
// can never match a real decision). A garbage `to` is caught elsewhere,
|
|
40
|
+
// not here: `hunch repair-provenance --apply` runs commitsExist against
|
|
41
|
+
// every `to` it's actually about to act on (the whole queue, or just the
|
|
42
|
+
// one entry `--only <id>` targets) before repairDecisionCommit ever sees
|
|
43
|
+
// it, and leaves a non-resolving entry queued rather than applying it
|
|
44
|
+
// (withheldForUnresolvableTo, src/core/commitrepair.ts) — with the caveat
|
|
45
|
+
// that commitsExist itself fails OPEN if the check can't run at all (not a
|
|
46
|
+
// git repo, git missing, timeout), same as drift.ts's own use of it. This
|
|
47
|
+
// filter stays shape-only on purpose — the existence check needs a
|
|
48
|
+
// repository to run against, which this read-only queue loader doesn't
|
|
49
|
+
// have.
|
|
50
|
+
return typeof id === "string" && !!id
|
|
51
|
+
&& typeof from === "string" && !!from
|
|
52
|
+
&& typeof to === "string" && !!to
|
|
53
|
+
&& to !== from;
|
|
54
|
+
}
|
|
55
|
+
function isDroppedRewrite(value) {
|
|
56
|
+
if (!value || typeof value !== "object")
|
|
57
|
+
return false;
|
|
58
|
+
const { id, from, to } = value;
|
|
59
|
+
return typeof id === "string" && !!id
|
|
60
|
+
&& typeof from === "string" && !!from
|
|
61
|
+
&& typeof to === "string" && !!to;
|
|
62
|
+
}
|
|
63
|
+
/** Tolerant read: a missing or corrupt queue file is treated as empty — this
|
|
64
|
+
* is local scratch state, never a source of truth worth failing loudly over. */
|
|
65
|
+
export function readPendingRepairs(root) {
|
|
66
|
+
const path = queuePath(root);
|
|
67
|
+
if (!existsSync(path))
|
|
68
|
+
return [];
|
|
69
|
+
try {
|
|
70
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
71
|
+
return Array.isArray(parsed) ? parsed.filter(isCommitRewrite) : [];
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export function writePendingRepairs(root, rewrites) {
|
|
78
|
+
writeFileAtomic(queuePath(root), JSON.stringify(rewrites, null, 2) + "\n");
|
|
79
|
+
}
|
|
80
|
+
/** Tolerant read, same discipline as readPendingRepairs. */
|
|
81
|
+
export function readDroppedRepairs(root) {
|
|
82
|
+
const path = droppedPath(root);
|
|
83
|
+
if (!existsSync(path))
|
|
84
|
+
return [];
|
|
85
|
+
try {
|
|
86
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
87
|
+
return Array.isArray(parsed) ? parsed.filter(isDroppedRewrite) : [];
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export function writeDroppedRepairs(root, dropped) {
|
|
94
|
+
writeFileAtomic(droppedPath(root), JSON.stringify(dropped, null, 2) + "\n");
|
|
95
|
+
}
|
|
96
|
+
/** The queue as every READ-ONLY consumer should see it: raw entries minus
|
|
97
|
+
* anything a human already rejected via `--drop`, regardless of how a
|
|
98
|
+
* tombstoned entry ended up back in the raw queue file (e.g. the post-merge
|
|
99
|
+
* hook's backgrounded detection racing a `--drop`). A read-time filter, not
|
|
100
|
+
* a mutation — the raw queue file is untouched.
|
|
101
|
+
*
|
|
102
|
+
* `repair-provenance`'s own action is the one exception: it needs the RAW
|
|
103
|
+
* read (via readPendingRepairs) because it diffs raw-vs-swept to report what
|
|
104
|
+
* it cleaned up, and it persists the sweep back to disk. Every other
|
|
105
|
+
* reader — `hunch escalations`, SessionStart orientation, the `hunch_now`
|
|
106
|
+
* and `hunch_escalations` MCP tools — must call this instead, or a
|
|
107
|
+
* tombstoned entry that hasn't yet been swept by a `repair-provenance` run
|
|
108
|
+
* re-surfaces as if the human never answered it. */
|
|
109
|
+
export function readActivePendingRepairs(root) {
|
|
110
|
+
return withoutDropped(readPendingRepairs(root), readDroppedRepairs(root));
|
|
111
|
+
}
|
|
112
|
+
/** The `queued` entries whose proposed `to` doesn't resolve to a real commit
|
|
113
|
+
* in this repository — the same withheldForUnresolvableTo gate
|
|
114
|
+
* `repair-provenance --apply` itself runs before writing, surfaced here so
|
|
115
|
+
* a READ-ONLY consumer (hunch escalations, hunch_now/hunch_escalations,
|
|
116
|
+
* SessionStart orientation) can tell a permanently-stuck entry apart from
|
|
117
|
+
* one `--apply` can still resolve, instead of advertising a
|
|
118
|
+
* `--apply --only <id>` that's guaranteed to no-op forever. `null` from
|
|
119
|
+
* commitsExist (the check itself failed to run) is treated as fail-open —
|
|
120
|
+
* same discipline as the apply path — so nothing is misreported as
|
|
121
|
+
* withheld just because the check couldn't run.
|
|
122
|
+
*
|
|
123
|
+
* Returns the OBJECTS, not their ids, and every caller must pass the exact
|
|
124
|
+
* same `queued` array into both this function and whatever it hands the
|
|
125
|
+
* result to (commitRepairEscalations) — an id-keyed set would collapse a
|
|
126
|
+
* corrupted queue's two same-id entries (one resolvable, one not) into one
|
|
127
|
+
* unit, exactly the identity confusion withheldForUnresolvableTo's own
|
|
128
|
+
* docstring warns about. */
|
|
129
|
+
export function withheldRewrites(root, queued) {
|
|
130
|
+
const existing = commitsExist(queued.map((r) => r.to), root);
|
|
131
|
+
return new Set(withheldForUnresolvableTo(queued, existing).withheld);
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=repairqueue.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** Review text is evidence, never executable instructions or policy authority. */
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { Constraint } from "./types.js";
|
|
4
|
+
declare const commentSchema: z.ZodObject<{
|
|
5
|
+
id: z.ZodNumber;
|
|
6
|
+
body: z.ZodString;
|
|
7
|
+
path: z.ZodString;
|
|
8
|
+
html_url: z.ZodString;
|
|
9
|
+
commit_id: z.ZodString;
|
|
10
|
+
created_at: z.ZodString;
|
|
11
|
+
updated_at: z.ZodString;
|
|
12
|
+
in_reply_to_id: z.ZodOptional<z.ZodNumber>;
|
|
13
|
+
user: z.ZodObject<{
|
|
14
|
+
login: z.ZodString;
|
|
15
|
+
type: z.ZodEnum<{
|
|
16
|
+
User: "User";
|
|
17
|
+
Bot: "Bot";
|
|
18
|
+
}>;
|
|
19
|
+
}, z.core.$strip>;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
type Comment = z.infer<typeof commentSchema>;
|
|
22
|
+
export interface ReviewCandidate {
|
|
23
|
+
id: string;
|
|
24
|
+
evidence_hash: string;
|
|
25
|
+
file: string;
|
|
26
|
+
comments: Comment[];
|
|
27
|
+
}
|
|
28
|
+
export interface ReviewPacket {
|
|
29
|
+
schema: "hunch.review-memory/1";
|
|
30
|
+
repository: string;
|
|
31
|
+
authority: "none";
|
|
32
|
+
candidates: ReviewCandidate[];
|
|
33
|
+
excluded_bots: number;
|
|
34
|
+
}
|
|
35
|
+
/** Accept GitHub REST review-comment exports, including gh --paginate --slurp pages. */
|
|
36
|
+
export declare function prepareReviewMemory(repository: string, input: unknown): ReviewPacket;
|
|
37
|
+
export declare function validateReviewPacket(input: unknown): ReviewPacket;
|
|
38
|
+
/** A separate, explicit selection supplies the actual rule and how to check it. */
|
|
39
|
+
export declare function compileReviewRules(packetInput: unknown, selections: unknown, now: string): Constraint[];
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review-queue shaping for `hunch review` (the capture → REVIEW → enforce funnel).
|
|
3
|
+
*
|
|
4
|
+
* Pure, deterministic, no I/O — so it's unit-testable away from the store. Reads the
|
|
5
|
+
* `synth:` telemetry line that syncCommit parks in `provenance.evidence` and splits the
|
|
6
|
+
* drafts into two groups so a reviewer can blast through the easy confirmations and then
|
|
7
|
+
* scrutinize the rest:
|
|
8
|
+
* - READY — the Critic AUDITED the draft and found it well-grounded
|
|
9
|
+
* (source includes "verified" AND grounded >= threshold). Best first.
|
|
10
|
+
* - SCRUTINY — everything else (unverified, low-grounded, verify failed/unavailable).
|
|
11
|
+
* Lowest-confidence first, i.e. worst-first triage (unchanged behavior).
|
|
12
|
+
*/
|
|
13
|
+
import type { Decision } from "./types.js";
|
|
14
|
+
/** Parsed view of the `synth:` telemetry line (or {} when absent). */
|
|
15
|
+
export interface SynthInfo {
|
|
16
|
+
provider?: string;
|
|
17
|
+
grounded?: number;
|
|
18
|
+
samples?: number;
|
|
19
|
+
agreement?: number;
|
|
20
|
+
pruned?: number;
|
|
21
|
+
/** "unavailable" | "failed" — present only when verification was requested but didn't apply. */
|
|
22
|
+
verify?: string;
|
|
23
|
+
/** the raw telemetry body (the line minus the "synth:" prefix), for display. */
|
|
24
|
+
raw?: string;
|
|
25
|
+
}
|
|
26
|
+
/** Extract the `synth:` line out of a decision's evidence and parse its `k=v` fields. */
|
|
27
|
+
export declare function parseSynth(evidence: string[] | undefined): SynthInfo;
|
|
28
|
+
/** Grounded-ness at/above which a Critic-verified draft is a "quick yes". */
|
|
29
|
+
export declare const READY_MIN_GROUNDED = 0.7;
|
|
30
|
+
/** Whether a decision is an un-vouched draft still awaiting a human — the ONLY thing
|
|
31
|
+
* the review path surfaces under the auto-trust model.
|
|
32
|
+
*
|
|
33
|
+
* Low confidence NO LONGER makes a draft: captured memory is trusted-advisory the
|
|
34
|
+
* moment it lands (status `accepted`, source `llm_draft`), so it grounds and ranks
|
|
35
|
+
* but never nags. Only a DELIBERATE, not-yet-human-vouched `proposed` record — an
|
|
36
|
+
* explicit roadmap/intent entry a human hasn't confirmed — counts as a review draft.
|
|
37
|
+
* (Enforcement authority is granted INLINE, not by draining a background queue.) */
|
|
38
|
+
export declare function isReviewDraft(d: Decision): boolean;
|
|
39
|
+
export interface ReviewItem {
|
|
40
|
+
d: Decision;
|
|
41
|
+
synth: SynthInfo;
|
|
42
|
+
verified: boolean;
|
|
43
|
+
}
|
|
44
|
+
export interface ReviewQueue {
|
|
45
|
+
ready: ReviewItem[];
|
|
46
|
+
scrutiny: ReviewItem[];
|
|
47
|
+
}
|
|
48
|
+
/** A draft is "ready to confirm" only when the Critic actually audited it (source
|
|
49
|
+
* includes "verified") AND judged it well-grounded. A high confidence number alone
|
|
50
|
+
* is NOT enough — an un-audited draft always needs human eyes. */
|
|
51
|
+
export declare function isReady(d: Decision, synth: SynthInfo, minGrounded?: number): boolean;
|
|
52
|
+
/** Split review drafts into ready-to-confirm (best-grounded first) and needs-scrutiny
|
|
53
|
+
* (lowest-confidence first). A draft is never in both groups. */
|
|
54
|
+
export declare function partitionReview(drafts: Decision[], minGrounded?: number): ReviewQueue;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type RepoFileReader = (file: string) => string | null;
|
|
2
|
+
export type RepoFileBufferReader = (file: string) => Buffer | null;
|
|
3
|
+
/** Automatic repository scans are a convenience boundary, not a license to
|
|
4
|
+
* materialize arbitrarily large tracked blobs in memory. Eight MiB is well
|
|
5
|
+
* above ordinary source-file sizes while keeping one malicious/generated file
|
|
6
|
+
* from becoming an unbounded descriptor read. */
|
|
7
|
+
export declare const MAX_REPO_SOURCE_FILE_BYTES: number;
|
|
8
|
+
export interface RepoFileReaderOptions {
|
|
9
|
+
maxBytes?: number;
|
|
10
|
+
}
|
|
11
|
+
/** Build a no-follow reader for automatic repository scanners. A Git-tracked
|
|
12
|
+
* symlink still appears in `git ls-files`; following it can copy host data into
|
|
13
|
+
* generated memory or reports. This reader accepts only one unchanged regular
|
|
14
|
+
* file beneath the canonical repository root and reads through the descriptor
|
|
15
|
+
* whose identity was checked. */
|
|
16
|
+
export declare function createRepoFileBufferReader(root: string, options?: RepoFileReaderOptions): RepoFileBufferReader;
|
|
17
|
+
/** Text facade for parsers and legacy callers. Security-sensitive identities
|
|
18
|
+
* should hash the raw bytes returned by createRepoFileBufferReader first, since
|
|
19
|
+
* distinct invalid UTF-8 sequences can decode to the same replacement text. */
|
|
20
|
+
export declare function createRepoFileReader(root: string, options?: RepoFileReaderOptions): RepoFileReader;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
type DatabaseSync = import("node:sqlite").DatabaseSync;
|
|
2
|
+
export type ServedEvent = "served" | "refreshed";
|
|
3
|
+
export interface ServedEntry {
|
|
4
|
+
event: ServedEvent;
|
|
5
|
+
/** decisions | constraints | bugs | findings */
|
|
6
|
+
kind: string;
|
|
7
|
+
record_id: string;
|
|
8
|
+
/** what the delivery grounded: a repo-relative file, or a moment like "(subagent:Explore)" */
|
|
9
|
+
target: string;
|
|
10
|
+
session_id?: string;
|
|
11
|
+
rank?: number;
|
|
12
|
+
delivery_reason?: string;
|
|
13
|
+
provenance_status?: string;
|
|
14
|
+
token_cost?: number;
|
|
15
|
+
delivery_profile?: string;
|
|
16
|
+
ranking_policy?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ServedRow {
|
|
19
|
+
record_id: string;
|
|
20
|
+
kind: string;
|
|
21
|
+
serves: number;
|
|
22
|
+
refreshes: number;
|
|
23
|
+
last_at: string;
|
|
24
|
+
best_rank: number | null;
|
|
25
|
+
average_token_cost: number | null;
|
|
26
|
+
}
|
|
27
|
+
export interface ServedReceipt {
|
|
28
|
+
at: string;
|
|
29
|
+
session_id: string | null;
|
|
30
|
+
event: ServedEvent;
|
|
31
|
+
kind: string;
|
|
32
|
+
record_id: string;
|
|
33
|
+
target: string;
|
|
34
|
+
rank: number | null;
|
|
35
|
+
delivery_reason: string | null;
|
|
36
|
+
provenance_status: string | null;
|
|
37
|
+
token_cost: number | null;
|
|
38
|
+
delivery_profile: string | null;
|
|
39
|
+
ranking_policy: string | null;
|
|
40
|
+
}
|
|
41
|
+
export interface ServedSummary {
|
|
42
|
+
total: number;
|
|
43
|
+
distinct_records: number;
|
|
44
|
+
distinct_sessions: number;
|
|
45
|
+
first_at: string | null;
|
|
46
|
+
last_at: string | null;
|
|
47
|
+
rows: ServedRow[];
|
|
48
|
+
recent: ServedReceipt[];
|
|
49
|
+
}
|
|
50
|
+
/** Shared observation ledger. Explicit report operations surface failures; only
|
|
51
|
+
* passive delivery/hook callers may degrade to best-effort recording. */
|
|
52
|
+
export declare function withServedDatabase<T>(root: string, run: (db: DatabaseSync) => T): T;
|
|
53
|
+
/** Append delivery receipts. Never throws — a receipt must never cost a delivery. */
|
|
54
|
+
export declare function recordServed(root: string, entries: readonly ServedEntry[]): void;
|
|
55
|
+
/** The ledger, aggregated per record. Never throws; an unreadable ledger reads as empty. */
|
|
56
|
+
export declare function servedSummary(root: string): ServedSummary;
|
|
57
|
+
export {};
|
package/dist/core/served.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { createRequire } from "node:module";
|
|
16
16
|
import { mkdirSync } from "node:fs";
|
|
17
17
|
import { join } from "node:path";
|
|
18
|
+
import { assertReportPath } from "./taskReportPaths.js";
|
|
18
19
|
/** Load node:sqlite while swallowing ONLY its ExperimentalWarning — the same
|
|
19
20
|
* discipline as src/store/db.ts: this module rides the hook into every CLI
|
|
20
21
|
* invocation, and Hunch's stderr reaches humans, hooks, and MCP clients. A
|
|
@@ -71,6 +72,7 @@ function openServedDb(root) {
|
|
|
71
72
|
const dir = join(root, ".hunch-cache");
|
|
72
73
|
mkdirSync(dir, { recursive: true });
|
|
73
74
|
const db = new sqlite.DatabaseSync(join(dir, "served.db"));
|
|
75
|
+
db.exec("PRAGMA busy_timeout = 100");
|
|
74
76
|
db.exec(`CREATE TABLE IF NOT EXISTS served (
|
|
75
77
|
at TEXT NOT NULL,
|
|
76
78
|
session TEXT,
|
|
@@ -83,6 +85,18 @@ function openServedDb(root) {
|
|
|
83
85
|
ensureReceiptColumns(db);
|
|
84
86
|
return db;
|
|
85
87
|
}
|
|
88
|
+
/** Shared observation ledger. Explicit report operations surface failures; only
|
|
89
|
+
* passive delivery/hook callers may degrade to best-effort recording. */
|
|
90
|
+
export function withServedDatabase(root, run) {
|
|
91
|
+
assertReportPath(root, ".hunch-cache", "served.db");
|
|
92
|
+
const db = openServedDb(root);
|
|
93
|
+
try {
|
|
94
|
+
return run(db);
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
db.close();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
86
100
|
/** Append delivery receipts. Never throws — a receipt must never cost a delivery. */
|
|
87
101
|
export function recordServed(root, entries) {
|
|
88
102
|
if (!entries.length)
|