@davesheffer/hunch 1.31.1 → 1.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- 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 +606 -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 +128 -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/hookObservations.d.ts +9 -0
- package/dist/core/hookObservations.js +33 -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 +28 -0
- package/dist/core/taskReportEvidence.js +272 -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/health.js +32 -2
- 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 +188 -0
- package/dist/mcp/taskReportTools.js +147 -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 +79 -0
- package/dist/taskReports.js +69 -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,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic repair for a decision's commit provenance after a squash-merge.
|
|
3
|
+
*
|
|
4
|
+
* A squash-merge produces one new commit whose parent is the pre-merge target
|
|
5
|
+
* tip — the original per-commit SHAs it squashed are never ancestors of it.
|
|
6
|
+
* This module matches an orphaned decision to the ONE newly-merged commit
|
|
7
|
+
* whose changed files are a superset of the decision's related_files. Zero or
|
|
8
|
+
* multiple qualifying candidates means "don't guess" — same discipline as
|
|
9
|
+
* repair.ts's rename-repair.
|
|
10
|
+
*/
|
|
11
|
+
import { createHash } from "node:crypto";
|
|
12
|
+
import { replaceExact } from "./refrepair.js";
|
|
13
|
+
/** Bind review to the ordered queue and which targets are currently resolvable.
|
|
14
|
+
* Queue order matters: duplicate decision ids use first-match selection. */
|
|
15
|
+
export function commitRepairReviewHash(queued, withheld = new Set()) {
|
|
16
|
+
const snapshot = queued.map((r) => ({ id: r.id, from: r.from, to: r.to, withheld: withheld.has(r) }));
|
|
17
|
+
return `sha256:${createHash("sha256").update(JSON.stringify(snapshot)).digest("hex")}`;
|
|
18
|
+
}
|
|
19
|
+
/** A scope entry is exact (usable as a match key) only when it contains no glob syntax. */
|
|
20
|
+
function isExactPath(entry) {
|
|
21
|
+
return !!entry && !/[*?[\]{}]/.test(entry);
|
|
22
|
+
}
|
|
23
|
+
/** Live decisions whose cited commit still exists here but is no longer an
|
|
24
|
+
* ancestor of the current tip. Only "orphaned" qualifies: a commit that
|
|
25
|
+
* doesn't resolve at all ("unresolvable") is out of repair scope, and a git
|
|
26
|
+
* failure ("unknown") must never be mistaken for repair-eligible. */
|
|
27
|
+
export function orphanedCommitDecisions(decisions, status) {
|
|
28
|
+
return decisions.filter((d) => {
|
|
29
|
+
if (d.status === "superseded" || d.status === "rejected")
|
|
30
|
+
return false;
|
|
31
|
+
if (!d.commit)
|
|
32
|
+
return false;
|
|
33
|
+
return status(d.commit) === "orphaned";
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/** Match each orphaned decision to exactly one candidate whose changed files are
|
|
37
|
+
* a superset of the decision's related_files (non-empty, no globs). */
|
|
38
|
+
export function planCommitRepair(orphaned, candidates) {
|
|
39
|
+
const rewrites = [];
|
|
40
|
+
for (const d of orphaned) {
|
|
41
|
+
const files = (d.related_files ?? []).filter(isExactPath);
|
|
42
|
+
if (!files.length)
|
|
43
|
+
continue;
|
|
44
|
+
const matches = candidates.filter((c) => files.every((f) => c.files.includes(f)));
|
|
45
|
+
if (matches.length !== 1)
|
|
46
|
+
continue; // zero or ambiguous: never guess
|
|
47
|
+
rewrites.push({ id: d.id, from: d.commit, to: matches[0].sha });
|
|
48
|
+
}
|
|
49
|
+
return { rewrites, records: [...new Set(rewrites.map((r) => r.id))] };
|
|
50
|
+
}
|
|
51
|
+
/** Whether a queued rewrite is still worth ASKING about: the decision it
|
|
52
|
+
* names still exists, still cites the commit the entry expects to replace (a
|
|
53
|
+
* decision that already moved on would make repairDecisionCommit's own
|
|
54
|
+
* stale-plan bail refuse it), and hasn't since been superseded/rejected —
|
|
55
|
+
* same exclusion as orphanedCommitDecisions, since repairing dead history's
|
|
56
|
+
* provenance isn't worth asking about. Backs the read-only escalation
|
|
57
|
+
* surface only (commitRepairEscalations) — absence-means-not-askable is
|
|
58
|
+
* safe there because it self-heals the moment visibility returns.
|
|
59
|
+
* repair-provenance itself does NOT use this: it reads the full store and
|
|
60
|
+
* may legitimately list (dry-run) or leave queued (apply) an entry this
|
|
61
|
+
* predicate would call not-live, so the escalation surface and the CLI can
|
|
62
|
+
* disagree about the same entry — see deadRewrites and resolvedRewriteIds
|
|
63
|
+
* for the CLI's own, looser-on-purpose reasoning. */
|
|
64
|
+
export function liveRewrites(queued, decisions) {
|
|
65
|
+
const byId = new Map(decisions.map((d) => [d.id, d]));
|
|
66
|
+
return queued.filter((r) => {
|
|
67
|
+
const d = byId.get(r.id);
|
|
68
|
+
return !!d && d.commit === r.from && d.status !== "superseded" && d.status !== "rejected";
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/** Entries a decision has demonstrably outgrown: the decision IS present in
|
|
72
|
+
* `decisions`, and it either moved on from `from` or has since been
|
|
73
|
+
* superseded/rejected. An id this list can't see is deliberately NOT
|
|
74
|
+
* included — absence is a property of the READER (a branch checkout that
|
|
75
|
+
* predates the decision, an unmounted private overlay), not proof the match
|
|
76
|
+
* is stale. This predicate backs a DESTRUCTIVE prune (repair-provenance
|
|
77
|
+
* deletes what it returns from the queue file); repairqueue.ts's own
|
|
78
|
+
* docstring is why that matters — the queue is the one durable record of a
|
|
79
|
+
* match once ORIG_HEAD moves on and the matched-away commit can be gc'd, so
|
|
80
|
+
* deleting an entry on a merely-absent id would destroy it unrecoverably.
|
|
81
|
+
* Contrast liveRewrites, whose absence-means-not-askable rule is safe on
|
|
82
|
+
* the read-only escalation surface, which self-heals once visibility
|
|
83
|
+
* returns.
|
|
84
|
+
*
|
|
85
|
+
* Caveat: "demonstrably" is only as strong as this run's view of
|
|
86
|
+
* `decisions`, which comes from the same git-tracked, branch-dependent
|
|
87
|
+
* files that motivate treating ABSENCE as inconclusive. A decision whose
|
|
88
|
+
* `commit`/`status` genuinely differ between branches (e.g. a repair
|
|
89
|
+
* already applied and committed on one branch, checked out here from a
|
|
90
|
+
* branch that predates it) could still read as "moved on" when it hasn't,
|
|
91
|
+
* from this branch's perspective. Far narrower than the absence case this
|
|
92
|
+
* function exists to fix, and not addressed here. */
|
|
93
|
+
export function deadRewrites(queued, decisions) {
|
|
94
|
+
const byId = new Map(decisions.map((d) => [d.id, d]));
|
|
95
|
+
return queued.filter((r) => {
|
|
96
|
+
const d = byId.get(r.id);
|
|
97
|
+
return !!d && (d.commit !== r.from || d.status === "superseded" || d.status === "rejected");
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
/** Among `toApply` (the queued/matched candidates this run is about to act
|
|
101
|
+
* on), the ids repair-provenance may treat as RESOLVED once it's done: the
|
|
102
|
+
* decision is present in `decisions` this run, whether or not
|
|
103
|
+
* repairDecisionCommit actually changed it (a present decision that already
|
|
104
|
+
* moved on is "resolved" too — repairDecisionCommit's own bail refused it,
|
|
105
|
+
* and there is nothing more this run can do about it). An id whose decision
|
|
106
|
+
* is NOT present is never resolved — same reasoning as deadRewrites:
|
|
107
|
+
* absence is the reader's transient view, not proof the match is settled,
|
|
108
|
+
* so it must stay queued for a run where the decision is visible again. */
|
|
109
|
+
export function resolvedRewriteIds(toApply, decisions) {
|
|
110
|
+
const seen = new Set(decisions.map((d) => d.id));
|
|
111
|
+
return new Set(toApply.filter((r) => seen.has(r.id)).map((r) => r.id));
|
|
112
|
+
}
|
|
113
|
+
/** Remove any match whose exact {id, from, to} triple was already tombstoned
|
|
114
|
+
* by an earlier `--drop` — otherwise a later merge that re-derives the
|
|
115
|
+
* identical candidate would re-queue exactly what the human rejected. A
|
|
116
|
+
* match sharing {id, from} but proposing a different `to` is unaffected: it
|
|
117
|
+
* is a different proposal, not the rejected one.
|
|
118
|
+
*
|
|
119
|
+
* Preserves object identity for every surviving entry (a plain filter, never
|
|
120
|
+
* a clone or a rebuild) — repair-provenance's own action relies on this to
|
|
121
|
+
* diff its swept-vs-active queue by reference (`queue.filter(r =>
|
|
122
|
+
* !active.includes(r))`) rather than re-spelling the {id, from, to} key a
|
|
123
|
+
* third time. Do not change this to normalize or reconstruct entries
|
|
124
|
+
* without updating that call site too. */
|
|
125
|
+
export function withoutDropped(rewrites, dropped) {
|
|
126
|
+
if (!dropped.length)
|
|
127
|
+
return [...rewrites];
|
|
128
|
+
const tombstoned = new Set(dropped.map((t) => `${t.id}\0${t.from}\0${t.to}`));
|
|
129
|
+
return rewrites.filter((r) => !tombstoned.has(`${r.id}\0${r.from}\0${r.to}`));
|
|
130
|
+
}
|
|
131
|
+
/** Append newly-dropped {id, from, to} triples to the tombstone list,
|
|
132
|
+
* deduped — same append-only, dedupe-by-key shape as mergeRewrites. */
|
|
133
|
+
export function addDropped(newly, existing) {
|
|
134
|
+
const seen = new Set(existing.map((t) => `${t.id}\0${t.from}\0${t.to}`));
|
|
135
|
+
const additions = newly.filter((t) => !seen.has(`${t.id}\0${t.from}\0${t.to}`));
|
|
136
|
+
return [...existing, ...additions];
|
|
137
|
+
}
|
|
138
|
+
/** Combine a freshly-computed plan's rewrites with anything already queued
|
|
139
|
+
* (src/core/repairqueue.ts) from an earlier detection. A fresh match —
|
|
140
|
+
* computed just now, against the current range — overrides a queued one for
|
|
141
|
+
* the same decision; queued entries no longer reachable are simply not
|
|
142
|
+
* repeated by the fresh scan.
|
|
143
|
+
*
|
|
144
|
+
* Overrides by object identity, targeting exactly the one queued entry
|
|
145
|
+
* firstFor (id) would pick — the same first-match rule --drop applies, and
|
|
146
|
+
* the same identity-not-id targeting the dead-entry prune applies (#53; the
|
|
147
|
+
* prune itself removes every provably-dead entry, not just a first match).
|
|
148
|
+
* A corrupted queue file, a hand edit, or a bug upstream could otherwise
|
|
149
|
+
* carry a SECOND entry sharing that id; overriding by id alone would
|
|
150
|
+
* silently destroy that still-queued sibling too, with no tombstone and no
|
|
151
|
+
* way to recover it, even though it was never the entry that would have
|
|
152
|
+
* been applied. Any such sibling is left queued and untouched.
|
|
153
|
+
*
|
|
154
|
+
* How a survivor resolves: the dead-entry prune (deadRewrites), once
|
|
155
|
+
* --apply has moved the decision past the sibling's `from`; or a --drop
|
|
156
|
+
* whose tombstone matches the sibling's exact {id, from, to} — the same
|
|
157
|
+
* --drop that dropped the fresh entry, when the sibling happens to share
|
|
158
|
+
* its triple (the drop's own re-sweep, withoutDropped, catches it too), a
|
|
159
|
+
* second explicit --drop otherwise. NOT a later fresh detection: by this
|
|
160
|
+
* same first-match rule it always overrides the fresh entry sitting ahead
|
|
161
|
+
* of it, never the sibling. */
|
|
162
|
+
export function mergeRewrites(fresh, queued) {
|
|
163
|
+
const overridden = new Set();
|
|
164
|
+
for (const r of fresh) {
|
|
165
|
+
const first = firstFor(queued, r.id);
|
|
166
|
+
if (first)
|
|
167
|
+
overridden.add(first);
|
|
168
|
+
}
|
|
169
|
+
return [...fresh, ...queued.filter((r) => !overridden.has(r))];
|
|
170
|
+
}
|
|
171
|
+
/** Partition the entries --apply is about to act on by whether their proposed
|
|
172
|
+
* `to` commit actually exists in this repository. `existing` is
|
|
173
|
+
* `commitsExist`'s result over every `to` in `toApply`: `null` means the
|
|
174
|
+
* check itself failed to run (not a git repo, git missing, timeout) and is
|
|
175
|
+
* treated as fail-open, same discipline as drift.ts's own use of
|
|
176
|
+
* commitsExist — nothing is withheld just because the check couldn't run.
|
|
177
|
+
*
|
|
178
|
+
* A corrupted queue file, a hand-edited entry, or a bug upstream could
|
|
179
|
+
* otherwise get a `to` that never resolves to a real commit written
|
|
180
|
+
* straight into a decision's `commit` field and provenance evidence, then
|
|
181
|
+
* auto-committed into shared team memory. `withheld` entries must stay
|
|
182
|
+
* queued (never deleted, never passed to repairDecisionCommit) — the queue
|
|
183
|
+
* file is the one durable record of the match, same reasoning as
|
|
184
|
+
* deadRewrites/resolvedRewriteIds.
|
|
185
|
+
*
|
|
186
|
+
* Both returned arrays preserve object identity (never clones or rebuilds
|
|
187
|
+
* an entry) — the CLI's queue sweep and its "still queued" reporting both
|
|
188
|
+
* key a `Set` off the exact objects in `withheld`, by reference, precisely
|
|
189
|
+
* because a corrupted queue file can carry two entries sharing an id (one
|
|
190
|
+
* resolvable, one not): an id alone can't tell them apart. Do not change
|
|
191
|
+
* this to normalize or reconstruct entries without updating those call
|
|
192
|
+
* sites too — same caveat withoutDropped's own docstring carries. */
|
|
193
|
+
export function withheldForUnresolvableTo(toApply, existing) {
|
|
194
|
+
if (existing === null)
|
|
195
|
+
return { applicable: [...toApply], withheld: [] };
|
|
196
|
+
const applicable = [];
|
|
197
|
+
const withheld = [];
|
|
198
|
+
for (const r of toApply)
|
|
199
|
+
(existing.has(r.to) ? applicable : withheld).push(r);
|
|
200
|
+
return { applicable, withheld };
|
|
201
|
+
}
|
|
202
|
+
/** The one rule for which entry wins when more than one shares a decision id
|
|
203
|
+
* (a corrupted queue file, a hand edit, or a bug upstream): first match, by
|
|
204
|
+
* construction. Every caller goes through here so no two can independently
|
|
205
|
+
* drift on which entry "won" — this file's own duplicate-id queue handling
|
|
206
|
+
* has drifted between call sites three times already (see withoutDropped's,
|
|
207
|
+
* withheldForUnresolvableTo's, and mergeRewrites' own docstrings). */
|
|
208
|
+
export function firstFor(entries, id) {
|
|
209
|
+
return entries.find((r) => r.id === id);
|
|
210
|
+
}
|
|
211
|
+
/** pickRewrite is firstFor scoped to a plan's own rewrites (planCommitRepair
|
|
212
|
+
* itself never produces same-id duplicates, but a plan carrying them isn't
|
|
213
|
+
* ruled out here — see firstFor). repairDecisionCommit uses this to decide
|
|
214
|
+
* what to WRITE; a caller that needs to know which entry WOULD be picked
|
|
215
|
+
* without writing anything (the CLI's --apply summary and queue sweep)
|
|
216
|
+
* calls this same function, so the two can never independently drift on
|
|
217
|
+
* which entry "won". */
|
|
218
|
+
export function pickRewrite(plan, id) {
|
|
219
|
+
return firstFor(plan.rewrites, id);
|
|
220
|
+
}
|
|
221
|
+
/** Pure: rewrite `commit` for one decision, and its matching `commit:<sha>`
|
|
222
|
+
* evidence entry too if one is present (replaceExact is a no-op when the
|
|
223
|
+
* evidence array never cited the old sha) — or return the same reference
|
|
224
|
+
* when the plan doesn't touch it. If the record moved on since the plan was
|
|
225
|
+
* built (its commit no longer equals the plan's `from`), bail entirely
|
|
226
|
+
* rather than applying a now-stale match. */
|
|
227
|
+
export function repairDecisionCommit(d, plan) {
|
|
228
|
+
const mine = pickRewrite(plan, d.id);
|
|
229
|
+
if (!mine || d.commit !== mine.from)
|
|
230
|
+
return d;
|
|
231
|
+
const evidence = replaceExact(d.provenance.evidence, `commit:${mine.from}`, `commit:${mine.to}`);
|
|
232
|
+
return {
|
|
233
|
+
...d,
|
|
234
|
+
commit: mine.to,
|
|
235
|
+
provenance: { ...d.provenance, evidence: evidence.values },
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=commitrepair.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-candidate verdict (roadmap addendum, "evaluate 5 solutions"). Given several
|
|
3
|
+
* candidate refs (branches/commits — e.g. N agent-generated solutions to one task),
|
|
4
|
+
* replay each one's diff against the graph via the SAME deterministic merge-verdict
|
|
5
|
+
* (buildCheckReport + verdict) and RANK them: the candidate that fits the architecture
|
|
6
|
+
* best is the one that trips the fewest in-force invariants, reverses no decisions, and
|
|
7
|
+
* adds the least sprawl. No model in the ranking — it's set-intersection over the graph.
|
|
8
|
+
*/
|
|
9
|
+
import type { HunchStore } from "../store/hunchStore.js";
|
|
10
|
+
export interface CandidateResult {
|
|
11
|
+
ref: string;
|
|
12
|
+
verdict: "block" | "warn" | "pass";
|
|
13
|
+
blocking: number;
|
|
14
|
+
direct: number;
|
|
15
|
+
near: number;
|
|
16
|
+
vetoes: number;
|
|
17
|
+
redundant: number;
|
|
18
|
+
files: number;
|
|
19
|
+
error?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function compareCandidates(store: HunchStore, root: string, base: string, candidates: string[]): CandidateResult[];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { HunchPaths } from "./paths.js";
|
|
2
|
+
/** How firmly the agent lifecycle hook (`hunch hook`) enforces Hunch on edits:
|
|
3
|
+
* off — emit nothing (hook is a no-op).
|
|
4
|
+
* advisory — inject the relevant Hunch slice (decisions/constraints/bugs) as
|
|
5
|
+
* context before the edit. The default: always informs, never blocks.
|
|
6
|
+
* firm — advisory + explicitly flag invariants in the edited file's scope.
|
|
7
|
+
* strict — firm + DENY an edit that hits a BLOCKING invariant (direct or via
|
|
8
|
+
* blast radius), feeding the invariant back as the refusal reason. */
|
|
9
|
+
export type Firmness = "off" | "advisory" | "firm" | "strict";
|
|
10
|
+
export declare const FIRMNESS_LEVELS: readonly Firmness[];
|
|
11
|
+
export declare const DEFAULT_FIRMNESS: Firmness;
|
|
12
|
+
export interface HunchConfig {
|
|
13
|
+
firmness: Firmness;
|
|
14
|
+
}
|
|
15
|
+
export declare function isFirmness(v: unknown): v is Firmness;
|
|
16
|
+
/** Read `.hunch/config.json`. A missing/unparseable file, or an unknown firmness
|
|
17
|
+
* value, falls back to defaults — the hook must NEVER crash an edit over config. */
|
|
18
|
+
export declare function readConfig(paths: HunchPaths): HunchConfig;
|
|
19
|
+
/** Write `.hunch/config.json`, merging `patch` over the current on-disk config. */
|
|
20
|
+
export declare function writeConfig(paths: HunchPaths, patch: Partial<HunchConfig>): HunchConfig;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intent-conformance (the inversion). Today's guards ask "did this diff touch a guarded
|
|
3
|
+
* file?". This asks the deeper question: "does the code, right now, still SATISFY the
|
|
4
|
+
* intent a decision recorded?" — by compiling that intent into a DETERMINISTIC check over
|
|
5
|
+
* the symbol/dependency graph Hunch already builds. "pay must verify the session" becomes
|
|
6
|
+
* `pay` reaches `verifySession`; if the code drifts so it no longer does, the intent is
|
|
7
|
+
* violated even though no diff is in scope. No model — pure graph reachability.
|
|
8
|
+
*
|
|
9
|
+
* Note: reachability is over the unified dependency graph (call / import / depends-on /
|
|
10
|
+
* contains edges), so `calls` and `imports` both mean "must reach"; edge-type precision is
|
|
11
|
+
* a later refinement. The point this proves: code can be checked AGAINST intent.
|
|
12
|
+
*/
|
|
13
|
+
import type { HunchStore } from "../store/hunchStore.js";
|
|
14
|
+
import type { Edge, Symbol as HunchSymbol } from "./types.js";
|
|
15
|
+
export interface ConformanceResult {
|
|
16
|
+
decision: string;
|
|
17
|
+
title: string;
|
|
18
|
+
assert: string;
|
|
19
|
+
subject: string;
|
|
20
|
+
object?: string;
|
|
21
|
+
satisfied: boolean;
|
|
22
|
+
detail: string;
|
|
23
|
+
}
|
|
24
|
+
export type ConformanceGraph = {
|
|
25
|
+
symbols: HunchSymbol[];
|
|
26
|
+
edges: Edge[];
|
|
27
|
+
};
|
|
28
|
+
/** Check every in-force decision's conformance predicates against the CURRENT graph.
|
|
29
|
+
* `.satisfied === false` means the code drifted from the recorded intent. Deterministic.
|
|
30
|
+
* `publicOnly` selects every input at the JSON read boundary so a private decision,
|
|
31
|
+
* symbol, or edge can never influence (or be rendered into) a public CI receipt. */
|
|
32
|
+
export declare function checkConformance(store: HunchStore, opts?: {
|
|
33
|
+
publicOnly?: boolean;
|
|
34
|
+
graph?: ConformanceGraph;
|
|
35
|
+
}): ConformanceResult[];
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** Precise, AST-grounded matching for a constraint's content — the primitive behind
|
|
2
|
+
* "this change actually BREAKS the rule" (dec_… content-matched constraints).
|
|
3
|
+
*
|
|
4
|
+
* A constraint can forbid, in precision order:
|
|
5
|
+
* - deps: an external import (matched against the PARSED import set, so a comment
|
|
6
|
+
* or a string literal that merely names the module can't trip it; a
|
|
7
|
+
* submodule import like "lodash/groupBy" is caught by "lodash").
|
|
8
|
+
* - symbols: an identifier added in scoped code (whole-word, comments stripped).
|
|
9
|
+
* - patterns: a line regex (lint-grade last resort; comments stripped, strings kept).
|
|
10
|
+
*
|
|
11
|
+
* Deciding a violation by CONTENT is verifiable per commit, so a content-matched
|
|
12
|
+
* invariant is immune to file-change "staleness" and keeps its teeth across the file's
|
|
13
|
+
* whole life. The same matcher backs the Veto Guard's tripwires (one matcher, audited
|
|
14
|
+
* once) — see HunchStore.matchTripwire. */
|
|
15
|
+
export interface Forbids {
|
|
16
|
+
deps: string[];
|
|
17
|
+
symbols: string[];
|
|
18
|
+
patterns: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface ForbidMatch {
|
|
21
|
+
tier: "dep" | "symbol" | "pattern";
|
|
22
|
+
evidence: string[];
|
|
23
|
+
}
|
|
24
|
+
/** Walk the precision-first ladder against an analyzed diff/edit: dep (parsed import,
|
|
25
|
+
* exact or submodule) > symbol (whole-word identifier in scoped code) > pattern (scoped
|
|
26
|
+
* regex). Returns the highest-precision match, or null. */
|
|
27
|
+
export declare function matchForbids(f: Forbids, addedDeps: Set<string>, scopedAdded: string[]): ForbidMatch | null;
|
|
28
|
+
/** A constraint's effective forbids: its structured `forbids` plus a legacy `--match`
|
|
29
|
+
* regex folded into the pattern tier (back-compat with v0.35). null when it has none. */
|
|
30
|
+
export declare function effectiveForbids(c: {
|
|
31
|
+
forbids?: Forbids | null;
|
|
32
|
+
match?: string | null;
|
|
33
|
+
}): Forbids | null;
|
|
34
|
+
/** The external import module names on a set of raw lines (for the edit-time hook,
|
|
35
|
+
* which sees proposed lines, not a parsed diff). Relative imports are ignored. */
|
|
36
|
+
export declare function importedDeps(lines: string[]): Set<string>;
|
|
37
|
+
/** Best-effort: derive a forbidden DEP from a natural-language rule like "never import
|
|
38
|
+
* lodash" / "don't use the axios package" — so the seamless capture path (a human
|
|
39
|
+
* correction → enforced constraint) mints a PRECISE matcher, not a scope-only rule that
|
|
40
|
+
* goes stale. Conservative: only fires on an explicit import/require verb + a
|
|
41
|
+
* module-shaped token; returns null otherwise (caller falls back to scope-only). */
|
|
42
|
+
export declare function deriveForbids(rule: string, knownDeps?: readonly string[]): Forbids | null;
|
|
43
|
+
/** The enforceable CODE of an added line: a comment carries no invariant, so the lint-grade
|
|
44
|
+
* symbol/pattern tiers must not fire on it (a `// we avoid lodash` note is not a violation).
|
|
45
|
+
* Strips a line comment, an inline block comment, and a comment-only / JSDoc line — but NOT
|
|
46
|
+
* string literals, since an import specifier (`from "lodash"`) is itself a string.
|
|
47
|
+
* Single-pass and line-local, so a multi-line block-comment BODY line (no marker) is NOT
|
|
48
|
+
* stripped: that residual false-positive is why the DEP tier — gated on the PARSED import
|
|
49
|
+
* set, immune to any comment — is the precise path for "never import X". */
|
|
50
|
+
export declare function matchableCode(line: string): string;
|
|
51
|
+
/** Legacy: compile a constraint's `--match` regex defensively (bad regex → inert). */
|
|
52
|
+
export declare function constraintMatcher(pattern?: string | null): RegExp | null;
|
|
53
|
+
/** True iff any added line's CODE trips a single regex (the v0.35 textual path). */
|
|
54
|
+
export declare function contentViolates(re: RegExp | null, addedLines: string[]): boolean;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Constraint } from "./types.js";
|
|
2
|
+
export declare function looksLikeCorrection(prompt: string | undefined | null): boolean;
|
|
3
|
+
/** One-line nudge appended to the UserPromptSubmit hook context when a prompt
|
|
4
|
+
* reads like a correction — surfaces the write tool so the rule gets ENFORCED,
|
|
5
|
+
* not merely remembered. Client-agnostic (no Claude-only wording). */
|
|
6
|
+
export declare const CORRECTION_NUDGE: string;
|
|
7
|
+
export interface CorrectionInput {
|
|
8
|
+
/** The invariant in the human's words, e.g. "never call the pay-per-token API here". */
|
|
9
|
+
rule: string;
|
|
10
|
+
/** A file the correction was about — scopes the constraint to it (conservative default). */
|
|
11
|
+
scope_hint_file?: string;
|
|
12
|
+
severity?: "advisory" | "warning" | "blocking";
|
|
13
|
+
/** True only when the rule is genuinely repo-wide; required to scope to "**". */
|
|
14
|
+
applies_to_all?: boolean;
|
|
15
|
+
type?: "security" | "performance" | "correctness" | "architecture" | "compliance";
|
|
16
|
+
rationale?: string;
|
|
17
|
+
/** id of the decision this correction derives from, if any. */
|
|
18
|
+
source_decision?: string;
|
|
19
|
+
/** The repo's real dependency names (package.json). When given, a dep matcher is
|
|
20
|
+
* auto-derived ONLY for a dep that actually exists — so a non-dependency phrasing
|
|
21
|
+
* never silently mints a never-firing rule. */
|
|
22
|
+
knownDeps?: string[];
|
|
23
|
+
/** Repo root, used to relativize an ABSOLUTE `scope_hint_file`. Agents naturally
|
|
24
|
+
* produce absolute paths (edit-tool payloads and MCP roots are absolute), but every
|
|
25
|
+
* consumer matches repo-relative paths — so without this an absolute hint mints a
|
|
26
|
+
* scope that can never match. */
|
|
27
|
+
root?: string;
|
|
28
|
+
/** True when a capture token was CONSUMED for this write — proof a grilling interview
|
|
29
|
+
* preceded it. Determines the TIER, never whether the write lands: an un-vouched
|
|
30
|
+
* correction still records immediately and still surfaces at edit time and in CI.
|
|
31
|
+
* Only the authority to DENY waits for a countersign. */
|
|
32
|
+
vouched?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Build the Constraint a correction mints. Pure (caller passes `now`), so the
|
|
36
|
+
* scope/severity policy is testable in isolation. Key safety rule (research
|
|
37
|
+
* risk #2 — the scope footgun): a repo-wide ("**") constraint may only be
|
|
38
|
+
* BLOCKING when the caller explicitly set applies_to_all; otherwise a single
|
|
39
|
+
* mis-scoped correction would deny every edit under strict firmness, so we
|
|
40
|
+
* down-rank it to a warning.
|
|
41
|
+
*/
|
|
42
|
+
export declare function buildCorrectionConstraint(input: CorrectionInput, now: string): Constraint;
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { type ContractAxisOwnerSource } from "./pipeline.js";
|
|
2
|
+
import { type VerifiedEvidenceMap } from "./evidenceMap.js";
|
|
3
|
+
import { type FileFirstDeclarationDiagnostic, type ProgressiveDeclarationPlan } from "./declarationClusters.js";
|
|
4
|
+
/** The contract-owning layer suggested by issue/reproduction prose. */
|
|
5
|
+
export type CorrectionStage = "schema-emission" | "schema-ingestion" | "presentation" | "constraint-definition" | "runtime-policy";
|
|
6
|
+
export interface CorrectionStageCandidate {
|
|
7
|
+
owner: string;
|
|
8
|
+
stage: CorrectionStage;
|
|
9
|
+
lexical_score: number;
|
|
10
|
+
symbol_overlap: number;
|
|
11
|
+
runtime_declaration: boolean;
|
|
12
|
+
type_scaffolding: boolean;
|
|
13
|
+
default_locale: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface AdaptiveCorrectionStageCandidate {
|
|
16
|
+
owner: string;
|
|
17
|
+
stage: CorrectionStage;
|
|
18
|
+
score: number;
|
|
19
|
+
lexical_score: number;
|
|
20
|
+
path_overlap: number;
|
|
21
|
+
symbol_overlap: number;
|
|
22
|
+
component_support: number;
|
|
23
|
+
runtime_declaration: boolean;
|
|
24
|
+
invoked_entrance: boolean;
|
|
25
|
+
generic_entrance: boolean;
|
|
26
|
+
type_scaffolding: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface EvidenceGuidedCorrectionStageCandidate extends AdaptiveCorrectionStageCandidate {
|
|
29
|
+
baseline_rank: number;
|
|
30
|
+
optimized_rank: number;
|
|
31
|
+
evidence: {
|
|
32
|
+
behavior_sensitive_owner: boolean;
|
|
33
|
+
behavior_sensitive_file: boolean;
|
|
34
|
+
target_only_execution: boolean;
|
|
35
|
+
shared_execution: boolean;
|
|
36
|
+
strong_differential_file: boolean;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export declare const EVIDENCE_GUIDED_SHORTLIST_RULE: "guarded-evidence-bridge-v3";
|
|
40
|
+
export interface CorrectionStageOptimizationReceipt {
|
|
41
|
+
version: 3;
|
|
42
|
+
receipt_id: string;
|
|
43
|
+
rule: typeof EVIDENCE_GUIDED_SHORTLIST_RULE;
|
|
44
|
+
applied: boolean;
|
|
45
|
+
reason: "evidence-reordered" | "already-ranked" | "claim-mismatch" | "probe-unverified" | "transfer-rejected-read-only" | "no-actionable-evidence" | "no-sensitive-declaration-resolved";
|
|
46
|
+
evidence_level: VerifiedEvidenceMap["level"];
|
|
47
|
+
probe_authenticated: boolean;
|
|
48
|
+
claim_bound: boolean;
|
|
49
|
+
requested_limit: number;
|
|
50
|
+
evidence_slots: number;
|
|
51
|
+
evidence_strategy: "behavior-sensitive" | "direct-high-contrast-execution" | "guarded-execution-file-peer" | null;
|
|
52
|
+
selected_execution_ratio: number | null;
|
|
53
|
+
selected_static_rank: number | null;
|
|
54
|
+
baseline_candidates: string[];
|
|
55
|
+
optimized_candidates: string[];
|
|
56
|
+
promoted_candidates: string[];
|
|
57
|
+
displaced_candidates: string[];
|
|
58
|
+
behavior_sensitive_files: string[];
|
|
59
|
+
strong_differential_files: string[];
|
|
60
|
+
exact_owner_enabled: false;
|
|
61
|
+
}
|
|
62
|
+
export interface CorrectionStageDiagnostic {
|
|
63
|
+
stage: CorrectionStage;
|
|
64
|
+
likely_file: string | null;
|
|
65
|
+
candidates: Array<CorrectionStageCandidate | AdaptiveCorrectionStageCandidate | EvidenceGuidedCorrectionStageCandidate>;
|
|
66
|
+
file_first_declaration_clusters: FileFirstDeclarationDiagnostic;
|
|
67
|
+
progressive_inspection: ProgressiveDeclarationPlan;
|
|
68
|
+
exact_owner_enabled: false;
|
|
69
|
+
optimization: CorrectionStageOptimizationReceipt | null;
|
|
70
|
+
calibration: {
|
|
71
|
+
holdout_tasks: 11;
|
|
72
|
+
likely_file_hits: 9;
|
|
73
|
+
top_five_hits: 8;
|
|
74
|
+
};
|
|
75
|
+
cross_repository_transfer: {
|
|
76
|
+
repositories: readonly ["jquense/yup", "sinclairzx81/typebox"];
|
|
77
|
+
holdout_tasks: 16;
|
|
78
|
+
likely_file_hits: 0;
|
|
79
|
+
top_five_hits: 0;
|
|
80
|
+
decision: "rejected";
|
|
81
|
+
};
|
|
82
|
+
adaptive_transfer: {
|
|
83
|
+
repositories: readonly ["arktypeio/arktype", "typestack/class-validator"];
|
|
84
|
+
scorable_tasks: 11;
|
|
85
|
+
likely_file_hits: 8;
|
|
86
|
+
top_five_hits: 9;
|
|
87
|
+
exact_symbol_hits: 7;
|
|
88
|
+
decision: "promoted-diagnostic";
|
|
89
|
+
};
|
|
90
|
+
adaptive_replication: {
|
|
91
|
+
repositories: readonly ["trpc/trpc", "elysiajs/elysia"];
|
|
92
|
+
scorable_tasks: 11;
|
|
93
|
+
likely_file_hits: 4;
|
|
94
|
+
top_five_hits: 5;
|
|
95
|
+
exact_symbol_hits: 4;
|
|
96
|
+
decision: "failed-replication";
|
|
97
|
+
};
|
|
98
|
+
optimization_policy: typeof CORRECTION_OPTIMIZATION_POLICY;
|
|
99
|
+
}
|
|
100
|
+
export declare const CORRECTION_STAGE_CANDIDATE_LIMIT = 5;
|
|
101
|
+
export declare const EVIDENCE_GUIDED_SLOT_LIMIT = 3;
|
|
102
|
+
export declare const EVIDENCE_GUIDED_BASELINE_FLOOR = 2;
|
|
103
|
+
export declare const EXECUTION_GUIDED_SLOT_LIMIT = 1;
|
|
104
|
+
export declare const EXECUTION_GUIDED_BASELINE_FLOOR = 4;
|
|
105
|
+
export declare const EXECUTION_DIRECT_RATIO_MIN = 4;
|
|
106
|
+
export declare const EXECUTION_DIRECT_STATIC_RANK_MAX = 20;
|
|
107
|
+
export declare const EXECUTION_FILE_RATIO_MIN = 2;
|
|
108
|
+
export declare const EXECUTION_FILE_STATIC_RANK_MAX = 10;
|
|
109
|
+
export declare const CORRECTION_STAGE_CALIBRATION: {
|
|
110
|
+
readonly holdout_tasks: 11;
|
|
111
|
+
readonly likely_file_hits: 9;
|
|
112
|
+
readonly top_five_hits: 8;
|
|
113
|
+
};
|
|
114
|
+
export declare const CORRECTION_STAGE_TRANSFER: {
|
|
115
|
+
readonly repositories: readonly ["jquense/yup", "sinclairzx81/typebox"];
|
|
116
|
+
readonly holdout_tasks: 16;
|
|
117
|
+
readonly likely_file_hits: 0;
|
|
118
|
+
readonly top_five_hits: 0;
|
|
119
|
+
readonly decision: "rejected";
|
|
120
|
+
};
|
|
121
|
+
export declare const ADAPTIVE_CORRECTION_STAGE_TRANSFER: {
|
|
122
|
+
readonly repositories: readonly ["arktypeio/arktype", "typestack/class-validator"];
|
|
123
|
+
readonly scorable_tasks: 11;
|
|
124
|
+
readonly likely_file_hits: 8;
|
|
125
|
+
readonly top_five_hits: 9;
|
|
126
|
+
readonly exact_symbol_hits: 7;
|
|
127
|
+
readonly decision: "promoted-diagnostic";
|
|
128
|
+
};
|
|
129
|
+
export declare const ADAPTIVE_CORRECTION_STAGE_REPLICATION: {
|
|
130
|
+
readonly repositories: readonly ["trpc/trpc", "elysiajs/elysia"];
|
|
131
|
+
readonly scorable_tasks: 11;
|
|
132
|
+
readonly likely_file_hits: 4;
|
|
133
|
+
readonly top_five_hits: 5;
|
|
134
|
+
readonly exact_symbol_hits: 4;
|
|
135
|
+
readonly decision: "failed-replication";
|
|
136
|
+
};
|
|
137
|
+
export declare const CORRECTION_OPTIMIZATION_POLICY: {
|
|
138
|
+
readonly active: readonly [{
|
|
139
|
+
readonly mechanism: "repository-adaptive-ranking";
|
|
140
|
+
readonly verdict: "promote-adaptive-diagnostic";
|
|
141
|
+
}, {
|
|
142
|
+
readonly mechanism: "flat-file-anchored-semantic-clusters";
|
|
143
|
+
readonly verdict: "promote-flat-file-anchored-clusters-v3";
|
|
144
|
+
}];
|
|
145
|
+
readonly advisory_only: readonly [{
|
|
146
|
+
readonly mechanism: "static-stage-shortlist";
|
|
147
|
+
readonly verdict: "retain-diagnostic-stage-shortlist";
|
|
148
|
+
}, {
|
|
149
|
+
readonly mechanism: "progressive-inspection-budget";
|
|
150
|
+
readonly verdict: "retain-efficiency-advisory-v4";
|
|
151
|
+
}];
|
|
152
|
+
readonly disabled: readonly [{
|
|
153
|
+
readonly mechanism: "fixed-repository-stage-router";
|
|
154
|
+
readonly verdict: "reject-cross-repository-transfer";
|
|
155
|
+
}, {
|
|
156
|
+
readonly mechanism: "score-gap-confidence";
|
|
157
|
+
readonly verdict: "reject-shortlist-evidence";
|
|
158
|
+
}, {
|
|
159
|
+
readonly mechanism: "cross-view-confidence";
|
|
160
|
+
readonly verdict: "reject-cross-view-evidence";
|
|
161
|
+
}, {
|
|
162
|
+
readonly mechanism: "causal-slot-owner";
|
|
163
|
+
readonly verdict: "reject-causal-slot";
|
|
164
|
+
}, {
|
|
165
|
+
readonly mechanism: "causal-intervention-owner";
|
|
166
|
+
readonly verdict: "reject-causal-intervention-owner";
|
|
167
|
+
}, {
|
|
168
|
+
readonly mechanism: "evidence-guided-reordering";
|
|
169
|
+
readonly verdict: "reject-guarded-evidence-bridge-v3";
|
|
170
|
+
}, {
|
|
171
|
+
readonly mechanism: "product-source-filter";
|
|
172
|
+
readonly verdict: "reject-development-v5-one-loss";
|
|
173
|
+
}, {
|
|
174
|
+
readonly mechanism: "one-hop-relationship-expansion";
|
|
175
|
+
readonly verdict: "reject-development-v5-no-lift";
|
|
176
|
+
}, {
|
|
177
|
+
readonly mechanism: "same-file-frontier-replacement";
|
|
178
|
+
readonly verdict: "reject-development-v5-three-losses";
|
|
179
|
+
}, {
|
|
180
|
+
readonly mechanism: "additive-same-file-frontier";
|
|
181
|
+
readonly verdict: "reject-additive-frontier-v5-no-fresh-rescue";
|
|
182
|
+
}];
|
|
183
|
+
readonly exact_owner_policy: "disabled";
|
|
184
|
+
readonly per_case_confidence: "disabled";
|
|
185
|
+
};
|
|
186
|
+
/** Classify the layer that owns the broken contract, not the public API through
|
|
187
|
+
* which the symptom happened to surface. This is deterministic and read-only. */
|
|
188
|
+
export declare function inferIssueCorrectionStage(issueValue: unknown): CorrectionStage;
|
|
189
|
+
/** Repository paths that commonly implement each correction stage. Exported so
|
|
190
|
+
* safe source collection can prioritize the relevant layer in very large repos. */
|
|
191
|
+
export declare function correctionStagePathPattern(stage: CorrectionStage, issueValue: unknown): RegExp;
|
|
192
|
+
/** Return a stage-constrained declaration ranking. Public APIs invoked by the
|
|
193
|
+
* reproduction are treated as symptom entrances and excluded whenever deeper
|
|
194
|
+
* candidates exist in the selected stage. */
|
|
195
|
+
export declare function rankIssueCorrectionStageCandidates(issueValue: unknown, sources: ContractAxisOwnerSource[]): CorrectionStageCandidate[];
|
|
196
|
+
/** Reserve a bounded portion of a shortlist for declarations proven to affect
|
|
197
|
+
* the same authenticated behavior. File peers are included because the held
|
|
198
|
+
* intervention experiments localized files more reliably than exact owners. */
|
|
199
|
+
export declare function reserveEvidenceGuidedOwners(baselineOwnersValue: string[], rankedOwnersValue: string[], evidenceMap: VerifiedEvidenceMap, requestedLimit?: number): string[];
|
|
200
|
+
export interface GuardedExecutionBridgeSelection {
|
|
201
|
+
owner: string;
|
|
202
|
+
path: string;
|
|
203
|
+
strategy: "direct-high-contrast-execution" | "guarded-execution-file-peer";
|
|
204
|
+
execution_ratio: number;
|
|
205
|
+
static_rank: number;
|
|
206
|
+
}
|
|
207
|
+
/** Combine execution contrast with static plausibility. Files already covered
|
|
208
|
+
* by the baseline are ignored, generic instrumentation files are excluded,
|
|
209
|
+
* and only the final shortlist slot is eligible. Runtime evidence proposes a
|
|
210
|
+
* bounded hypothesis; it never becomes an exact-owner claim. */
|
|
211
|
+
export declare function selectGuardedExecutionBridge(baselineOwnersValue: string[], rankedOwnersValue: string[], evidenceMap: VerifiedEvidenceMap, requestedLimit?: number): GuardedExecutionBridgeSelection | null;
|
|
212
|
+
export declare function reserveExecutionGuidedFileOwner(baselineOwnersValue: string[], rankedOwnersValue: string[], evidenceMap: VerifiedEvidenceMap, requestedLimit?: number): string[];
|
|
213
|
+
/** Repository-adaptive replacement for fixed Zod path routing. It discovers
|
|
214
|
+
* issue vocabulary in this repository's own paths and symbols, adds local
|
|
215
|
+
* component consensus, and removes an invoked facade only when a deeper
|
|
216
|
+
* repository-native candidate is available. */
|
|
217
|
+
export declare function rankIssueAdaptiveCorrectionCandidates(issueValue: unknown, sources: ContractAxisOwnerSource[]): AdaptiveCorrectionStageCandidate[];
|
|
218
|
+
export declare function optimizeIssueCorrectionCandidates(issueValue: unknown, sources: ContractAxisOwnerSource[], evidenceValue: unknown, requestedLimit?: number): {
|
|
219
|
+
candidates: EvidenceGuidedCorrectionStageCandidate[];
|
|
220
|
+
receipt: CorrectionStageOptimizationReceipt;
|
|
221
|
+
evidence_map: VerifiedEvidenceMap;
|
|
222
|
+
};
|
|
223
|
+
export declare function diagnoseIssueCorrectionStage(issueValue: unknown, sources: ContractAxisOwnerSource[], requestedLimit?: number, evidenceValue?: unknown): CorrectionStageDiagnostic;
|
|
224
|
+
export declare function formatCorrectionStageDiagnostic(diagnostic: CorrectionStageDiagnostic): string;
|