@isaacriehm/cairn-core 0.2.0 → 0.3.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/dist/.tsbuildinfo +1 -1
- package/dist/claude/runner.d.ts +1 -1
- package/dist/claude/runner.js +62 -1
- package/dist/claude/runner.js.map +1 -1
- package/dist/claude/types.d.ts +14 -7
- package/dist/claude/types.js +5 -7
- package/dist/claude/types.js.map +1 -1
- package/dist/context/index.d.ts +4 -4
- package/dist/context/index.js +3 -4
- package/dist/context/index.js.map +1 -1
- package/dist/context/spec-delta.js +2 -3
- package/dist/context/spec-delta.js.map +1 -1
- package/dist/context/task-summary.d.ts +18 -0
- package/dist/context/task-summary.js +89 -0
- package/dist/context/task-summary.js.map +1 -0
- package/dist/decision-capture/id.d.ts +21 -4
- package/dist/decision-capture/id.js +56 -5
- package/dist/decision-capture/id.js.map +1 -1
- package/dist/decision-capture/index.d.ts +7 -22
- package/dist/decision-capture/index.js +7 -17
- package/dist/decision-capture/index.js.map +1 -1
- package/dist/doctor/index.d.ts +1 -1
- package/dist/doctor/index.js +1 -1
- package/dist/events/index.d.ts +1 -1
- package/dist/events/index.js +1 -1
- package/dist/events/writer.d.ts +1 -1
- package/dist/events/writer.js +1 -1
- package/dist/gc/canary.d.ts +13 -23
- package/dist/gc/canary.js +36 -92
- package/dist/gc/canary.js.map +1 -1
- package/dist/gc/citation-integrity.d.ts +6 -6
- package/dist/gc/citation-integrity.js +64 -20
- package/dist/gc/citation-integrity.js.map +1 -1
- package/dist/gc/frontmatter.js +1 -1
- package/dist/gc/generator-drift.js +1 -1
- package/dist/gc/generator-drift.js.map +1 -1
- package/dist/gc/index.d.ts +2 -2
- package/dist/gc/index.js +1 -1
- package/dist/gc/index.js.map +1 -1
- package/dist/gc/quality-update.js +1 -1
- package/dist/gc/quality-update.js.map +1 -1
- package/dist/gc/types.d.ts +1 -30
- package/dist/ground/index.d.ts +2 -2
- package/dist/ground/index.js +1 -1
- package/dist/ground/index.js.map +1 -1
- package/dist/ground/ledgers.d.ts +0 -4
- package/dist/ground/ledgers.js +10 -8
- package/dist/ground/ledgers.js.map +1 -1
- package/dist/ground/manifest.js +0 -2
- package/dist/ground/manifest.js.map +1 -1
- package/dist/ground/quality-grades.js +3 -1
- package/dist/ground/quality-grades.js.map +1 -1
- package/dist/ground/schemas.d.ts +2 -7
- package/dist/ground/schemas.js +7 -2
- package/dist/ground/schemas.js.map +1 -1
- package/dist/ground/scope-index.d.ts +59 -12
- package/dist/ground/scope-index.js +212 -43
- package/dist/ground/scope-index.js.map +1 -1
- package/dist/hooks/bypass-detection.js +4 -2
- package/dist/hooks/bypass-detection.js.map +1 -1
- package/dist/hooks/post-tool-use/citation-scanner.d.ts +7 -5
- package/dist/hooks/post-tool-use/citation-scanner.js +15 -9
- package/dist/hooks/post-tool-use/citation-scanner.js.map +1 -1
- package/dist/hooks/post-tool-use/copy-scanner.js +1 -1
- package/dist/hooks/post-tool-use/copy-scanner.js.map +1 -1
- package/dist/hooks/post-tool-use/ledger-cache.d.ts +8 -0
- package/dist/hooks/post-tool-use/ledger-cache.js +53 -0
- package/dist/hooks/post-tool-use/ledger-cache.js.map +1 -1
- package/dist/hooks/post-tool-use/legend-builder.d.ts +3 -3
- package/dist/hooks/post-tool-use/legend-builder.js +30 -8
- package/dist/hooks/post-tool-use/legend-builder.js.map +1 -1
- package/dist/hooks/post-tool-use/read-enricher.d.ts +1 -1
- package/dist/hooks/post-tool-use/read-enricher.js +68 -21
- package/dist/hooks/post-tool-use/read-enricher.js.map +1 -1
- package/dist/hooks/post-tool-use/write-guardian.js +148 -18
- package/dist/hooks/post-tool-use/write-guardian.js.map +1 -1
- package/dist/hooks/runners/index.d.ts +1 -0
- package/dist/hooks/runners/index.js +1 -0
- package/dist/hooks/runners/index.js.map +1 -1
- package/dist/hooks/runners/payload.d.ts +1 -1
- package/dist/hooks/runners/payload.js +27 -12
- package/dist/hooks/runners/payload.js.map +1 -1
- package/dist/hooks/runners/session-start.js +212 -66
- package/dist/hooks/runners/session-start.js.map +1 -1
- package/dist/hooks/runners/stop.d.ts +9 -12
- package/dist/hooks/runners/stop.js +67 -36
- package/dist/hooks/runners/stop.js.map +1 -1
- package/dist/hooks/runners/user-prompt-submit.d.ts +15 -0
- package/dist/hooks/runners/user-prompt-submit.js +149 -0
- package/dist/hooks/runners/user-prompt-submit.js.map +1 -0
- package/dist/hooks/user-prompt-submit.d.ts +7 -0
- package/dist/hooks/user-prompt-submit.js +12 -0
- package/dist/hooks/user-prompt-submit.js.map +1 -0
- package/dist/index.d.ts +1 -6
- package/dist/index.js +1 -5
- package/dist/index.js.map +1 -1
- package/dist/init/baseline-audit.d.ts +5 -1
- package/dist/init/baseline-audit.js +25 -2
- package/dist/init/baseline-audit.js.map +1 -1
- package/dist/init/glob-inference.d.ts +16 -0
- package/dist/init/glob-inference.js +108 -0
- package/dist/init/glob-inference.js.map +1 -0
- package/dist/init/index.d.ts +2 -0
- package/dist/init/index.js +1 -0
- package/dist/init/index.js.map +1 -1
- package/dist/init/ingest-docs.d.ts +1 -1
- package/dist/init/ingest-docs.js +19 -6
- package/dist/init/ingest-docs.js.map +1 -1
- package/dist/init/init.js +12 -7
- package/dist/init/init.js.map +1 -1
- package/dist/init/mapper-merge.d.ts +8 -2
- package/dist/init/mapper-merge.js +50 -32
- package/dist/init/mapper-merge.js.map +1 -1
- package/dist/init/mapper-parallel.d.ts +2 -3
- package/dist/init/mapper-parallel.js +9 -38
- package/dist/init/mapper-parallel.js.map +1 -1
- package/dist/init/mapper-prompts.js +1 -1
- package/dist/init/mapper-prompts.js.map +1 -1
- package/dist/init/mapper.d.ts +6 -127
- package/dist/init/mapper.js +30 -7
- package/dist/init/mapper.js.map +1 -1
- package/dist/init/module-slicer.d.ts +1 -1
- package/dist/init/module-slicer.js +1 -1
- package/dist/init/multi-dev/install.d.ts +5 -11
- package/dist/init/multi-dev/install.js +4 -6
- package/dist/init/multi-dev/install.js.map +1 -1
- package/dist/init/overlay.d.ts +2 -2
- package/dist/init/overlay.js +1 -1
- package/dist/init/overlay.js.map +1 -1
- package/dist/init/phases/10-strip.js +1 -2
- package/dist/init/phases/10-strip.js.map +1 -1
- package/dist/init/phases/12-multidev.d.ts +1 -6
- package/dist/init/phases/12-multidev.js +1 -6
- package/dist/init/phases/12-multidev.js.map +1 -1
- package/dist/init/phases/3b-seed.d.ts +1 -10
- package/dist/init/phases/3b-seed.js +1 -10
- package/dist/init/phases/3b-seed.js.map +1 -1
- package/dist/init/phases/4-pilot.js +53 -15
- package/dist/init/phases/4-pilot.js.map +1 -1
- package/dist/init/phases/5-brand.js +10 -10
- package/dist/init/phases/5-brand.js.map +1 -1
- package/dist/init/prompts.d.ts +6 -8
- package/dist/init/prompts.js +3 -6
- package/dist/init/prompts.js.map +1 -1
- package/dist/init/rules-merge/ingest.js +1 -1
- package/dist/init/source-comments/classify.d.ts +1 -41
- package/dist/init/source-comments/classify.js +68 -37
- package/dist/init/source-comments/classify.js.map +1 -1
- package/dist/init/source-comments/index.d.ts +2 -2
- package/dist/init/source-comments/index.js +2 -2
- package/dist/init/source-comments/index.js.map +1 -1
- package/dist/init/source-comments/ingest.d.ts +38 -2
- package/dist/init/source-comments/ingest.js +237 -4
- package/dist/init/source-comments/ingest.js.map +1 -1
- package/dist/init/source-comments/strip-replace.d.ts +10 -19
- package/dist/init/source-comments/strip-replace.js +26 -2
- package/dist/init/source-comments/strip-replace.js.map +1 -1
- package/dist/init/source-comments/walker.d.ts +9 -2
- package/dist/init/source-comments/walker.js +38 -19
- package/dist/init/source-comments/walker.js.map +1 -1
- package/dist/init/submodules.d.ts +3 -2
- package/dist/init/types.d.ts +3 -5
- package/dist/init/types.js +3 -5
- package/dist/init/types.js.map +1 -1
- package/dist/init/visual.d.ts +4 -9
- package/dist/init/visual.js +1 -16
- package/dist/init/visual.js.map +1 -1
- package/dist/logger.d.ts +0 -1
- package/dist/logger.js +0 -1
- package/dist/logger.js.map +1 -1
- package/dist/mcp/context.d.ts +2 -3
- package/dist/mcp/context.js.map +1 -1
- package/dist/mcp/errors.d.ts +1 -1
- package/dist/mcp/errors.js.map +1 -1
- package/dist/mcp/history/prompt.d.ts +2 -1
- package/dist/mcp/history/walker.js +1 -1
- package/dist/mcp/history/walker.js.map +1 -1
- package/dist/mcp/path-allowlist.d.ts +0 -6
- package/dist/mcp/path-allowlist.js +0 -10
- package/dist/mcp/path-allowlist.js.map +1 -1
- package/dist/mcp/schemas.d.ts +15 -72
- package/dist/mcp/schemas.js +21 -70
- package/dist/mcp/schemas.js.map +1 -1
- package/dist/mcp/serve.d.ts +1 -1
- package/dist/mcp/serve.js +2 -5
- package/dist/mcp/serve.js.map +1 -1
- package/dist/mcp/server.js +10 -4
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/telemetry.d.ts +8 -1
- package/dist/mcp/telemetry.js +16 -0
- package/dist/mcp/telemetry.js.map +1 -1
- package/dist/mcp/tools/decision-get.js +37 -29
- package/dist/mcp/tools/decision-get.js.map +1 -1
- package/dist/mcp/tools/decisions-in-scope.js +22 -3
- package/dist/mcp/tools/decisions-in-scope.js.map +1 -1
- package/dist/mcp/tools/index.js +2 -2
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/invariant-get.js +1 -1
- package/dist/mcp/tools/invariant-get.js.map +1 -1
- package/dist/mcp/tools/invariants-in-scope.js +26 -7
- package/dist/mcp/tools/invariants-in-scope.js.map +1 -1
- package/dist/mcp/tools/query-history.js +3 -3
- package/dist/mcp/tools/query-history.js.map +1 -1
- package/dist/mcp/tools/resolve-attention.d.ts +3 -3
- package/dist/mcp/tools/resolve-attention.js +40 -28
- package/dist/mcp/tools/resolve-attention.js.map +1 -1
- package/dist/mcp/tools/search.js +3 -4
- package/dist/mcp/tools/search.js.map +1 -1
- package/dist/mcp/tools/task-create.d.ts +15 -0
- package/dist/mcp/tools/task-create.js +96 -0
- package/dist/mcp/tools/task-create.js.map +1 -0
- package/dist/mcp/tools/timeline.js +3 -7
- package/dist/mcp/tools/timeline.js.map +1 -1
- package/dist/profiles/types.d.ts +1 -1
- package/dist/profiles/types.js +1 -1
- package/dist/session/id.d.ts +1 -3
- package/dist/session/id.js +1 -1
- package/dist/session/id.js.map +1 -1
- package/dist/session-start/build.d.ts +3 -11
- package/dist/session-start/build.js +55 -34
- package/dist/session-start/build.js.map +1 -1
- package/dist/session-start/index.d.ts +2 -2
- package/dist/session-start/index.js +2 -2
- package/dist/session-start/index.js.map +1 -1
- package/dist/session-start/templates.d.ts +20 -4
- package/dist/session-start/templates.js +45 -35
- package/dist/session-start/templates.js.map +1 -1
- package/dist/status-line/format.d.ts +19 -11
- package/dist/status-line/format.js +44 -36
- package/dist/status-line/format.js.map +1 -1
- package/dist/status-line/index.d.ts +3 -1
- package/dist/status-line/index.js +1 -1
- package/dist/status-line/index.js.map +1 -1
- package/dist/status-line/reader.d.ts +9 -6
- package/dist/status-line/reader.js +50 -15
- package/dist/status-line/reader.js.map +1 -1
- package/dist/status-line/writer.d.ts +5 -0
- package/dist/status-line/writer.js +9 -0
- package/dist/status-line/writer.js.map +1 -1
- package/dist/trace/index.d.ts +44 -0
- package/dist/trace/index.js +51 -0
- package/dist/trace/index.js.map +1 -0
- package/package.json +2 -3
- package/templates/.archive/README.md +3 -3
- package/templates/.cairn/config/sensors.yaml +16 -19
- package/templates/.cairn/config/stub-patterns.yaml +4 -4
- package/templates/.cairn/config/trust-policy.yaml +3 -35
- package/templates/.cairn/config/workflow.md +13 -194
- package/templates/.cairn/git-hooks/commit-msg +1 -1
- package/templates/.cairn/ground/canonical-map/topics.yaml +3 -26
- package/templates/.cairn/ground/capabilities/snippets.yaml +0 -1
- package/templates/.cairn/ground/manifest.yaml +5 -8
- package/templates/.cairn/ground/product/personas.yaml +0 -1
- package/dist/context/checkpoint.d.ts +0 -11
- package/dist/context/checkpoint.js +0 -30
- package/dist/context/checkpoint.js.map +0 -1
- package/dist/decision-capture/capture.d.ts +0 -57
- package/dist/decision-capture/capture.js +0 -186
- package/dist/decision-capture/capture.js.map +0 -1
- package/dist/decision-capture/extractor.d.ts +0 -20
- package/dist/decision-capture/extractor.js +0 -103
- package/dist/decision-capture/extractor.js.map +0 -1
- package/dist/decision-capture/prompt.d.ts +0 -15
- package/dist/decision-capture/prompt.js +0 -68
- package/dist/decision-capture/prompt.js.map +0 -1
- package/dist/decision-capture/refinement-prompt.d.ts +0 -25
- package/dist/decision-capture/refinement-prompt.js +0 -146
- package/dist/decision-capture/refinement-prompt.js.map +0 -1
- package/dist/decision-capture/refinement-schema.d.ts +0 -52
- package/dist/decision-capture/refinement-schema.js +0 -61
- package/dist/decision-capture/refinement-schema.js.map +0 -1
- package/dist/decision-capture/refinement.d.ts +0 -60
- package/dist/decision-capture/refinement.js +0 -439
- package/dist/decision-capture/refinement.js.map +0 -1
- package/dist/decision-capture/schema.d.ts +0 -70
- package/dist/decision-capture/schema.js +0 -71
- package/dist/decision-capture/schema.js.map +0 -1
- package/dist/decision-capture/types.d.ts +0 -201
- package/dist/decision-capture/types.js +0 -20
- package/dist/decision-capture/types.js.map +0 -1
- package/dist/decision-capture/writer.d.ts +0 -90
- package/dist/decision-capture/writer.js +0 -267
- package/dist/decision-capture/writer.js.map +0 -1
- package/dist/frontend-types.d.ts +0 -243
- package/dist/frontend-types.js +0 -15
- package/dist/frontend-types.js.map +0 -1
- package/dist/hooks/index.d.ts +0 -14
- package/dist/hooks/index.js +0 -14
- package/dist/hooks/index.js.map +0 -1
- package/dist/inbox.d.ts +0 -17
- package/dist/inbox.js +0 -30
- package/dist/inbox.js.map +0 -1
- package/dist/mcp/tools/append-run-note.d.ts +0 -18
- package/dist/mcp/tools/append-run-note.js +0 -54
- package/dist/mcp/tools/append-run-note.js.map +0 -1
- package/dist/mcp/tools/append.d.ts +0 -8
- package/dist/mcp/tools/append.js +0 -37
- package/dist/mcp/tools/append.js.map +0 -1
- package/dist/mcp/tools/ask-operator.d.ts +0 -34
- package/dist/mcp/tools/ask-operator.js +0 -97
- package/dist/mcp/tools/ask-operator.js.map +0 -1
- package/dist/mcp/tools/drop-task.d.ts +0 -12
- package/dist/mcp/tools/drop-task.js +0 -68
- package/dist/mcp/tools/drop-task.js.map +0 -1
- package/dist/mcp/tools/record-run-event.d.ts +0 -10
- package/dist/mcp/tools/record-run-event.js +0 -32
- package/dist/mcp/tools/record-run-event.js.map +0 -1
- package/dist/prompt.d.ts +0 -19
- package/dist/prompt.js +0 -50
- package/dist/prompt.js.map +0 -1
- package/dist/tier0/classify.d.ts +0 -10
- package/dist/tier0/classify.js +0 -110
- package/dist/tier0/classify.js.map +0 -1
- package/dist/tier0/index.d.ts +0 -2
- package/dist/tier0/index.js +0 -2
- package/dist/tier0/index.js.map +0 -1
- package/dist/tier0/types.d.ts +0 -24
- package/dist/tier0/types.js +0 -9
- package/dist/tier0/types.js.map +0 -1
- package/dist/tightener/index.d.ts +0 -4
- package/dist/tightener/index.js +0 -4
- package/dist/tightener/index.js.map +0 -1
- package/dist/tightener/prompt.d.ts +0 -3
- package/dist/tightener/prompt.js +0 -67
- package/dist/tightener/prompt.js.map +0 -1
- package/dist/tightener/schema.d.ts +0 -68
- package/dist/tightener/schema.js +0 -44
- package/dist/tightener/schema.js.map +0 -1
- package/dist/tightener/tighten.d.ts +0 -2
- package/dist/tightener/tighten.js +0 -66
- package/dist/tightener/tighten.js.map +0 -1
- package/dist/tightener/types.d.ts +0 -74
- package/dist/tightener/types.js +0 -6
- package/dist/tightener/types.js.map +0 -1
- package/templates/.claude/settings.json +0 -57
- package/templates/.mcp.json +0 -8
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* runDecisionCapture — orchestrates the full flow:
|
|
3
|
-
*
|
|
4
|
-
* raw_text → extract → write draft → adapter dialog 🟢/🟡/🔴
|
|
5
|
-
* ├── 🟢 commit → acceptDraft → ledger
|
|
6
|
-
* ├── 🟡 edit → leave draft + return correction text
|
|
7
|
-
* └── 🔴 reject → rejectDraft → no record
|
|
8
|
-
*
|
|
9
|
-
* The dialog is supplied by the caller (typically a FrontendAdapter's
|
|
10
|
-
* requestDialog) so this entry point works equally well in tests with the
|
|
11
|
-
* stub adapter, in CLI with a TTY prompt, and in Discord with the real
|
|
12
|
-
* adapter.
|
|
13
|
-
*/
|
|
14
|
-
import { logger } from "../logger.js";
|
|
15
|
-
import { runDecisionExtractor } from "./extractor.js";
|
|
16
|
-
import { allocateDecisionId } from "./id.js";
|
|
17
|
-
import { acceptDraft, rejectDraft, writeDecisionDraft, } from "./writer.js";
|
|
18
|
-
import { runDecisionRefinement, } from "./refinement.js";
|
|
19
|
-
const log = logger("decision-capture");
|
|
20
|
-
const CHOICE_COMMIT = "a";
|
|
21
|
-
const CHOICE_EDIT = "b";
|
|
22
|
-
const CHOICE_REJECT = "c";
|
|
23
|
-
export async function runDecisionCapture(args) {
|
|
24
|
-
const startedAt = Date.now();
|
|
25
|
-
const tier = args.tier ?? "haiku";
|
|
26
|
-
const receivedAt = args.receivedAt ?? new Date().toISOString();
|
|
27
|
-
const extract = args.extractorOverride ?? runDecisionExtractor;
|
|
28
|
-
const extractorResult = await extract({
|
|
29
|
-
raw_text: args.rawText,
|
|
30
|
-
author_id: args.authorId,
|
|
31
|
-
received_at: receivedAt,
|
|
32
|
-
source: args.source,
|
|
33
|
-
tier,
|
|
34
|
-
});
|
|
35
|
-
if (extractorResult.output.not_a_decision) {
|
|
36
|
-
log.info({ source: args.source, author: args.authorId }, "decision-extractor flagged not_a_decision — short-circuiting");
|
|
37
|
-
return {
|
|
38
|
-
short_circuited: true,
|
|
39
|
-
duration_ms: Date.now() - startedAt,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
const id = allocateDecisionId(args.repoRoot);
|
|
43
|
-
const draft = writeDecisionDraft({
|
|
44
|
-
repoRoot: args.repoRoot,
|
|
45
|
-
id,
|
|
46
|
-
output: extractorResult.output,
|
|
47
|
-
rawText: args.rawText,
|
|
48
|
-
authorId: args.authorId,
|
|
49
|
-
receivedAt,
|
|
50
|
-
source: args.source,
|
|
51
|
-
});
|
|
52
|
-
log.info({ id, draft_path: draft.draft_path, confidence: extractorResult.output.confidence_signal }, "draft written; awaiting confirm");
|
|
53
|
-
const decision = await promptConfirm({
|
|
54
|
-
adapter: args.adapter,
|
|
55
|
-
draft,
|
|
56
|
-
...(args.channelId !== undefined ? { channelId: args.channelId } : {}),
|
|
57
|
-
timeoutMs: args.confirmTimeoutMs ?? 60_000,
|
|
58
|
-
});
|
|
59
|
-
if (decision.decision === "commit") {
|
|
60
|
-
const accepted = acceptDraft({ repoRoot: args.repoRoot, draft });
|
|
61
|
-
log.info({ id, accepted_path: accepted.acceptedPath, ledger_size: accepted.ledgerSize }, "draft accepted; ledger regenerated");
|
|
62
|
-
let refinement;
|
|
63
|
-
const hasCandidates = extractorResult.output.candidate_assertions.length > 0;
|
|
64
|
-
if (!args.bypassRefinement && hasCandidates) {
|
|
65
|
-
try {
|
|
66
|
-
refinement = await runDecisionRefinement({
|
|
67
|
-
repoRoot: args.repoRoot,
|
|
68
|
-
decisionId: id,
|
|
69
|
-
adapter: args.adapter,
|
|
70
|
-
...(args.channelId !== undefined ? { channelId: args.channelId } : {}),
|
|
71
|
-
tier: args.refinementTier ?? tier,
|
|
72
|
-
...(args.refinementDialogTimeoutMs !== undefined
|
|
73
|
-
? { dialogTimeoutMs: args.refinementDialogTimeoutMs }
|
|
74
|
-
: {}),
|
|
75
|
-
...(args.refinementProposerOverride !== undefined
|
|
76
|
-
? { proposerOverride: args.refinementProposerOverride }
|
|
77
|
-
: {}),
|
|
78
|
-
});
|
|
79
|
-
log.info({
|
|
80
|
-
id,
|
|
81
|
-
operator_choice: refinement.operator_choice,
|
|
82
|
-
lifted: refinement.lifted_count,
|
|
83
|
-
demoted: refinement.demoted_count,
|
|
84
|
-
kept_candidate: refinement.skipped_count,
|
|
85
|
-
}, "refinement complete");
|
|
86
|
-
}
|
|
87
|
-
catch (err) {
|
|
88
|
-
// Refinement failure must NEVER roll back the accept. Log and move
|
|
89
|
-
// on; candidates stay loose under candidate_assertions: for the
|
|
90
|
-
// operator's next refine pass.
|
|
91
|
-
log.error({ err: String(err), id }, "refinement threw — accept stands; candidates remain loose");
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return {
|
|
95
|
-
short_circuited: false,
|
|
96
|
-
draft,
|
|
97
|
-
confirm: {
|
|
98
|
-
decision: "commit",
|
|
99
|
-
accepted_path: accepted.acceptedPath,
|
|
100
|
-
ledger_size: accepted.ledgerSize,
|
|
101
|
-
draft,
|
|
102
|
-
confidence: extractorResult.output.confidence_signal,
|
|
103
|
-
},
|
|
104
|
-
...(refinement !== undefined ? { refinement } : {}),
|
|
105
|
-
duration_ms: Date.now() - startedAt,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
if (decision.decision === "edit") {
|
|
109
|
-
log.info({ id, correction: decision.correction?.slice(0, 120) }, "draft edit requested");
|
|
110
|
-
return {
|
|
111
|
-
short_circuited: false,
|
|
112
|
-
draft,
|
|
113
|
-
confirm: {
|
|
114
|
-
decision: "edit",
|
|
115
|
-
draft,
|
|
116
|
-
...(decision.correction !== undefined ? { correction: decision.correction } : {}),
|
|
117
|
-
confidence: extractorResult.output.confidence_signal,
|
|
118
|
-
},
|
|
119
|
-
duration_ms: Date.now() - startedAt,
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
// reject
|
|
123
|
-
rejectDraft({ repoRoot: args.repoRoot, draft });
|
|
124
|
-
log.info({ id }, "draft rejected; file removed");
|
|
125
|
-
return {
|
|
126
|
-
short_circuited: false,
|
|
127
|
-
draft,
|
|
128
|
-
confirm: {
|
|
129
|
-
decision: "reject",
|
|
130
|
-
draft,
|
|
131
|
-
confidence: extractorResult.output.confidence_signal,
|
|
132
|
-
},
|
|
133
|
-
duration_ms: Date.now() - startedAt,
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
async function promptConfirm(args) {
|
|
137
|
-
const summary = args.draft.output.summary.split(/\r?\n/).slice(0, 3).join(" ").trim();
|
|
138
|
-
const scope = args.draft.output.scope_globs.length > 0
|
|
139
|
-
? args.draft.output.scope_globs.join(", ")
|
|
140
|
-
: "(no scope captured)";
|
|
141
|
-
const supersedes = args.draft.output.supersedes
|
|
142
|
-
? `Supersedes ${args.draft.output.supersedes}. `
|
|
143
|
-
: "";
|
|
144
|
-
const assertions = args.draft.output.candidate_assertions.length;
|
|
145
|
-
const prompt = [
|
|
146
|
-
`Confirm ${args.draft.id}? "${args.draft.output.subject}"`,
|
|
147
|
-
summary,
|
|
148
|
-
`Scope: ${scope}`,
|
|
149
|
-
`${supersedes}Candidate assertions: ${assertions}`,
|
|
150
|
-
].join("\n");
|
|
151
|
-
const dialogSpec = {
|
|
152
|
-
bundleId: args.draft.id,
|
|
153
|
-
prompt,
|
|
154
|
-
choices: [
|
|
155
|
-
{ id: CHOICE_COMMIT, label: "🟢 commit" },
|
|
156
|
-
{ id: CHOICE_EDIT, label: "🟡 edit" },
|
|
157
|
-
{ id: CHOICE_REJECT, label: "🔴 not a decision" },
|
|
158
|
-
{ id: "e_other", label: "E) Other" },
|
|
159
|
-
],
|
|
160
|
-
timeoutMs: args.timeoutMs,
|
|
161
|
-
};
|
|
162
|
-
if (args.channelId !== undefined)
|
|
163
|
-
dialogSpec.channelId = args.channelId;
|
|
164
|
-
const response = await args.adapter.requestDialog(dialogSpec);
|
|
165
|
-
if (response.timedOut) {
|
|
166
|
-
// Timeout = treat as edit-with-no-correction so the draft survives in
|
|
167
|
-
// _inbox/ and the operator can come back to it. This avoids losing the
|
|
168
|
-
// capture on a transient inattentiveness.
|
|
169
|
-
return { decision: "edit" };
|
|
170
|
-
}
|
|
171
|
-
if (response.choiceId === CHOICE_COMMIT) {
|
|
172
|
-
return { decision: "commit" };
|
|
173
|
-
}
|
|
174
|
-
if (response.choiceId === CHOICE_REJECT) {
|
|
175
|
-
return { decision: "reject" };
|
|
176
|
-
}
|
|
177
|
-
if (response.choiceId === CHOICE_EDIT || response.choiceId === "e_other") {
|
|
178
|
-
return {
|
|
179
|
-
decision: "edit",
|
|
180
|
-
...(response.freeText !== undefined ? { correction: response.freeText } : {}),
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
// Unknown id — fall back to edit (preserve the draft).
|
|
184
|
-
return { decision: "edit" };
|
|
185
|
-
}
|
|
186
|
-
//# sourceMappingURL=capture.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/decision-capture/capture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EACL,WAAW,EACX,WAAW,EACX,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAEL,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAOzB,MAAM,GAAG,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAyCvC,MAAM,aAAa,GAAG,GAAG,CAAC;AAC1B,MAAM,WAAW,GAAG,GAAG,CAAC;AACxB,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAA4B;IAE5B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC;IAClC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,IAAI,oBAAoB,CAAC;IAE/D,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC;QACpC,QAAQ,EAAE,IAAI,CAAC,OAAO;QACtB,SAAS,EAAE,IAAI,CAAC,QAAQ;QACxB,WAAW,EAAE,UAAU;QACvB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,IAAI;KACL,CAAC,CAAC;IAEH,IAAI,eAAe,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAC1C,GAAG,CAAC,IAAI,CACN,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,EAC9C,8DAA8D,CAC/D,CAAC;QACF,OAAO;YACL,eAAe,EAAE,IAAI;YACrB,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;SACpC,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,kBAAkB,CAAC;QAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,EAAE;QACF,MAAM,EAAE,eAAe,CAAC,MAAM;QAC9B,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,UAAU;QACV,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CACN,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,UAAU,EAAE,eAAe,CAAC,MAAM,CAAC,iBAAiB,EAAE,EAC1F,iCAAiC,CAClC,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC;QACnC,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,KAAK;QACL,GAAG,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,SAAS,EAAE,IAAI,CAAC,gBAAgB,IAAI,MAAM;KAC3C,CAAC,CAAC;IAEH,IAAI,QAAQ,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,WAAW,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QACjE,GAAG,CAAC,IAAI,CACN,EAAE,EAAE,EAAE,aAAa,EAAE,QAAQ,CAAC,YAAY,EAAE,WAAW,EAAE,QAAQ,CAAC,UAAU,EAAE,EAC9E,oCAAoC,CACrC,CAAC;QAEF,IAAI,UAA2D,CAAC;QAChE,MAAM,aAAa,GAAG,eAAe,CAAC,MAAM,CAAC,oBAAoB,CAAC,MAAM,GAAG,CAAC,CAAC;QAC7E,IAAI,CAAC,IAAI,CAAC,gBAAgB,IAAI,aAAa,EAAE,CAAC;YAC5C,IAAI,CAAC;gBACH,UAAU,GAAG,MAAM,qBAAqB,CAAC;oBACvC,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,UAAU,EAAE,EAAE;oBACd,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,GAAG,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACtE,IAAI,EAAE,IAAI,CAAC,cAAc,IAAI,IAAI;oBACjC,GAAG,CAAC,IAAI,CAAC,yBAAyB,KAAK,SAAS;wBAC9C,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,CAAC,yBAAyB,EAAE;wBACrD,CAAC,CAAC,EAAE,CAAC;oBACP,GAAG,CAAC,IAAI,CAAC,0BAA0B,KAAK,SAAS;wBAC/C,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,0BAA0B,EAAE;wBACvD,CAAC,CAAC,EAAE,CAAC;iBACR,CAAC,CAAC;gBACH,GAAG,CAAC,IAAI,CACN;oBACE,EAAE;oBACF,eAAe,EAAE,UAAU,CAAC,eAAe;oBAC3C,MAAM,EAAE,UAAU,CAAC,YAAY;oBAC/B,OAAO,EAAE,UAAU,CAAC,aAAa;oBACjC,cAAc,EAAE,UAAU,CAAC,aAAa;iBACzC,EACD,qBAAqB,CACtB,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,mEAAmE;gBACnE,gEAAgE;gBAChE,+BAA+B;gBAC/B,GAAG,CAAC,KAAK,CACP,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,EACxB,2DAA2D,CAC5D,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO;YACL,eAAe,EAAE,KAAK;YACtB,KAAK;YACL,OAAO,EAAE;gBACP,QAAQ,EAAE,QAAQ;gBAClB,aAAa,EAAE,QAAQ,CAAC,YAAY;gBACpC,WAAW,EAAE,QAAQ,CAAC,UAAU;gBAChC,KAAK;gBACL,UAAU,EAAE,eAAe,CAAC,MAAM,CAAC,iBAAiB;aACrD;YACD,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;SACpC,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QACjC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,sBAAsB,CAAC,CAAC;QACzF,OAAO;YACL,eAAe,EAAE,KAAK;YACtB,KAAK;YACL,OAAO,EAAE;gBACP,QAAQ,EAAE,MAAM;gBAChB,KAAK;gBACL,GAAG,CAAC,QAAQ,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjF,UAAU,EAAE,eAAe,CAAC,MAAM,CAAC,iBAAiB;aACrD;YACD,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;SACpC,CAAC;IACJ,CAAC;IAED,SAAS;IACT,WAAW,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IAChD,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,8BAA8B,CAAC,CAAC;IACjD,OAAO;QACL,eAAe,EAAE,KAAK;QACtB,KAAK;QACL,OAAO,EAAE;YACP,QAAQ,EAAE,QAAQ;YAClB,KAAK;YACL,UAAU,EAAE,eAAe,CAAC,MAAM,CAAC,iBAAiB;SACrD;QACD,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;KACpC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,IAK5B;IACC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACtF,MAAM,KAAK,GACT,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;QACtC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;QAC1C,CAAC,CAAC,qBAAqB,CAAC;IAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU;QAC7C,CAAC,CAAC,cAAc,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,IAAI;QAChD,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,oBAAoB,CAAC,MAAM,CAAC;IAEjE,MAAM,MAAM,GAAG;QACb,WAAW,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,GAAG;QAC1D,OAAO;QACP,UAAU,KAAK,EAAE;QACjB,GAAG,UAAU,yBAAyB,UAAU,EAAE;KACnD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,MAAM,UAAU,GAAe;QAC7B,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE;QACvB,MAAM;QACN,OAAO,EAAE;YACP,EAAE,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE;YACzC,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE;YACrC,EAAE,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,mBAAmB,EAAE;YACjD,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE;SACrC;QACD,SAAS,EAAE,IAAI,CAAC,SAAS;KAC1B,CAAC;IACF,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS;QAAE,UAAU,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IACxE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAE9D,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACtB,sEAAsE;QACtE,uEAAuE;QACvE,0CAA0C;QAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC9B,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;QACxC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;IAChC,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;QACxC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;IAChC,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,KAAK,WAAW,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACzE,OAAO;YACL,QAAQ,EAAE,MAAM;YAChB,GAAG,CAAC,QAAQ,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9E,CAAC;IACJ,CAAC;IACD,uDAAuD;IACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;AAC9B,CAAC"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decision-extractor runner.
|
|
3
|
-
*
|
|
4
|
-
* Single Tier-1 (Haiku) call by default per workflow.md
|
|
5
|
-
* `decision_extractor: 1`. Output is gated by `--json-schema`. The wrapper
|
|
6
|
-
* validates shape via a runtime guard and returns the typed payload.
|
|
7
|
-
*
|
|
8
|
-
* The runner does NOT touch the filesystem. It returns the extractor's
|
|
9
|
-
* structured output; the writer + confirm flow handle persistence.
|
|
10
|
-
*/
|
|
11
|
-
import type { DecisionExtractorInput, DecisionExtractorOutput } from "./types.js";
|
|
12
|
-
export interface ExtractorResult {
|
|
13
|
-
output: DecisionExtractorOutput;
|
|
14
|
-
duration_ms: number;
|
|
15
|
-
usage?: {
|
|
16
|
-
input_tokens?: number;
|
|
17
|
-
output_tokens?: number;
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
export declare function runDecisionExtractor(input: DecisionExtractorInput): Promise<ExtractorResult>;
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decision-extractor runner.
|
|
3
|
-
*
|
|
4
|
-
* Single Tier-1 (Haiku) call by default per workflow.md
|
|
5
|
-
* `decision_extractor: 1`. Output is gated by `--json-schema`. The wrapper
|
|
6
|
-
* validates shape via a runtime guard and returns the typed payload.
|
|
7
|
-
*
|
|
8
|
-
* The runner does NOT touch the filesystem. It returns the extractor's
|
|
9
|
-
* structured output; the writer + confirm flow handle persistence.
|
|
10
|
-
*/
|
|
11
|
-
import { runClaude } from "../claude/index.js";
|
|
12
|
-
import { logger } from "../logger.js";
|
|
13
|
-
import { DECISION_EXTRACTOR_SYSTEM_PROMPT, buildDecisionExtractorUserPrompt, } from "./prompt.js";
|
|
14
|
-
import { DECISION_EXTRACTOR_OUTPUT_SCHEMA } from "./schema.js";
|
|
15
|
-
const log = logger("decision-capture.extractor");
|
|
16
|
-
export async function runDecisionExtractor(input) {
|
|
17
|
-
const userPrompt = buildDecisionExtractorUserPrompt(input);
|
|
18
|
-
log.info({
|
|
19
|
-
tier: input.tier,
|
|
20
|
-
raw_text_len: input.raw_text.length,
|
|
21
|
-
accepted_decisions: input.accepted_decisions?.length ?? 0,
|
|
22
|
-
}, "decision-extractor dispatch");
|
|
23
|
-
const result = await runClaude({
|
|
24
|
-
tier: input.tier,
|
|
25
|
-
prompt: userPrompt,
|
|
26
|
-
system: DECISION_EXTRACTOR_SYSTEM_PROMPT,
|
|
27
|
-
jsonSchema: DECISION_EXTRACTOR_OUTPUT_SCHEMA,
|
|
28
|
-
timeoutMs: input.timeout_ms ?? 120_000,
|
|
29
|
-
});
|
|
30
|
-
if (!isOutput(result.parsed)) {
|
|
31
|
-
throw new Error(`decision-extractor returned malformed output. preview: ${result.text.slice(0, 200)}`);
|
|
32
|
-
}
|
|
33
|
-
const output = result.parsed;
|
|
34
|
-
log.info({
|
|
35
|
-
not_a_decision: output.not_a_decision,
|
|
36
|
-
subject_preview: output.subject.slice(0, 80),
|
|
37
|
-
assertions: output.candidate_assertions.length,
|
|
38
|
-
confidence: output.confidence_signal,
|
|
39
|
-
duration_ms: result.durationMs,
|
|
40
|
-
}, "decision-extractor complete");
|
|
41
|
-
return {
|
|
42
|
-
output,
|
|
43
|
-
duration_ms: result.durationMs,
|
|
44
|
-
...(result.usage !== undefined
|
|
45
|
-
? {
|
|
46
|
-
usage: {
|
|
47
|
-
...(result.usage["input_tokens"] !== undefined
|
|
48
|
-
? { input_tokens: result.usage["input_tokens"] }
|
|
49
|
-
: {}),
|
|
50
|
-
...(result.usage["output_tokens"] !== undefined
|
|
51
|
-
? { output_tokens: result.usage["output_tokens"] }
|
|
52
|
-
: {}),
|
|
53
|
-
},
|
|
54
|
-
}
|
|
55
|
-
: {}),
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
function isOutput(value) {
|
|
59
|
-
if (typeof value !== "object" || value === null)
|
|
60
|
-
return false;
|
|
61
|
-
const v = value;
|
|
62
|
-
if (typeof v["subject"] !== "string")
|
|
63
|
-
return false;
|
|
64
|
-
if (typeof v["summary"] !== "string")
|
|
65
|
-
return false;
|
|
66
|
-
if (!Array.isArray(v["scope_globs"]))
|
|
67
|
-
return false;
|
|
68
|
-
for (const g of v["scope_globs"]) {
|
|
69
|
-
if (typeof g !== "string")
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
const supersedes = v["supersedes"];
|
|
73
|
-
if (supersedes !== undefined &&
|
|
74
|
-
supersedes !== null &&
|
|
75
|
-
typeof supersedes !== "string") {
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
if (!Array.isArray(v["candidate_assertions"]))
|
|
79
|
-
return false;
|
|
80
|
-
for (const a of v["candidate_assertions"]) {
|
|
81
|
-
if (!isCandidateAssertion(a))
|
|
82
|
-
return false;
|
|
83
|
-
}
|
|
84
|
-
if (v["confidence_signal"] !== "high" &&
|
|
85
|
-
v["confidence_signal"] !== "medium" &&
|
|
86
|
-
v["confidence_signal"] !== "low") {
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
89
|
-
if (typeof v["not_a_decision"] !== "boolean")
|
|
90
|
-
return false;
|
|
91
|
-
return true;
|
|
92
|
-
}
|
|
93
|
-
function isCandidateAssertion(value) {
|
|
94
|
-
if (typeof value !== "object" || value === null)
|
|
95
|
-
return false;
|
|
96
|
-
const v = value;
|
|
97
|
-
if (typeof v["kind"] !== "string")
|
|
98
|
-
return false;
|
|
99
|
-
if (typeof v["description"] !== "string")
|
|
100
|
-
return false;
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
//# sourceMappingURL=extractor.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/decision-capture/extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decision-extractor prompts.
|
|
3
|
-
*
|
|
4
|
-
* Operator submits a direction (slash arg or free-text classified as
|
|
5
|
-
* `direction`). The extractor distills it into a typed candidate the
|
|
6
|
-
* cairn materializes into a draft decision.
|
|
7
|
-
*
|
|
8
|
-
* Anti-fabrication framing: when the input isn't actually a direction
|
|
9
|
-
* (rambling, off-topic, a question), the extractor sets
|
|
10
|
-
* `not_a_decision=true` and the cairn short-circuits without writing a
|
|
11
|
-
* draft. This keeps the decisions ledger free of noise.
|
|
12
|
-
*/
|
|
13
|
-
import type { DecisionExtractorInput } from "./types.js";
|
|
14
|
-
export declare const DECISION_EXTRACTOR_SYSTEM_PROMPT = "You are the **decision-extractor** for an agent cairn. The operator just spoke a direction \u2014 a binding course-change like \"from now on, X\" or \"scrap that, go with Y\" or \"user_id always required on integration tables\". Your job is to capture it as a typed candidate decision so the cairn can present it for confirmation.\n\nYou read three things:\n1. The raw direction text the operator submitted.\n2. Author / source / received-at metadata for the audit record.\n3. (Optional) A short list of currently-accepted decisions so you can spot supersedes relationships.\n\nYou emit a single JSON object matching the supplied schema. Required fields:\n\n- `subject`: imperative one-line title. Example: \"Filter integration_oauth_tokens queries by user_id\".\n- `summary`: 2-4 sentence paragraph expanding the subject. Capture the *what* and the *why* as the operator stated them \u2014 do NOT invent rationale they didn't give.\n- `scope_globs`: repo-relative globs the decision binds. Be specific. `[\"core/src/integrations/**/*.ts\"]` is good; `[\"**/*.ts\"]` is almost always wrong. When you genuinely can't tell, emit `[]` and let the operator narrow at confirm time.\n- `supersedes`: if the input EXPLICITLY revokes a previously-accepted decision (`scrap DEC-0042`, `undo the FK denorm rule`), set the DEC-id. Otherwise null/omit.\n- `candidate_assertions`: 0-3 mechanical-sensor checks that would enforce the decision going forward. Pick the kind from the schema enum that fits. ZERO is a valid answer when the rule is purely conceptual \u2014 better than fabricating an assertion that can't actually be verified.\n- `confidence_signal`: `high` when the direction is unambiguous + scope is obvious; `medium` when one of those is shaky; `low` when both are.\n- `not_a_decision`: set TRUE if the input is rambling, off-topic, a question rather than a directive, or otherwise lacks a binding rule. The cairn will short-circuit without writing a draft. When in doubt, set true \u2014 false-positive drafts pollute the ledger; false-negatives are recoverable via re-submission.\n\nExamples of inputs that should map to `not_a_decision: true`:\n- \"what's the status?\"\n- \"I'm thinking about switching to FK denorm but not sure\" \u2190 thinking-out-loud, not yet binding\n- \"lol\"\n- \"remind me about Phase 12\"\n\nExamples that should map to `not_a_decision: false`:\n- \"scrap that \u2014 going forward, FK denormalization only\" \u2190 supersedes implicit\n- \"all integration_oauth_tokens queries must filter by user_id\" \u2190 clear assertion candidate\n- \"from now on, no new code in core/src/legacy\" \u2190 scope_globs + file_must_not_be_modified\n\nYour candidate_assertions are *proposals* \u2014 the operator gets one more chance to edit them at the confirm dialog. Don't over-commit; aim for the smallest set of assertions that mechanically captures the binding behavior, not every implication.\n\nOutput ONLY the JSON object. No prose, no code fences, no other content.";
|
|
15
|
-
export declare function buildDecisionExtractorUserPrompt(input: DecisionExtractorInput): string;
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decision-extractor prompts.
|
|
3
|
-
*
|
|
4
|
-
* Operator submits a direction (slash arg or free-text classified as
|
|
5
|
-
* `direction`). The extractor distills it into a typed candidate the
|
|
6
|
-
* cairn materializes into a draft decision.
|
|
7
|
-
*
|
|
8
|
-
* Anti-fabrication framing: when the input isn't actually a direction
|
|
9
|
-
* (rambling, off-topic, a question), the extractor sets
|
|
10
|
-
* `not_a_decision=true` and the cairn short-circuits without writing a
|
|
11
|
-
* draft. This keeps the decisions ledger free of noise.
|
|
12
|
-
*/
|
|
13
|
-
const PER_DIRECTION_CHAR_CAP = 6_000;
|
|
14
|
-
export const DECISION_EXTRACTOR_SYSTEM_PROMPT = `You are the **decision-extractor** for an agent cairn. The operator just spoke a direction — a binding course-change like "from now on, X" or "scrap that, go with Y" or "user_id always required on integration tables". Your job is to capture it as a typed candidate decision so the cairn can present it for confirmation.
|
|
15
|
-
|
|
16
|
-
You read three things:
|
|
17
|
-
1. The raw direction text the operator submitted.
|
|
18
|
-
2. Author / source / received-at metadata for the audit record.
|
|
19
|
-
3. (Optional) A short list of currently-accepted decisions so you can spot supersedes relationships.
|
|
20
|
-
|
|
21
|
-
You emit a single JSON object matching the supplied schema. Required fields:
|
|
22
|
-
|
|
23
|
-
- \`subject\`: imperative one-line title. Example: "Filter integration_oauth_tokens queries by user_id".
|
|
24
|
-
- \`summary\`: 2-4 sentence paragraph expanding the subject. Capture the *what* and the *why* as the operator stated them — do NOT invent rationale they didn't give.
|
|
25
|
-
- \`scope_globs\`: repo-relative globs the decision binds. Be specific. \`["core/src/integrations/**/*.ts"]\` is good; \`["**/*.ts"]\` is almost always wrong. When you genuinely can't tell, emit \`[]\` and let the operator narrow at confirm time.
|
|
26
|
-
- \`supersedes\`: if the input EXPLICITLY revokes a previously-accepted decision (\`scrap DEC-0042\`, \`undo the FK denorm rule\`), set the DEC-id. Otherwise null/omit.
|
|
27
|
-
- \`candidate_assertions\`: 0-3 mechanical-sensor checks that would enforce the decision going forward. Pick the kind from the schema enum that fits. ZERO is a valid answer when the rule is purely conceptual — better than fabricating an assertion that can't actually be verified.
|
|
28
|
-
- \`confidence_signal\`: \`high\` when the direction is unambiguous + scope is obvious; \`medium\` when one of those is shaky; \`low\` when both are.
|
|
29
|
-
- \`not_a_decision\`: set TRUE if the input is rambling, off-topic, a question rather than a directive, or otherwise lacks a binding rule. The cairn will short-circuit without writing a draft. When in doubt, set true — false-positive drafts pollute the ledger; false-negatives are recoverable via re-submission.
|
|
30
|
-
|
|
31
|
-
Examples of inputs that should map to \`not_a_decision: true\`:
|
|
32
|
-
- "what's the status?"
|
|
33
|
-
- "I'm thinking about switching to FK denorm but not sure" ← thinking-out-loud, not yet binding
|
|
34
|
-
- "lol"
|
|
35
|
-
- "remind me about Phase 12"
|
|
36
|
-
|
|
37
|
-
Examples that should map to \`not_a_decision: false\`:
|
|
38
|
-
- "scrap that — going forward, FK denormalization only" ← supersedes implicit
|
|
39
|
-
- "all integration_oauth_tokens queries must filter by user_id" ← clear assertion candidate
|
|
40
|
-
- "from now on, no new code in core/src/legacy" ← scope_globs + file_must_not_be_modified
|
|
41
|
-
|
|
42
|
-
Your candidate_assertions are *proposals* — the operator gets one more chance to edit them at the confirm dialog. Don't over-commit; aim for the smallest set of assertions that mechanically captures the binding behavior, not every implication.
|
|
43
|
-
|
|
44
|
-
Output ONLY the JSON object. No prose, no code fences, no other content.`;
|
|
45
|
-
export function buildDecisionExtractorUserPrompt(input) {
|
|
46
|
-
const sections = [];
|
|
47
|
-
sections.push("## Raw direction text");
|
|
48
|
-
const text = input.raw_text.trim();
|
|
49
|
-
sections.push(text.length > PER_DIRECTION_CHAR_CAP
|
|
50
|
-
? text.slice(0, PER_DIRECTION_CHAR_CAP) +
|
|
51
|
-
`\n…[truncated; ${text.length - PER_DIRECTION_CHAR_CAP} chars elided]`
|
|
52
|
-
: text);
|
|
53
|
-
sections.push("\n## Metadata");
|
|
54
|
-
sections.push(`author: ${input.author_id}`);
|
|
55
|
-
sections.push(`source: ${input.source}`);
|
|
56
|
-
sections.push(`received_at: ${input.received_at}`);
|
|
57
|
-
if (input.accepted_decisions && input.accepted_decisions.length > 0) {
|
|
58
|
-
sections.push("\n## Currently-accepted decisions (most recent first)");
|
|
59
|
-
for (const d of input.accepted_decisions.slice(0, 10)) {
|
|
60
|
-
sections.push(`- **${d.id}** — ${d.title} (${d.scope_summary})`);
|
|
61
|
-
}
|
|
62
|
-
sections.push("\nIf the new direction explicitly revokes one of these, set `supersedes` to its id.");
|
|
63
|
-
}
|
|
64
|
-
sections.push("\n## Your task");
|
|
65
|
-
sections.push("Extract the decision per the schema. Emit ONLY the JSON object.");
|
|
66
|
-
return sections.join("\n");
|
|
67
|
-
}
|
|
68
|
-
//# sourceMappingURL=prompt.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/decision-capture/prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,sBAAsB,GAAG,KAAK,CAAC;AAErC,MAAM,CAAC,MAAM,gCAAgC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yEA8ByB,CAAC;AAE1E,MAAM,UAAU,gCAAgC,CAC9C,KAA6B;IAE7B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,QAAQ,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,QAAQ,CAAC,IAAI,CACX,IAAI,CAAC,MAAM,GAAG,sBAAsB;QAClC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,CAAC;YACnC,kBAAkB,IAAI,CAAC,MAAM,GAAG,sBAAsB,gBAAgB;QAC1E,CAAC,CAAC,IAAI,CACT,CAAC;IAEF,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC/B,QAAQ,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IAC5C,QAAQ,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IAEnD,IAAI,KAAK,CAAC,kBAAkB,IAAI,KAAK,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpE,QAAQ,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;QACvE,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YACtD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC;QACpE,CAAC;QACD,QAAQ,CAAC,IAAI,CACX,qFAAqF,CACtF,CAAC;IACJ,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAChC,QAAQ,CAAC,IAAI,CACX,iEAAiE,CAClE,CAAC;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Assertion-refiner prompts.
|
|
3
|
-
*
|
|
4
|
-
* The decision-extractor (Phase 14) emits LOOSE candidate assertions —
|
|
5
|
-
* `{kind, description, parameters?}` with `parameters` schema-loose. The
|
|
6
|
-
* decision file stores them under frontmatter `candidate_assertions:`,
|
|
7
|
-
* NOT under `assertions:` which Layer-D sensors enforce.
|
|
8
|
-
*
|
|
9
|
-
* The refiner's job is to lift each candidate into a STRICT shape that
|
|
10
|
-
* matches one of the eleven `DecisionAssertion` kinds (see
|
|
11
|
-
* `src/ground/schemas.ts`). When a candidate is too vague to form
|
|
12
|
-
* confident strict params, the refiner DEMOTES it to
|
|
13
|
-
* `human_review_hint` (always soft, always passes zod). When the
|
|
14
|
-
* candidate description is sound but the strict params would need
|
|
15
|
-
* operator input the refiner can't infer, it SKIPS — the candidate
|
|
16
|
-
* survives in `candidate_assertions:` for the next refine pass.
|
|
17
|
-
*
|
|
18
|
-
* Anti-fabrication framing: prefer demote / skip over inventing wrong
|
|
19
|
-
* regex / globs / table names. A wrong assertion is a sensor that fires
|
|
20
|
-
* on every PR forever; a `human_review_hint` is at worst noise in the
|
|
21
|
-
* reviewer's pre-amble.
|
|
22
|
-
*/
|
|
23
|
-
import type { RefinerInput } from "./types.js";
|
|
24
|
-
export declare const REFINEMENT_PROPOSER_SYSTEM_PROMPT = "You are the **assertion-refiner** for an agent cairn. The operator just confirmed a binding decision; the decision-extractor proposed N loose candidate assertions to enforce it. Your job is to lift each candidate into the STRICT shape used by the cairn's mechanical sensors, OR demote / skip it.\n\n## The eleven assertion kinds\n\nEach kind requires specific fields. The cairn's zod re-validates at apply time; a malformed `strict_assertion` is auto-demoted, so don't fudge \u2014 when you don't have a confident value for a required field, set status=\"demote\" or status=\"skip\" instead.\n\n- **schema_must_contain** \u2014 { table: string, column: string, column_type?: string, nullable?: boolean }\n Migration / schema rule. Example: \"tokens table must have user_id column NOT NULL\".\n\n- **text_must_match** \u2014 { pattern: string (JS regex source), in_globs: string[] }\n Some text must appear in matching files. Example: license header in src/**/*.ts.\n\n- **text_must_not_match** \u2014 { pattern: string, in_globs: string[] }\n Some text must NOT appear. Example: \"no `process.env.` access in src/**/*.ts\".\n\n- **index_must_exist** \u2014 { table: string, columns: string[], where?: string }\n Database index. Example: \"(provider, user_id) WHERE archived_at IS NULL on tokens\".\n\n- **ast_pattern** \u2014 { language: string (\"ts\"|\"py\"|\"go\"|...), pattern: string (regex fallback), in_globs: string[] }\n Structural pattern. Example: \"all controllers extend BaseController\".\n\n- **file_must_not_be_modified** \u2014 { path: string }\n Frozen file. Example: \"core/src/legacy/billing.ts\".\n\n- **query_must_filter_by** \u2014 { orm: string (\"drizzle\"|\"prisma\"|\"sqlalchemy\"|...), in_globs: string[], table: string, columns: string[], operator: \"eq\"|\"in\"|\"between\"|\"is_not_null\", require_combination: \"and\"|\"or\" }\n ORM-level scope. Example: \"all integration_oauth_tokens queries filter by user_id eq AND provider eq\".\n\n- **route_must_have_guard** \u2014 { in_globs: string[], guard: string, require_on: string[] }\n HTTP guard. Example: \"all routes in api/*/admin.ts have RequireRole guard, require_on: [GET, POST]\".\n\n- **event_must_emit** \u2014 { in_globs: string[], after_method: string, event_key: string, payload_must_include?: string[] }\n Event emission. Example: \"after createInvoice() emit invoice.created with [invoice_id, user_id]\".\n\n- **service_method_must_call** \u2014 { in_globs: string[], in_method: string, must_call: string, before_returning?: boolean }\n Required call inside method. Example: \"in TokenService.refresh(), must call audit.log() before returning\".\n\n- **human_review_hint** \u2014 { description: string }\n Always-soft fallback. Use this for purely conceptual rules (\"prefer simple solutions\", \"avoid magic numbers in pricing logic\").\n\n## Per-candidate verdict\n\nFor each candidate, emit one proposal:\n\n```\n{\n candidate_id: <as given>,\n candidate_kind: <as given>,\n status: \"lift\" | \"demote\" | \"skip\",\n confidence_signal: \"high\" | \"medium\" | \"low\",\n strict_assertion?: { ... } // present iff status=\"lift\"\n rationale: \"one sentence explaining the choice\"\n}\n```\n\n### When to LIFT\n\nYou are confident on every required field for the candidate's kind. The description gave you concrete table / file / regex / glob names, and the decision's scope_globs lets you narrow the in_globs reasonably.\n\nIf the candidate kind is **human_review_hint**, ALWAYS lift \u2014 the kind already has a single-field shape. `description` is the candidate's existing description.\n\n### When to DEMOTE\n\nThe candidate description is sound but the strict params would require input you don't have (e.g., \"no env vars\" \u2014 needs the actual regex pattern; \"must filter by user_id\" \u2014 needs the ORM name and table name and you don't know which).\n\nDemote means: rewrite as `human_review_hint` with a description that captures the rule's intent. The operator + reviewer + UAT still see it; sensors don't enforce it. Better than a hallucinated regex that fires on every PR.\n\n### When to SKIP\n\nThe candidate is weakly-specified to the point that even `human_review_hint` would be too vague to be useful (e.g., the operator's description was \"fix the thing\", the kind doesn't match the description, etc.). Skip leaves it under `candidate_assertions:` for a future refine pass.\n\n## Confidence\n\n- `high`: required fields are explicit in the candidate description. No guesses.\n- `medium`: most fields present, one or two reasonable inferences from scope_globs / decision summary.\n- `low`: status=\"lift\" with low confidence is a defect. Use status=\"demote\" or \"skip\" instead.\n\n## Output\n\nEmit ONLY the JSON object: `{ \"proposals\": [...] }`. One proposal per input candidate, in the order given. No prose, no code fences.";
|
|
25
|
-
export declare function buildRefinementProposerUserPrompt(input: RefinerInput): string;
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Assertion-refiner prompts.
|
|
3
|
-
*
|
|
4
|
-
* The decision-extractor (Phase 14) emits LOOSE candidate assertions —
|
|
5
|
-
* `{kind, description, parameters?}` with `parameters` schema-loose. The
|
|
6
|
-
* decision file stores them under frontmatter `candidate_assertions:`,
|
|
7
|
-
* NOT under `assertions:` which Layer-D sensors enforce.
|
|
8
|
-
*
|
|
9
|
-
* The refiner's job is to lift each candidate into a STRICT shape that
|
|
10
|
-
* matches one of the eleven `DecisionAssertion` kinds (see
|
|
11
|
-
* `src/ground/schemas.ts`). When a candidate is too vague to form
|
|
12
|
-
* confident strict params, the refiner DEMOTES it to
|
|
13
|
-
* `human_review_hint` (always soft, always passes zod). When the
|
|
14
|
-
* candidate description is sound but the strict params would need
|
|
15
|
-
* operator input the refiner can't infer, it SKIPS — the candidate
|
|
16
|
-
* survives in `candidate_assertions:` for the next refine pass.
|
|
17
|
-
*
|
|
18
|
-
* Anti-fabrication framing: prefer demote / skip over inventing wrong
|
|
19
|
-
* regex / globs / table names. A wrong assertion is a sensor that fires
|
|
20
|
-
* on every PR forever; a `human_review_hint` is at worst noise in the
|
|
21
|
-
* reviewer's pre-amble.
|
|
22
|
-
*/
|
|
23
|
-
const PER_DECISION_CHAR_CAP = 4_000;
|
|
24
|
-
export const REFINEMENT_PROPOSER_SYSTEM_PROMPT = `You are the **assertion-refiner** for an agent cairn. The operator just confirmed a binding decision; the decision-extractor proposed N loose candidate assertions to enforce it. Your job is to lift each candidate into the STRICT shape used by the cairn's mechanical sensors, OR demote / skip it.
|
|
25
|
-
|
|
26
|
-
## The eleven assertion kinds
|
|
27
|
-
|
|
28
|
-
Each kind requires specific fields. The cairn's zod re-validates at apply time; a malformed \`strict_assertion\` is auto-demoted, so don't fudge — when you don't have a confident value for a required field, set status="demote" or status="skip" instead.
|
|
29
|
-
|
|
30
|
-
- **schema_must_contain** — { table: string, column: string, column_type?: string, nullable?: boolean }
|
|
31
|
-
Migration / schema rule. Example: "tokens table must have user_id column NOT NULL".
|
|
32
|
-
|
|
33
|
-
- **text_must_match** — { pattern: string (JS regex source), in_globs: string[] }
|
|
34
|
-
Some text must appear in matching files. Example: license header in src/**/*.ts.
|
|
35
|
-
|
|
36
|
-
- **text_must_not_match** — { pattern: string, in_globs: string[] }
|
|
37
|
-
Some text must NOT appear. Example: "no \`process.env.\` access in src/**/*.ts".
|
|
38
|
-
|
|
39
|
-
- **index_must_exist** — { table: string, columns: string[], where?: string }
|
|
40
|
-
Database index. Example: "(provider, user_id) WHERE archived_at IS NULL on tokens".
|
|
41
|
-
|
|
42
|
-
- **ast_pattern** — { language: string ("ts"|"py"|"go"|...), pattern: string (regex fallback), in_globs: string[] }
|
|
43
|
-
Structural pattern. Example: "all controllers extend BaseController".
|
|
44
|
-
|
|
45
|
-
- **file_must_not_be_modified** — { path: string }
|
|
46
|
-
Frozen file. Example: "core/src/legacy/billing.ts".
|
|
47
|
-
|
|
48
|
-
- **query_must_filter_by** — { orm: string ("drizzle"|"prisma"|"sqlalchemy"|...), in_globs: string[], table: string, columns: string[], operator: "eq"|"in"|"between"|"is_not_null", require_combination: "and"|"or" }
|
|
49
|
-
ORM-level scope. Example: "all integration_oauth_tokens queries filter by user_id eq AND provider eq".
|
|
50
|
-
|
|
51
|
-
- **route_must_have_guard** — { in_globs: string[], guard: string, require_on: string[] }
|
|
52
|
-
HTTP guard. Example: "all routes in api/*/admin.ts have RequireRole guard, require_on: [GET, POST]".
|
|
53
|
-
|
|
54
|
-
- **event_must_emit** — { in_globs: string[], after_method: string, event_key: string, payload_must_include?: string[] }
|
|
55
|
-
Event emission. Example: "after createInvoice() emit invoice.created with [invoice_id, user_id]".
|
|
56
|
-
|
|
57
|
-
- **service_method_must_call** — { in_globs: string[], in_method: string, must_call: string, before_returning?: boolean }
|
|
58
|
-
Required call inside method. Example: "in TokenService.refresh(), must call audit.log() before returning".
|
|
59
|
-
|
|
60
|
-
- **human_review_hint** — { description: string }
|
|
61
|
-
Always-soft fallback. Use this for purely conceptual rules ("prefer simple solutions", "avoid magic numbers in pricing logic").
|
|
62
|
-
|
|
63
|
-
## Per-candidate verdict
|
|
64
|
-
|
|
65
|
-
For each candidate, emit one proposal:
|
|
66
|
-
|
|
67
|
-
\`\`\`
|
|
68
|
-
{
|
|
69
|
-
candidate_id: <as given>,
|
|
70
|
-
candidate_kind: <as given>,
|
|
71
|
-
status: "lift" | "demote" | "skip",
|
|
72
|
-
confidence_signal: "high" | "medium" | "low",
|
|
73
|
-
strict_assertion?: { ... } // present iff status="lift"
|
|
74
|
-
rationale: "one sentence explaining the choice"
|
|
75
|
-
}
|
|
76
|
-
\`\`\`
|
|
77
|
-
|
|
78
|
-
### When to LIFT
|
|
79
|
-
|
|
80
|
-
You are confident on every required field for the candidate's kind. The description gave you concrete table / file / regex / glob names, and the decision's scope_globs lets you narrow the in_globs reasonably.
|
|
81
|
-
|
|
82
|
-
If the candidate kind is **human_review_hint**, ALWAYS lift — the kind already has a single-field shape. \`description\` is the candidate's existing description.
|
|
83
|
-
|
|
84
|
-
### When to DEMOTE
|
|
85
|
-
|
|
86
|
-
The candidate description is sound but the strict params would require input you don't have (e.g., "no env vars" — needs the actual regex pattern; "must filter by user_id" — needs the ORM name and table name and you don't know which).
|
|
87
|
-
|
|
88
|
-
Demote means: rewrite as \`human_review_hint\` with a description that captures the rule's intent. The operator + reviewer + UAT still see it; sensors don't enforce it. Better than a hallucinated regex that fires on every PR.
|
|
89
|
-
|
|
90
|
-
### When to SKIP
|
|
91
|
-
|
|
92
|
-
The candidate is weakly-specified to the point that even \`human_review_hint\` would be too vague to be useful (e.g., the operator's description was "fix the thing", the kind doesn't match the description, etc.). Skip leaves it under \`candidate_assertions:\` for a future refine pass.
|
|
93
|
-
|
|
94
|
-
## Confidence
|
|
95
|
-
|
|
96
|
-
- \`high\`: required fields are explicit in the candidate description. No guesses.
|
|
97
|
-
- \`medium\`: most fields present, one or two reasonable inferences from scope_globs / decision summary.
|
|
98
|
-
- \`low\`: status="lift" with low confidence is a defect. Use status="demote" or "skip" instead.
|
|
99
|
-
|
|
100
|
-
## Output
|
|
101
|
-
|
|
102
|
-
Emit ONLY the JSON object: \`{ "proposals": [...] }\`. One proposal per input candidate, in the order given. No prose, no code fences.`;
|
|
103
|
-
export function buildRefinementProposerUserPrompt(input) {
|
|
104
|
-
const sections = [];
|
|
105
|
-
sections.push(`## Decision context — ${input.decision_id}`);
|
|
106
|
-
sections.push(`subject: ${input.subject}`);
|
|
107
|
-
const summary = input.summary.trim();
|
|
108
|
-
sections.push("");
|
|
109
|
-
sections.push("summary:");
|
|
110
|
-
sections.push(summary.length > PER_DECISION_CHAR_CAP
|
|
111
|
-
? summary.slice(0, PER_DECISION_CHAR_CAP) +
|
|
112
|
-
`\n…[truncated; ${summary.length - PER_DECISION_CHAR_CAP} chars elided]`
|
|
113
|
-
: summary);
|
|
114
|
-
if (input.scope_globs.length > 0) {
|
|
115
|
-
sections.push("");
|
|
116
|
-
sections.push("scope_globs:");
|
|
117
|
-
for (const g of input.scope_globs)
|
|
118
|
-
sections.push(` - ${g}`);
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
sections.push("");
|
|
122
|
-
sections.push("scope_globs: (none — operator left it unspecified)");
|
|
123
|
-
}
|
|
124
|
-
sections.push("");
|
|
125
|
-
sections.push("## Candidates to refine");
|
|
126
|
-
for (let i = 0; i < input.candidates.length; i++) {
|
|
127
|
-
const c = input.candidates[i];
|
|
128
|
-
if (c === undefined)
|
|
129
|
-
continue;
|
|
130
|
-
const id = c.id ?? `${input.decision_id}-A${(i + 1).toString().padStart(2, "0")}`;
|
|
131
|
-
sections.push("");
|
|
132
|
-
sections.push(`### ${id} (kind: ${c.kind})`);
|
|
133
|
-
sections.push(`description: ${c.description}`);
|
|
134
|
-
if (c.parameters && Object.keys(c.parameters).length > 0) {
|
|
135
|
-
sections.push("parameters (loose, from extractor):");
|
|
136
|
-
sections.push("```json");
|
|
137
|
-
sections.push(JSON.stringify(c.parameters, null, 2));
|
|
138
|
-
sections.push("```");
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
sections.push("");
|
|
142
|
-
sections.push("## Your task");
|
|
143
|
-
sections.push("Emit one proposal per candidate in the order given. Use the candidate_id values shown above. Output ONLY the JSON object.");
|
|
144
|
-
return sections.join("\n");
|
|
145
|
-
}
|
|
146
|
-
//# sourceMappingURL=refinement-prompt.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"refinement-prompt.js","sourceRoot":"","sources":["../../src/decision-capture/refinement-prompt.ts"],"names":[],"mappings":"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"}
|