openplanr 1.2.6 → 1.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -1
- package/dist/ai/prompts/prompt-builder.d.ts +48 -0
- package/dist/ai/prompts/prompt-builder.d.ts.map +1 -1
- package/dist/ai/prompts/prompt-builder.js +57 -1
- package/dist/ai/prompts/prompt-builder.js.map +1 -1
- package/dist/ai/prompts/system-prompts.d.ts +23 -0
- package/dist/ai/prompts/system-prompts.d.ts.map +1 -1
- package/dist/ai/prompts/system-prompts.js +98 -0
- package/dist/ai/prompts/system-prompts.js.map +1 -1
- package/dist/ai/schemas/ai-response-schemas.d.ts +68 -0
- package/dist/ai/schemas/ai-response-schemas.d.ts.map +1 -1
- package/dist/ai/schemas/ai-response-schemas.js +81 -0
- package/dist/ai/schemas/ai-response-schemas.js.map +1 -1
- package/dist/ai/types.d.ts +2 -0
- package/dist/ai/types.d.ts.map +1 -1
- package/dist/ai/types.js +2 -0
- package/dist/ai/types.js.map +1 -1
- package/dist/cli/commands/context.d.ts +6 -0
- package/dist/cli/commands/context.d.ts.map +1 -0
- package/dist/cli/commands/context.js +45 -0
- package/dist/cli/commands/context.js.map +1 -0
- package/dist/cli/commands/export.d.ts.map +1 -1
- package/dist/cli/commands/export.js +8 -0
- package/dist/cli/commands/export.js.map +1 -1
- package/dist/cli/commands/report-linter.d.ts +6 -0
- package/dist/cli/commands/report-linter.d.ts.map +1 -0
- package/dist/cli/commands/report-linter.js +61 -0
- package/dist/cli/commands/report-linter.js.map +1 -0
- package/dist/cli/commands/report.d.ts +6 -0
- package/dist/cli/commands/report.d.ts.map +1 -0
- package/dist/cli/commands/report.js +150 -0
- package/dist/cli/commands/report.js.map +1 -0
- package/dist/cli/commands/revise.d.ts +23 -0
- package/dist/cli/commands/revise.d.ts.map +1 -0
- package/dist/cli/commands/revise.js +502 -0
- package/dist/cli/commands/revise.js.map +1 -0
- package/dist/cli/commands/story.d.ts.map +1 -1
- package/dist/cli/commands/story.js +31 -0
- package/dist/cli/commands/story.js.map +1 -1
- package/dist/cli/commands/voice.d.ts +6 -0
- package/dist/cli/commands/voice.d.ts.map +1 -0
- package/dist/cli/commands/voice.js +64 -0
- package/dist/cli/commands/voice.js.map +1 -0
- package/dist/cli/index.js +10 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/models/schema.d.ts +63 -0
- package/dist/models/schema.d.ts.map +1 -1
- package/dist/models/schema.js +31 -0
- package/dist/models/schema.js.map +1 -1
- package/dist/models/types.d.ts +280 -0
- package/dist/models/types.d.ts.map +1 -1
- package/dist/services/atomic-write-service.d.ts +41 -0
- package/dist/services/atomic-write-service.d.ts.map +1 -0
- package/dist/services/atomic-write-service.js +87 -0
- package/dist/services/atomic-write-service.js.map +1 -0
- package/dist/services/audit-log-service.d.ts +50 -0
- package/dist/services/audit-log-service.d.ts.map +1 -0
- package/dist/services/audit-log-service.js +213 -0
- package/dist/services/audit-log-service.js.map +1 -0
- package/dist/services/cascade-service.d.ts +62 -0
- package/dist/services/cascade-service.d.ts.map +1 -0
- package/dist/services/cascade-service.js +189 -0
- package/dist/services/cascade-service.js.map +1 -0
- package/dist/services/context-pack-service.d.ts +12 -0
- package/dist/services/context-pack-service.d.ts.map +1 -0
- package/dist/services/context-pack-service.js +155 -0
- package/dist/services/context-pack-service.js.map +1 -0
- package/dist/services/diff-service.d.ts +18 -0
- package/dist/services/diff-service.d.ts.map +1 -0
- package/dist/services/diff-service.js +35 -0
- package/dist/services/diff-service.js.map +1 -0
- package/dist/services/distribution-service.d.ts +18 -0
- package/dist/services/distribution-service.d.ts.map +1 -0
- package/dist/services/distribution-service.js +104 -0
- package/dist/services/distribution-service.js.map +1 -0
- package/dist/services/evidence-service.d.ts +17 -0
- package/dist/services/evidence-service.d.ts.map +1 -0
- package/dist/services/evidence-service.js +85 -0
- package/dist/services/evidence-service.js.map +1 -0
- package/dist/services/evidence-verifier.d.ts +71 -0
- package/dist/services/evidence-verifier.d.ts.map +1 -0
- package/dist/services/evidence-verifier.js +171 -0
- package/dist/services/evidence-verifier.js.map +1 -0
- package/dist/services/git-service.d.ts +60 -0
- package/dist/services/git-service.d.ts.map +1 -0
- package/dist/services/git-service.js +137 -0
- package/dist/services/git-service.js.map +1 -0
- package/dist/services/github-service.d.ts +28 -1
- package/dist/services/github-service.d.ts.map +1 -1
- package/dist/services/github-service.js +95 -0
- package/dist/services/github-service.js.map +1 -1
- package/dist/services/graph-integrity.d.ts +36 -0
- package/dist/services/graph-integrity.d.ts.map +1 -0
- package/dist/services/graph-integrity.js +54 -0
- package/dist/services/graph-integrity.js.map +1 -0
- package/dist/services/prompt-service.d.ts +18 -0
- package/dist/services/prompt-service.d.ts.map +1 -1
- package/dist/services/prompt-service.js +47 -0
- package/dist/services/prompt-service.js.map +1 -1
- package/dist/services/report-linter-service.d.ts +10 -0
- package/dist/services/report-linter-service.d.ts.map +1 -0
- package/dist/services/report-linter-service.js +95 -0
- package/dist/services/report-linter-service.js.map +1 -0
- package/dist/services/report-service.d.ts +37 -0
- package/dist/services/report-service.d.ts.map +1 -0
- package/dist/services/report-service.js +173 -0
- package/dist/services/report-service.js.map +1 -0
- package/dist/services/revise-cache-service.d.ts +46 -0
- package/dist/services/revise-cache-service.d.ts.map +1 -0
- package/dist/services/revise-cache-service.js +88 -0
- package/dist/services/revise-cache-service.js.map +1 -0
- package/dist/services/revise-service.d.ts +108 -0
- package/dist/services/revise-service.d.ts.map +1 -0
- package/dist/services/revise-service.js +249 -0
- package/dist/services/revise-service.js.map +1 -0
- package/dist/services/standup-parser.d.ts +21 -0
- package/dist/services/standup-parser.d.ts.map +1 -0
- package/dist/services/standup-parser.js +104 -0
- package/dist/services/standup-parser.js.map +1 -0
- package/dist/services/story-standup-service.d.ts +7 -0
- package/dist/services/story-standup-service.d.ts.map +1 -0
- package/dist/services/story-standup-service.js +27 -0
- package/dist/services/story-standup-service.js.map +1 -0
- package/dist/services/template-sections.d.ts +28 -0
- package/dist/services/template-sections.d.ts.map +1 -0
- package/dist/services/template-sections.js +55 -0
- package/dist/services/template-sections.js.map +1 -0
- package/dist/services/template-service.d.ts.map +1 -1
- package/dist/services/template-service.js +1 -0
- package/dist/services/template-service.js.map +1 -1
- package/dist/services/voice-service.d.ts +12 -0
- package/dist/services/voice-service.d.ts.map +1 -0
- package/dist/services/voice-service.js +42 -0
- package/dist/services/voice-service.js.map +1 -0
- package/dist/templates/export/planning-report.html.hbs +10 -0
- package/dist/templates/export/planning-report.md.hbs +11 -0
- package/dist/templates/linter/linter-config.json.hbs +13 -0
- package/dist/templates/reports/executive.md.hbs +28 -0
- package/dist/templates/reports/release-notes.md.hbs +37 -0
- package/dist/templates/reports/retrospective.md.hbs +36 -0
- package/dist/templates/reports/sprint.md.hbs +91 -0
- package/dist/templates/reports/standup.md.hbs +27 -0
- package/dist/templates/reports/weekly.md.hbs +42 -0
- package/dist/templates/voice/standup.md.hbs +20 -0
- package/dist/utils/diff.d.ts +26 -0
- package/dist/utils/diff.d.ts.map +1 -0
- package/dist/utils/diff.js +143 -0
- package/dist/utils/diff.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evidence linking and validation for stakeholder reports.
|
|
3
|
+
*/
|
|
4
|
+
import { validateRepoAccessible } from './github-service.js';
|
|
5
|
+
const URL_RE = /https?:\/\/[^\s)]+/g;
|
|
6
|
+
const ISSUE_RE = /(?:#|GH-)\d+/gi;
|
|
7
|
+
export function countEvidenceAnchors(markdown) {
|
|
8
|
+
const urls = markdown.match(URL_RE) ?? [];
|
|
9
|
+
const issues = markdown.match(ISSUE_RE) ?? [];
|
|
10
|
+
return urls.length + issues.length;
|
|
11
|
+
}
|
|
12
|
+
function shouldSkipStrictEvidenceSection(heading) {
|
|
13
|
+
return /^\s*evidence\b/i.test(heading);
|
|
14
|
+
}
|
|
15
|
+
/** Template placeholder bullets (italic instructions) are not treated as factual claims. */
|
|
16
|
+
function isPlaceholderClaimBullet(line) {
|
|
17
|
+
const m = line.match(/^\s*[-*]\s+(.+)$/);
|
|
18
|
+
if (!m)
|
|
19
|
+
return false;
|
|
20
|
+
const t = m[1].trim();
|
|
21
|
+
return /^_.+_$/s.test(t);
|
|
22
|
+
}
|
|
23
|
+
export function validateClaimsHaveAnchors(markdown, minAnchors, options) {
|
|
24
|
+
void options?.reportType;
|
|
25
|
+
const sections = markdown.split(/^## /m).slice(1);
|
|
26
|
+
const results = [];
|
|
27
|
+
let idx = 0;
|
|
28
|
+
for (const chunk of sections) {
|
|
29
|
+
idx += 1;
|
|
30
|
+
const lines = chunk.split('\n');
|
|
31
|
+
const heading = lines[0]?.trim() ?? `section-${idx}`;
|
|
32
|
+
if (shouldSkipStrictEvidenceSection(heading)) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const body = lines.slice(1).join('\n');
|
|
36
|
+
const bullets = body.split('\n').filter((l) => /^\s*[-*]\s+/.test(l));
|
|
37
|
+
for (let j = 0; j < bullets.length; j += 1) {
|
|
38
|
+
const line = bullets[j];
|
|
39
|
+
if (isPlaceholderClaimBullet(line)) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const n = countEvidenceAnchors(line);
|
|
43
|
+
const claimId = `${heading}:${j}`;
|
|
44
|
+
if (n < minAnchors) {
|
|
45
|
+
results.push({
|
|
46
|
+
claimId,
|
|
47
|
+
ok: false,
|
|
48
|
+
missingReason: 'No link or issue reference found for this bullet; add a PR URL, commit, or #issue.',
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
results.push({ claimId, ok: true });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return results;
|
|
57
|
+
}
|
|
58
|
+
export async function validateRemoteEvidence(items) {
|
|
59
|
+
const repo = await validateRepoAccessible();
|
|
60
|
+
const inaccessible = [];
|
|
61
|
+
for (const it of items) {
|
|
62
|
+
if (!it.url)
|
|
63
|
+
continue;
|
|
64
|
+
try {
|
|
65
|
+
const u = new URL(it.url);
|
|
66
|
+
if (u.hostname !== 'github.com')
|
|
67
|
+
continue;
|
|
68
|
+
// Lightweight check only — full HTTP HEAD would add dependency noise
|
|
69
|
+
if (!repo.ok)
|
|
70
|
+
inaccessible.push(it);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
inaccessible.push(it);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return { inaccessible, repoOk: repo.ok, repoMessage: repo.message };
|
|
77
|
+
}
|
|
78
|
+
export function summarizeEvidenceItem(item) {
|
|
79
|
+
return {
|
|
80
|
+
evidenceId: item.id,
|
|
81
|
+
title: item.label,
|
|
82
|
+
body: [item.detail, item.url].filter(Boolean).join('\n'),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=evidence-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence-service.js","sourceRoot":"","sources":["../../src/services/evidence-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-flight evidence verification for `planr revise` (EPIC-003, FEAT-011).
|
|
3
|
+
*
|
|
4
|
+
* The revise agent emits a ReviseDecision with typed evidence citations. Before
|
|
5
|
+
* the user ever sees a diff, this verifier checks each citation against the
|
|
6
|
+
* real repo:
|
|
7
|
+
*
|
|
8
|
+
* - `file_exists` / `file_absent` — fs.stat on the ref path
|
|
9
|
+
* - `grep_match` — literal check inside the codebase context
|
|
10
|
+
* the agent was given; rejects claims the
|
|
11
|
+
* agent could not have seen
|
|
12
|
+
* - `sibling_artifact` — artifact id must exist on disk
|
|
13
|
+
* - `source_quote` — source path must exist on disk (quote
|
|
14
|
+
* fuzzy-match is best-effort)
|
|
15
|
+
* - `pattern_rule` — rule id must be in the detected pattern
|
|
16
|
+
* rules for this run
|
|
17
|
+
*
|
|
18
|
+
* Unverifiable evidence is dropped with a reason. If a `revise` action has no
|
|
19
|
+
* surviving evidence after the sweep, the decision is demoted to `flag` with
|
|
20
|
+
* an explicit ambiguity entry — the agent's judgment wasn't necessarily wrong,
|
|
21
|
+
* but its *proof* can't be trusted, so a human owns the call.
|
|
22
|
+
*/
|
|
23
|
+
import type { OpenPlanrConfig, ReviseDecision, ReviseEvidence } from '../models/types.js';
|
|
24
|
+
/**
|
|
25
|
+
* Run-time context the verifier needs. Callers should populate this from the
|
|
26
|
+
* same inputs used to build the revise prompt, so the verifier checks evidence
|
|
27
|
+
* against exactly the material the agent had access to.
|
|
28
|
+
*/
|
|
29
|
+
export interface EvidenceVerifierContext {
|
|
30
|
+
projectDir: string;
|
|
31
|
+
config: OpenPlanrConfig;
|
|
32
|
+
/**
|
|
33
|
+
* Directory of the artifact being verified. Used to resolve relative
|
|
34
|
+
* evidence refs like `../features/FEAT-001-slug.md` that appear in
|
|
35
|
+
* markdown cross-reference links (those paths are relative to the
|
|
36
|
+
* artifact's file location, not to projectDir). Falls back to projectDir
|
|
37
|
+
* when omitted.
|
|
38
|
+
*/
|
|
39
|
+
artifactDir?: string;
|
|
40
|
+
/** Concatenated string from `formatCodebaseContext`; undefined in fast mode. */
|
|
41
|
+
codebaseContextFormatted?: string;
|
|
42
|
+
/** Labels (paths or URLs) of declared sources supplied to the agent. */
|
|
43
|
+
knownSourceRefs: string[];
|
|
44
|
+
/** Pattern rule ids detected in the codebase context (from pattern-rules). */
|
|
45
|
+
knownPatternRuleIds: string[];
|
|
46
|
+
}
|
|
47
|
+
export interface DroppedEvidence {
|
|
48
|
+
evidence: ReviseEvidence;
|
|
49
|
+
reason: string;
|
|
50
|
+
}
|
|
51
|
+
export interface DecisionVerificationResult {
|
|
52
|
+
/** Possibly-rewritten decision (evidence filtered; action demoted if needed). */
|
|
53
|
+
decision: ReviseDecision;
|
|
54
|
+
/** Evidence items that failed verification and were removed from the decision. */
|
|
55
|
+
dropped: DroppedEvidence[];
|
|
56
|
+
/** True when the verifier changed the action (e.g., revise → flag). */
|
|
57
|
+
demoted: boolean;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Verify every evidence item in a decision; drop anything unverifiable.
|
|
61
|
+
* Demote `revise` to `flag` when no verifiable evidence remains.
|
|
62
|
+
*/
|
|
63
|
+
export declare function verifyDecision(decision: ReviseDecision, ctx: EvidenceVerifierContext): Promise<DecisionVerificationResult>;
|
|
64
|
+
interface EvidenceCheck {
|
|
65
|
+
ok: boolean;
|
|
66
|
+
reason: string;
|
|
67
|
+
}
|
|
68
|
+
/** Verify a single evidence item. Exported primarily for testing. */
|
|
69
|
+
export declare function verifyEvidence(ev: ReviseEvidence, ctx: EvidenceVerifierContext): Promise<EvidenceCheck>;
|
|
70
|
+
export {};
|
|
71
|
+
//# sourceMappingURL=evidence-verifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence-verifier.d.ts","sourceRoot":"","sources":["../../src/services/evidence-verifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,KAAK,EAEV,eAAe,EAEf,cAAc,EACd,cAAc,EACf,MAAM,oBAAoB,CAAC;AAI5B;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,eAAe,CAAC;IACxB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,wEAAwE;IACxE,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,8EAA8E;IAC9E,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,0BAA0B;IACzC,iFAAiF;IACjF,QAAQ,EAAE,cAAc,CAAC;IACzB,kFAAkF;IAClF,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,uEAAuE;IACvE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,cAAc,EACxB,GAAG,EAAE,uBAAuB,GAC3B,OAAO,CAAC,0BAA0B,CAAC,CAgErC;AAED,UAAU,aAAa;IACrB,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qEAAqE;AACrE,wBAAsB,cAAc,CAClC,EAAE,EAAE,cAAc,EAClB,GAAG,EAAE,uBAAuB,GAC3B,OAAO,CAAC,aAAa,CAAC,CAwDxB"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-flight evidence verification for `planr revise` (EPIC-003, FEAT-011).
|
|
3
|
+
*
|
|
4
|
+
* The revise agent emits a ReviseDecision with typed evidence citations. Before
|
|
5
|
+
* the user ever sees a diff, this verifier checks each citation against the
|
|
6
|
+
* real repo:
|
|
7
|
+
*
|
|
8
|
+
* - `file_exists` / `file_absent` — fs.stat on the ref path
|
|
9
|
+
* - `grep_match` — literal check inside the codebase context
|
|
10
|
+
* the agent was given; rejects claims the
|
|
11
|
+
* agent could not have seen
|
|
12
|
+
* - `sibling_artifact` — artifact id must exist on disk
|
|
13
|
+
* - `source_quote` — source path must exist on disk (quote
|
|
14
|
+
* fuzzy-match is best-effort)
|
|
15
|
+
* - `pattern_rule` — rule id must be in the detected pattern
|
|
16
|
+
* rules for this run
|
|
17
|
+
*
|
|
18
|
+
* Unverifiable evidence is dropped with a reason. If a `revise` action has no
|
|
19
|
+
* surviving evidence after the sweep, the decision is demoted to `flag` with
|
|
20
|
+
* an explicit ambiguity entry — the agent's judgment wasn't necessarily wrong,
|
|
21
|
+
* but its *proof* can't be trusted, so a human owns the call.
|
|
22
|
+
*/
|
|
23
|
+
import { stat } from 'node:fs/promises';
|
|
24
|
+
import path from 'node:path';
|
|
25
|
+
import { logger } from '../utils/logger.js';
|
|
26
|
+
import { findArtifactTypeById, listArtifacts, readArtifact } from './artifact-service.js';
|
|
27
|
+
/**
|
|
28
|
+
* Verify every evidence item in a decision; drop anything unverifiable.
|
|
29
|
+
* Demote `revise` to `flag` when no verifiable evidence remains.
|
|
30
|
+
*/
|
|
31
|
+
export async function verifyDecision(decision, ctx) {
|
|
32
|
+
const dropped = [];
|
|
33
|
+
const verified = [];
|
|
34
|
+
for (const ev of decision.evidence) {
|
|
35
|
+
const check = await verifyEvidence(ev, ctx);
|
|
36
|
+
if (check.ok) {
|
|
37
|
+
verified.push(ev);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
dropped.push({ evidence: ev, reason: check.reason });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (dropped.length > 0) {
|
|
44
|
+
logger.debug(`evidence-verifier: dropped ${dropped.length}/${decision.evidence.length} citations for ${decision.artifactId}`);
|
|
45
|
+
}
|
|
46
|
+
// Demotion rules for a `revise` action. We never silently apply a rewrite
|
|
47
|
+
// whose evidence base is weak. Two triggers:
|
|
48
|
+
//
|
|
49
|
+
// (a) `verified.length === 0` — no evidence survived at all
|
|
50
|
+
// (b) `dropped.length > verified.length` — a majority of the agent's
|
|
51
|
+
// evidence was unverifiable. This catches the failure mode where
|
|
52
|
+
// the agent cites one true thing and several hallucinated ones;
|
|
53
|
+
// without this rule a 1-out-of-6 verification rate passes through
|
|
54
|
+
// because at least one citation survives.
|
|
55
|
+
//
|
|
56
|
+
// Both rules target `revise` specifically — `flag` decisions are already
|
|
57
|
+
// asking for human review, and `skip` decisions don't change anything.
|
|
58
|
+
const shouldDemote = decision.action === 'revise' && (verified.length === 0 || dropped.length > verified.length);
|
|
59
|
+
if (shouldDemote) {
|
|
60
|
+
const reason = verified.length === 0
|
|
61
|
+
? 'Agent proposed a revision but none of its evidence citations could be verified against the repo. Human review required.'
|
|
62
|
+
: `Agent proposed a revision but a majority of its evidence citations (${dropped.length}/${dropped.length + verified.length}) could not be verified. Most likely hallucinated — human review required.`;
|
|
63
|
+
const tag = verified.length === 0 ? 'all evidence unverifiable' : 'majority evidence unverifiable';
|
|
64
|
+
const ambiguity = {
|
|
65
|
+
section: '(evidence verification)',
|
|
66
|
+
reason,
|
|
67
|
+
};
|
|
68
|
+
return {
|
|
69
|
+
decision: {
|
|
70
|
+
...decision,
|
|
71
|
+
action: 'flag',
|
|
72
|
+
evidence: verified, // keep any surviving citations in the flag record
|
|
73
|
+
revisedMarkdown: undefined,
|
|
74
|
+
ambiguous: [...decision.ambiguous, ambiguity],
|
|
75
|
+
rationale: `${decision.rationale} [demoted: ${tag}]`,
|
|
76
|
+
},
|
|
77
|
+
dropped,
|
|
78
|
+
demoted: true,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
decision: { ...decision, evidence: verified },
|
|
83
|
+
dropped,
|
|
84
|
+
demoted: false,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** Verify a single evidence item. Exported primarily for testing. */
|
|
88
|
+
export async function verifyEvidence(ev, ctx) {
|
|
89
|
+
switch (ev.type) {
|
|
90
|
+
case 'file_exists':
|
|
91
|
+
return (await pathExists(ctx.projectDir, ev.ref, ctx.artifactDir))
|
|
92
|
+
? ok()
|
|
93
|
+
: fail(`cited file does not exist: ${ev.ref}`);
|
|
94
|
+
case 'file_absent':
|
|
95
|
+
return (await pathExists(ctx.projectDir, ev.ref, ctx.artifactDir))
|
|
96
|
+
? fail(`cited file IS present in the repo, contradicting 'file_absent': ${ev.ref}`)
|
|
97
|
+
: ok();
|
|
98
|
+
case 'grep_match':
|
|
99
|
+
if (!ctx.codebaseContextFormatted) {
|
|
100
|
+
return fail('grep_match citation requires codebase context, but context was not loaded (fast mode)');
|
|
101
|
+
}
|
|
102
|
+
// Require either ref OR quote to appear in the context the agent saw.
|
|
103
|
+
if (ctx.codebaseContextFormatted.includes(ev.ref) ||
|
|
104
|
+
(ev.quote && ctx.codebaseContextFormatted.includes(ev.quote))) {
|
|
105
|
+
return ok();
|
|
106
|
+
}
|
|
107
|
+
return fail(`grep_match token not found in codebase context: ${ev.ref}`);
|
|
108
|
+
case 'sibling_artifact': {
|
|
109
|
+
const type = findArtifactTypeById(ev.ref);
|
|
110
|
+
if (!type) {
|
|
111
|
+
return fail(`sibling_artifact ref is not a recognizable artifact id: ${ev.ref}`);
|
|
112
|
+
}
|
|
113
|
+
return (await artifactExists(ctx.projectDir, ctx.config, type, ev.ref))
|
|
114
|
+
? ok()
|
|
115
|
+
: fail(`sibling_artifact not found on disk: ${ev.ref}`);
|
|
116
|
+
}
|
|
117
|
+
case 'source_quote':
|
|
118
|
+
// Source refs are labels/paths declared in .planr/revise.yaml; the
|
|
119
|
+
// caller has already globbed them, so we validate against that list.
|
|
120
|
+
return ctx.knownSourceRefs.includes(ev.ref)
|
|
121
|
+
? ok()
|
|
122
|
+
: fail(`source_quote ref is not a declared source: ${ev.ref}`);
|
|
123
|
+
case 'pattern_rule':
|
|
124
|
+
return ctx.knownPatternRuleIds.includes(ev.ref)
|
|
125
|
+
? ok()
|
|
126
|
+
: fail(`pattern_rule ref is not a detected pattern rule: ${ev.ref}`);
|
|
127
|
+
default: {
|
|
128
|
+
// Exhaustive check — if a new evidence type is added to the TS union
|
|
129
|
+
// but not here, the compiler will complain.
|
|
130
|
+
const _exhaustive = ev.type;
|
|
131
|
+
return fail(`unhandled evidence type: ${String(_exhaustive)}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const ok = () => ({ ok: true, reason: '' });
|
|
136
|
+
const fail = (reason) => ({ ok: false, reason });
|
|
137
|
+
async function pathExists(projectDir, ref, artifactDir) {
|
|
138
|
+
// Choose resolution base:
|
|
139
|
+
// - Relative refs (`./` or `../`) resolve against the artifact's directory
|
|
140
|
+
// when available, because OpenPlanr's cross-reference convention writes
|
|
141
|
+
// paths like `../features/FEAT-001-slug.md` relative to the artifact file.
|
|
142
|
+
// - Everything else (repo-root-style refs like `src/services/foo.ts`) resolves
|
|
143
|
+
// against projectDir.
|
|
144
|
+
const looksRelative = ref.startsWith('./') || ref.startsWith('../');
|
|
145
|
+
const base = looksRelative && artifactDir ? artifactDir : projectDir;
|
|
146
|
+
const resolved = path.resolve(base, ref);
|
|
147
|
+
const normalized = path.normalize(resolved);
|
|
148
|
+
// Traversal guard — the final path must still land inside projectDir
|
|
149
|
+
// (after following any `../`). This blocks probes like `../../../etc/passwd`
|
|
150
|
+
// while allowing legitimate artifact→sibling-dir references.
|
|
151
|
+
if (!normalized.startsWith(path.normalize(projectDir)))
|
|
152
|
+
return false;
|
|
153
|
+
try {
|
|
154
|
+
await stat(normalized);
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async function artifactExists(projectDir, config, type, id) {
|
|
162
|
+
// readArtifact is the authoritative existence check — it looks for files
|
|
163
|
+
// matching `${id}-*.md` in the correct artifact-type directory.
|
|
164
|
+
const artifact = await readArtifact(projectDir, config, type, id);
|
|
165
|
+
if (artifact !== null)
|
|
166
|
+
return true;
|
|
167
|
+
// Fallback: scan the listing in case id-case or prefix routing differs.
|
|
168
|
+
const list = await listArtifacts(projectDir, config, type);
|
|
169
|
+
return list.some((a) => a.id === id);
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=evidence-verifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence-verifier.js","sourceRoot":"","sources":["../../src/services/evidence-verifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,IAAI,MAAM,WAAW,CAAC;AAQ7B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAwC1F;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,QAAwB,EACxB,GAA4B;IAE5B,MAAM,OAAO,GAAsB,EAAE,CAAC;IACtC,MAAM,QAAQ,GAAqB,EAAE,CAAC;IAEtC,KAAK,MAAM,EAAE,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;YACb,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,CAAC,KAAK,CACV,8BAA8B,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,kBAAkB,QAAQ,CAAC,UAAU,EAAE,CAChH,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,6CAA6C;IAC7C,EAAE;IACF,8DAA8D;IAC9D,uEAAuE;IACvE,uEAAuE;IACvE,sEAAsE;IACtE,wEAAwE;IACxE,gDAAgD;IAChD,EAAE;IACF,yEAAyE;IACzE,uEAAuE;IACvE,MAAM,YAAY,GAChB,QAAQ,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE9F,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,MAAM,GACV,QAAQ,CAAC,MAAM,KAAK,CAAC;YACnB,CAAC,CAAC,yHAAyH;YAC3H,CAAC,CAAC,uEAAuE,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,4EAA4E,CAAC;QAC5M,MAAM,GAAG,GACP,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,gCAAgC,CAAC;QACzF,MAAM,SAAS,GAAoB;YACjC,OAAO,EAAE,yBAAyB;YAClC,MAAM;SACP,CAAC;QACF,OAAO;YACL,QAAQ,EAAE;gBACR,GAAG,QAAQ;gBACX,MAAM,EAAE,MAAM;gBACd,QAAQ,EAAE,QAAQ,EAAE,kDAAkD;gBACtE,eAAe,EAAE,SAAS;gBAC1B,SAAS,EAAE,CAAC,GAAG,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;gBAC7C,SAAS,EAAE,GAAG,QAAQ,CAAC,SAAS,cAAc,GAAG,GAAG;aACrD;YACD,OAAO;YACP,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,EAAE,GAAG,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE;QAC7C,OAAO;QACP,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC;AAOD,qEAAqE;AACrE,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,EAAkB,EAClB,GAA4B;IAE5B,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;QAChB,KAAK,aAAa;YAChB,OAAO,CAAC,MAAM,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;gBAChE,CAAC,CAAC,EAAE,EAAE;gBACN,CAAC,CAAC,IAAI,CAAC,8BAA8B,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;QAEnD,KAAK,aAAa;YAChB,OAAO,CAAC,MAAM,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;gBAChE,CAAC,CAAC,IAAI,CAAC,mEAAmE,EAAE,CAAC,GAAG,EAAE,CAAC;gBACnF,CAAC,CAAC,EAAE,EAAE,CAAC;QAEX,KAAK,YAAY;YACf,IAAI,CAAC,GAAG,CAAC,wBAAwB,EAAE,CAAC;gBAClC,OAAO,IAAI,CACT,uFAAuF,CACxF,CAAC;YACJ,CAAC;YACD,sEAAsE;YACtE,IACE,GAAG,CAAC,wBAAwB,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC;gBAC7C,CAAC,EAAE,CAAC,KAAK,IAAI,GAAG,CAAC,wBAAwB,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAC7D,CAAC;gBACD,OAAO,EAAE,EAAE,CAAC;YACd,CAAC;YACD,OAAO,IAAI,CAAC,mDAAmD,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;QAE3E,KAAK,kBAAkB,CAAC,CAAC,CAAC;YACxB,MAAM,IAAI,GAAG,oBAAoB,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;YAC1C,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,IAAI,CAAC,2DAA2D,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;YACnF,CAAC;YACD,OAAO,CAAC,MAAM,cAAc,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;gBACrE,CAAC,CAAC,EAAE,EAAE;gBACN,CAAC,CAAC,IAAI,CAAC,uCAAuC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;QAC5D,CAAC;QAED,KAAK,cAAc;YACjB,mEAAmE;YACnE,qEAAqE;YACrE,OAAO,GAAG,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC;gBACzC,CAAC,CAAC,EAAE,EAAE;gBACN,CAAC,CAAC,IAAI,CAAC,8CAA8C,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;QAEnE,KAAK,cAAc;YACjB,OAAO,GAAG,CAAC,mBAAmB,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC;gBAC7C,CAAC,CAAC,EAAE,EAAE;gBACN,CAAC,CAAC,IAAI,CAAC,oDAAoD,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;QAEzE,OAAO,CAAC,CAAC,CAAC;YACR,qEAAqE;YACrE,4CAA4C;YAC5C,MAAM,WAAW,GAAU,EAAE,CAAC,IAAI,CAAC;YACnC,OAAO,IAAI,CAAC,4BAA4B,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,EAAE,GAAG,GAAkB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;AAC3D,MAAM,IAAI,GAAG,CAAC,MAAc,EAAiB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;AAExE,KAAK,UAAU,UAAU,CAAC,UAAkB,EAAE,GAAW,EAAE,WAAoB;IAC7E,0BAA0B;IAC1B,2EAA2E;IAC3E,0EAA0E;IAC1E,6EAA6E;IAC7E,+EAA+E;IAC/E,wBAAwB;IACxB,MAAM,aAAa,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACpE,MAAM,IAAI,GAAG,aAAa,IAAI,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC;IACrE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC5C,qEAAqE;IACrE,6EAA6E;IAC7E,6DAA6D;IAC7D,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACrE,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,KAAK,UAAU,cAAc,CAC3B,UAAkB,EAClB,MAAuB,EACvB,IAAkB,EAClB,EAAU;IAEV,yEAAyE;IACzE,gEAAgE;IAChE,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IAClE,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACnC,wEAAwE;IACxE,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git integration for `planr revise` (EPIC-003, FEAT-011 + FEAT-013).
|
|
3
|
+
*
|
|
4
|
+
* Two responsibilities:
|
|
5
|
+
*
|
|
6
|
+
* 1. **Clean-tree gate (FEAT-011 §2.0):** revise refuses to run with a dirty
|
|
7
|
+
* working tree by default. Users can override with `--allow-dirty`, but
|
|
8
|
+
* post-flight rollback depends on a clean pre-run state, so the gate is
|
|
9
|
+
* the load-bearing safety net.
|
|
10
|
+
*
|
|
11
|
+
* 2. **Capture + rollback anchor (FEAT-013 §4.0):** before bulk writes,
|
|
12
|
+
* revise captures HEAD and the set of touched paths so a post-flight
|
|
13
|
+
* graph-integrity failure can restore via `git checkout`.
|
|
14
|
+
*
|
|
15
|
+
* All git operations use `execFile` (not shell), matching the pattern in
|
|
16
|
+
* github-service.ts. If git is not available or the project is not a git
|
|
17
|
+
* repo, clean-tree checks fail closed (revise refuses to run) unless
|
|
18
|
+
* --allow-dirty is passed, because without git there is no safety net.
|
|
19
|
+
*/
|
|
20
|
+
export type GitTreeStatus = {
|
|
21
|
+
kind: 'clean';
|
|
22
|
+
head: string;
|
|
23
|
+
} | {
|
|
24
|
+
kind: 'dirty';
|
|
25
|
+
head: string;
|
|
26
|
+
changedPaths: string[];
|
|
27
|
+
} | {
|
|
28
|
+
kind: 'not-a-repo';
|
|
29
|
+
reason: string;
|
|
30
|
+
} | {
|
|
31
|
+
kind: 'git-missing';
|
|
32
|
+
reason: string;
|
|
33
|
+
};
|
|
34
|
+
export interface GitCleanTreeCheckOptions {
|
|
35
|
+
allowDirty: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface GitCleanTreeCheckResult {
|
|
38
|
+
ok: boolean;
|
|
39
|
+
status: GitTreeStatus;
|
|
40
|
+
/** User-facing message describing why the gate opened or closed. */
|
|
41
|
+
message: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Inspect the working tree. Never throws — always returns a typed status so
|
|
45
|
+
* callers can render errors consistently.
|
|
46
|
+
*/
|
|
47
|
+
export declare function inspectGitTree(projectDir: string): Promise<GitTreeStatus>;
|
|
48
|
+
/**
|
|
49
|
+
* The clean-tree gate: clean → pass; dirty → pass only when --allow-dirty;
|
|
50
|
+
* missing git / not a repo → fail closed unless --allow-dirty was passed
|
|
51
|
+
* (because without git there is no post-flight rollback safety net).
|
|
52
|
+
*/
|
|
53
|
+
export declare function checkCleanTree(projectDir: string, options: GitCleanTreeCheckOptions): Promise<GitCleanTreeCheckResult>;
|
|
54
|
+
/**
|
|
55
|
+
* Restore a set of paths from HEAD — the primitive FEAT-013's post-flight
|
|
56
|
+
* rollback invokes when graph integrity breaks after writes. Paths are
|
|
57
|
+
* relative to `projectDir`. Empty list is a no-op.
|
|
58
|
+
*/
|
|
59
|
+
export declare function checkoutPaths(projectDir: string, relativePaths: string[]): Promise<void>;
|
|
60
|
+
//# sourceMappingURL=git-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-service.d.ts","sourceRoot":"","sources":["../../src/services/git-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5C,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,aAAa,CAAC;IACtB,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAuC/E;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,uBAAuB,CAAC,CA0DlC;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAM9F"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git integration for `planr revise` (EPIC-003, FEAT-011 + FEAT-013).
|
|
3
|
+
*
|
|
4
|
+
* Two responsibilities:
|
|
5
|
+
*
|
|
6
|
+
* 1. **Clean-tree gate (FEAT-011 §2.0):** revise refuses to run with a dirty
|
|
7
|
+
* working tree by default. Users can override with `--allow-dirty`, but
|
|
8
|
+
* post-flight rollback depends on a clean pre-run state, so the gate is
|
|
9
|
+
* the load-bearing safety net.
|
|
10
|
+
*
|
|
11
|
+
* 2. **Capture + rollback anchor (FEAT-013 §4.0):** before bulk writes,
|
|
12
|
+
* revise captures HEAD and the set of touched paths so a post-flight
|
|
13
|
+
* graph-integrity failure can restore via `git checkout`.
|
|
14
|
+
*
|
|
15
|
+
* All git operations use `execFile` (not shell), matching the pattern in
|
|
16
|
+
* github-service.ts. If git is not available or the project is not a git
|
|
17
|
+
* repo, clean-tree checks fail closed (revise refuses to run) unless
|
|
18
|
+
* --allow-dirty is passed, because without git there is no safety net.
|
|
19
|
+
*/
|
|
20
|
+
import { execFile } from 'node:child_process';
|
|
21
|
+
import { promisify } from 'node:util';
|
|
22
|
+
const execFileAsync = promisify(execFile);
|
|
23
|
+
const GIT_MAX_BUFFER = 10 * 1024 * 1024;
|
|
24
|
+
/**
|
|
25
|
+
* Inspect the working tree. Never throws — always returns a typed status so
|
|
26
|
+
* callers can render errors consistently.
|
|
27
|
+
*/
|
|
28
|
+
export async function inspectGitTree(projectDir) {
|
|
29
|
+
let head;
|
|
30
|
+
try {
|
|
31
|
+
const { stdout } = await execFileAsync('git', ['rev-parse', 'HEAD'], {
|
|
32
|
+
cwd: projectDir,
|
|
33
|
+
maxBuffer: GIT_MAX_BUFFER,
|
|
34
|
+
});
|
|
35
|
+
head = stdout.trim();
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
39
|
+
if (/not a git repository|fatal:.*repository/i.test(message)) {
|
|
40
|
+
return { kind: 'not-a-repo', reason: message };
|
|
41
|
+
}
|
|
42
|
+
if (/ENOENT|git: not found|command not found/i.test(message)) {
|
|
43
|
+
return { kind: 'git-missing', reason: message };
|
|
44
|
+
}
|
|
45
|
+
// Empty repo (no commits yet) also reaches here; treat it as not-a-repo
|
|
46
|
+
// for clean-tree gating purposes — there is no HEAD to roll back to.
|
|
47
|
+
if (/unknown revision|does not have any commits/i.test(message)) {
|
|
48
|
+
return { kind: 'not-a-repo', reason: 'git repository has no commits yet' };
|
|
49
|
+
}
|
|
50
|
+
return { kind: 'not-a-repo', reason: message };
|
|
51
|
+
}
|
|
52
|
+
const { stdout: porcelain } = await execFileAsync('git', ['status', '--porcelain'], {
|
|
53
|
+
cwd: projectDir,
|
|
54
|
+
maxBuffer: GIT_MAX_BUFFER,
|
|
55
|
+
});
|
|
56
|
+
if (porcelain.trim().length === 0) {
|
|
57
|
+
return { kind: 'clean', head };
|
|
58
|
+
}
|
|
59
|
+
const changedPaths = porcelain
|
|
60
|
+
.split('\n')
|
|
61
|
+
.filter((line) => line.length > 0)
|
|
62
|
+
.map((line) => line.slice(3).trim());
|
|
63
|
+
return { kind: 'dirty', head, changedPaths };
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The clean-tree gate: clean → pass; dirty → pass only when --allow-dirty;
|
|
67
|
+
* missing git / not a repo → fail closed unless --allow-dirty was passed
|
|
68
|
+
* (because without git there is no post-flight rollback safety net).
|
|
69
|
+
*/
|
|
70
|
+
export async function checkCleanTree(projectDir, options) {
|
|
71
|
+
const status = await inspectGitTree(projectDir);
|
|
72
|
+
switch (status.kind) {
|
|
73
|
+
case 'clean':
|
|
74
|
+
return {
|
|
75
|
+
ok: true,
|
|
76
|
+
status,
|
|
77
|
+
message: `Working tree is clean at ${status.head.slice(0, 12)}.`,
|
|
78
|
+
};
|
|
79
|
+
case 'dirty':
|
|
80
|
+
if (options.allowDirty) {
|
|
81
|
+
return {
|
|
82
|
+
ok: true,
|
|
83
|
+
status,
|
|
84
|
+
message: `Working tree has ${status.changedPaths.length} uncommitted change(s); running with --allow-dirty. Post-flight rollback cannot restore these changes.`,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
ok: false,
|
|
89
|
+
status,
|
|
90
|
+
message: `Working tree has ${status.changedPaths.length} uncommitted change(s). Commit or stash them, or re-run with --allow-dirty (post-flight rollback cannot restore uncommitted work).`,
|
|
91
|
+
};
|
|
92
|
+
case 'not-a-repo':
|
|
93
|
+
if (options.allowDirty) {
|
|
94
|
+
return {
|
|
95
|
+
ok: true,
|
|
96
|
+
status,
|
|
97
|
+
message: `Not a git repository (${status.reason.trim()}); running with --allow-dirty. Post-flight rollback is disabled.`,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
ok: false,
|
|
102
|
+
status,
|
|
103
|
+
message: `Not a git repository (${status.reason.trim()}). Revise requires git for its post-flight rollback safety net. Initialize git, or re-run with --allow-dirty to opt out of the safety net.`,
|
|
104
|
+
};
|
|
105
|
+
case 'git-missing':
|
|
106
|
+
if (options.allowDirty) {
|
|
107
|
+
return {
|
|
108
|
+
ok: true,
|
|
109
|
+
status,
|
|
110
|
+
message: `git CLI not found; running with --allow-dirty. Post-flight rollback is disabled.`,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
ok: false,
|
|
115
|
+
status,
|
|
116
|
+
message: `git CLI not found on PATH. Revise requires git for its post-flight rollback safety net. Install git, or re-run with --allow-dirty to opt out.`,
|
|
117
|
+
};
|
|
118
|
+
default: {
|
|
119
|
+
const _exhaustive = status;
|
|
120
|
+
throw new Error(`unhandled GitTreeStatus: ${JSON.stringify(_exhaustive)}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Restore a set of paths from HEAD — the primitive FEAT-013's post-flight
|
|
126
|
+
* rollback invokes when graph integrity breaks after writes. Paths are
|
|
127
|
+
* relative to `projectDir`. Empty list is a no-op.
|
|
128
|
+
*/
|
|
129
|
+
export async function checkoutPaths(projectDir, relativePaths) {
|
|
130
|
+
if (relativePaths.length === 0)
|
|
131
|
+
return;
|
|
132
|
+
await execFileAsync('git', ['checkout', '--', ...relativePaths], {
|
|
133
|
+
cwd: projectDir,
|
|
134
|
+
maxBuffer: GIT_MAX_BUFFER,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=git-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-service.js","sourceRoot":"","sources":["../../src/services/git-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* All operations use `gh` so authentication is handled by the user's
|
|
6
6
|
* existing GitHub CLI session — no extra API tokens needed.
|
|
7
7
|
*/
|
|
8
|
-
import type { ArtifactFrontmatter, ArtifactType } from '../models/types.js';
|
|
8
|
+
import type { ArtifactFrontmatter, ArtifactType, GitHubCommitSummary, GitHubPullRequestSummary } from '../models/types.js';
|
|
9
9
|
export interface GitHubIssue {
|
|
10
10
|
number: number;
|
|
11
11
|
title: string;
|
|
@@ -94,4 +94,31 @@ export declare function fetchIssueTypes(owner: string, repo: string): Promise<Re
|
|
|
94
94
|
* Requires the issue's node ID and the issue type's node ID.
|
|
95
95
|
*/
|
|
96
96
|
export declare function setIssueType(owner: string, repo: string, issueNumber: number, issueTypeName: string): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Recent commits on the default branch (best-effort via GitHub API).
|
|
99
|
+
*/
|
|
100
|
+
export declare function fetchRecentCommits(args: {
|
|
101
|
+
days: number;
|
|
102
|
+
limit: number;
|
|
103
|
+
}): Promise<{
|
|
104
|
+
commits: GitHubCommitSummary[];
|
|
105
|
+
warning?: string;
|
|
106
|
+
}>;
|
|
107
|
+
/**
|
|
108
|
+
* Recently updated pull requests (all states), filtered client-side by `updated_at`.
|
|
109
|
+
*/
|
|
110
|
+
export declare function fetchRecentPullRequests(args: {
|
|
111
|
+
days: number;
|
|
112
|
+
limit: number;
|
|
113
|
+
}): Promise<{
|
|
114
|
+
pullRequests: GitHubPullRequestSummary[];
|
|
115
|
+
warning?: string;
|
|
116
|
+
}>;
|
|
117
|
+
/**
|
|
118
|
+
* Best-effort check that `gh` can read the repo (already implied by verifyGitHubRepo).
|
|
119
|
+
*/
|
|
120
|
+
export declare function validateRepoAccessible(): Promise<{
|
|
121
|
+
ok: boolean;
|
|
122
|
+
message: string;
|
|
123
|
+
}>;
|
|
97
124
|
//# sourceMappingURL=github-service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-service.d.ts","sourceRoot":"","sources":["../../src/services/github-service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"github-service.d.ts","sourceRoot":"","sources":["../../src/services/github-service.ts"],"names":[],"mappings":"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"}
|