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.
Files changed (149) hide show
  1. package/README.md +54 -1
  2. package/dist/ai/prompts/prompt-builder.d.ts +48 -0
  3. package/dist/ai/prompts/prompt-builder.d.ts.map +1 -1
  4. package/dist/ai/prompts/prompt-builder.js +57 -1
  5. package/dist/ai/prompts/prompt-builder.js.map +1 -1
  6. package/dist/ai/prompts/system-prompts.d.ts +23 -0
  7. package/dist/ai/prompts/system-prompts.d.ts.map +1 -1
  8. package/dist/ai/prompts/system-prompts.js +98 -0
  9. package/dist/ai/prompts/system-prompts.js.map +1 -1
  10. package/dist/ai/schemas/ai-response-schemas.d.ts +68 -0
  11. package/dist/ai/schemas/ai-response-schemas.d.ts.map +1 -1
  12. package/dist/ai/schemas/ai-response-schemas.js +81 -0
  13. package/dist/ai/schemas/ai-response-schemas.js.map +1 -1
  14. package/dist/ai/types.d.ts +2 -0
  15. package/dist/ai/types.d.ts.map +1 -1
  16. package/dist/ai/types.js +2 -0
  17. package/dist/ai/types.js.map +1 -1
  18. package/dist/cli/commands/context.d.ts +6 -0
  19. package/dist/cli/commands/context.d.ts.map +1 -0
  20. package/dist/cli/commands/context.js +45 -0
  21. package/dist/cli/commands/context.js.map +1 -0
  22. package/dist/cli/commands/export.d.ts.map +1 -1
  23. package/dist/cli/commands/export.js +8 -0
  24. package/dist/cli/commands/export.js.map +1 -1
  25. package/dist/cli/commands/report-linter.d.ts +6 -0
  26. package/dist/cli/commands/report-linter.d.ts.map +1 -0
  27. package/dist/cli/commands/report-linter.js +61 -0
  28. package/dist/cli/commands/report-linter.js.map +1 -0
  29. package/dist/cli/commands/report.d.ts +6 -0
  30. package/dist/cli/commands/report.d.ts.map +1 -0
  31. package/dist/cli/commands/report.js +150 -0
  32. package/dist/cli/commands/report.js.map +1 -0
  33. package/dist/cli/commands/revise.d.ts +23 -0
  34. package/dist/cli/commands/revise.d.ts.map +1 -0
  35. package/dist/cli/commands/revise.js +502 -0
  36. package/dist/cli/commands/revise.js.map +1 -0
  37. package/dist/cli/commands/story.d.ts.map +1 -1
  38. package/dist/cli/commands/story.js +31 -0
  39. package/dist/cli/commands/story.js.map +1 -1
  40. package/dist/cli/commands/voice.d.ts +6 -0
  41. package/dist/cli/commands/voice.d.ts.map +1 -0
  42. package/dist/cli/commands/voice.js +64 -0
  43. package/dist/cli/commands/voice.js.map +1 -0
  44. package/dist/cli/index.js +10 -0
  45. package/dist/cli/index.js.map +1 -1
  46. package/dist/models/schema.d.ts +63 -0
  47. package/dist/models/schema.d.ts.map +1 -1
  48. package/dist/models/schema.js +31 -0
  49. package/dist/models/schema.js.map +1 -1
  50. package/dist/models/types.d.ts +280 -0
  51. package/dist/models/types.d.ts.map +1 -1
  52. package/dist/services/atomic-write-service.d.ts +41 -0
  53. package/dist/services/atomic-write-service.d.ts.map +1 -0
  54. package/dist/services/atomic-write-service.js +87 -0
  55. package/dist/services/atomic-write-service.js.map +1 -0
  56. package/dist/services/audit-log-service.d.ts +50 -0
  57. package/dist/services/audit-log-service.d.ts.map +1 -0
  58. package/dist/services/audit-log-service.js +213 -0
  59. package/dist/services/audit-log-service.js.map +1 -0
  60. package/dist/services/cascade-service.d.ts +62 -0
  61. package/dist/services/cascade-service.d.ts.map +1 -0
  62. package/dist/services/cascade-service.js +189 -0
  63. package/dist/services/cascade-service.js.map +1 -0
  64. package/dist/services/context-pack-service.d.ts +12 -0
  65. package/dist/services/context-pack-service.d.ts.map +1 -0
  66. package/dist/services/context-pack-service.js +155 -0
  67. package/dist/services/context-pack-service.js.map +1 -0
  68. package/dist/services/diff-service.d.ts +18 -0
  69. package/dist/services/diff-service.d.ts.map +1 -0
  70. package/dist/services/diff-service.js +35 -0
  71. package/dist/services/diff-service.js.map +1 -0
  72. package/dist/services/distribution-service.d.ts +18 -0
  73. package/dist/services/distribution-service.d.ts.map +1 -0
  74. package/dist/services/distribution-service.js +104 -0
  75. package/dist/services/distribution-service.js.map +1 -0
  76. package/dist/services/evidence-service.d.ts +17 -0
  77. package/dist/services/evidence-service.d.ts.map +1 -0
  78. package/dist/services/evidence-service.js +85 -0
  79. package/dist/services/evidence-service.js.map +1 -0
  80. package/dist/services/evidence-verifier.d.ts +71 -0
  81. package/dist/services/evidence-verifier.d.ts.map +1 -0
  82. package/dist/services/evidence-verifier.js +171 -0
  83. package/dist/services/evidence-verifier.js.map +1 -0
  84. package/dist/services/git-service.d.ts +60 -0
  85. package/dist/services/git-service.d.ts.map +1 -0
  86. package/dist/services/git-service.js +137 -0
  87. package/dist/services/git-service.js.map +1 -0
  88. package/dist/services/github-service.d.ts +28 -1
  89. package/dist/services/github-service.d.ts.map +1 -1
  90. package/dist/services/github-service.js +95 -0
  91. package/dist/services/github-service.js.map +1 -1
  92. package/dist/services/graph-integrity.d.ts +36 -0
  93. package/dist/services/graph-integrity.d.ts.map +1 -0
  94. package/dist/services/graph-integrity.js +54 -0
  95. package/dist/services/graph-integrity.js.map +1 -0
  96. package/dist/services/prompt-service.d.ts +18 -0
  97. package/dist/services/prompt-service.d.ts.map +1 -1
  98. package/dist/services/prompt-service.js +47 -0
  99. package/dist/services/prompt-service.js.map +1 -1
  100. package/dist/services/report-linter-service.d.ts +10 -0
  101. package/dist/services/report-linter-service.d.ts.map +1 -0
  102. package/dist/services/report-linter-service.js +95 -0
  103. package/dist/services/report-linter-service.js.map +1 -0
  104. package/dist/services/report-service.d.ts +37 -0
  105. package/dist/services/report-service.d.ts.map +1 -0
  106. package/dist/services/report-service.js +173 -0
  107. package/dist/services/report-service.js.map +1 -0
  108. package/dist/services/revise-cache-service.d.ts +46 -0
  109. package/dist/services/revise-cache-service.d.ts.map +1 -0
  110. package/dist/services/revise-cache-service.js +88 -0
  111. package/dist/services/revise-cache-service.js.map +1 -0
  112. package/dist/services/revise-service.d.ts +108 -0
  113. package/dist/services/revise-service.d.ts.map +1 -0
  114. package/dist/services/revise-service.js +249 -0
  115. package/dist/services/revise-service.js.map +1 -0
  116. package/dist/services/standup-parser.d.ts +21 -0
  117. package/dist/services/standup-parser.d.ts.map +1 -0
  118. package/dist/services/standup-parser.js +104 -0
  119. package/dist/services/standup-parser.js.map +1 -0
  120. package/dist/services/story-standup-service.d.ts +7 -0
  121. package/dist/services/story-standup-service.d.ts.map +1 -0
  122. package/dist/services/story-standup-service.js +27 -0
  123. package/dist/services/story-standup-service.js.map +1 -0
  124. package/dist/services/template-sections.d.ts +28 -0
  125. package/dist/services/template-sections.d.ts.map +1 -0
  126. package/dist/services/template-sections.js +55 -0
  127. package/dist/services/template-sections.js.map +1 -0
  128. package/dist/services/template-service.d.ts.map +1 -1
  129. package/dist/services/template-service.js +1 -0
  130. package/dist/services/template-service.js.map +1 -1
  131. package/dist/services/voice-service.d.ts +12 -0
  132. package/dist/services/voice-service.d.ts.map +1 -0
  133. package/dist/services/voice-service.js +42 -0
  134. package/dist/services/voice-service.js.map +1 -0
  135. package/dist/templates/export/planning-report.html.hbs +10 -0
  136. package/dist/templates/export/planning-report.md.hbs +11 -0
  137. package/dist/templates/linter/linter-config.json.hbs +13 -0
  138. package/dist/templates/reports/executive.md.hbs +28 -0
  139. package/dist/templates/reports/release-notes.md.hbs +37 -0
  140. package/dist/templates/reports/retrospective.md.hbs +36 -0
  141. package/dist/templates/reports/sprint.md.hbs +91 -0
  142. package/dist/templates/reports/standup.md.hbs +27 -0
  143. package/dist/templates/reports/weekly.md.hbs +42 -0
  144. package/dist/templates/voice/standup.md.hbs +20 -0
  145. package/dist/utils/diff.d.ts +26 -0
  146. package/dist/utils/diff.d.ts.map +1 -0
  147. package/dist/utils/diff.js +143 -0
  148. package/dist/utils/diff.js.map +1 -0
  149. 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":"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"}
@@ -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":"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"}
1
+ {"version":3,"file":"github-service.d.ts","sourceRoot":"","sources":["../../src/services/github-service.ts"],"names":[],"mappings":"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"}