@itsthelore/proofkeeper 2026.6.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.
Files changed (156) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +10 -0
  3. package/README.md +207 -0
  4. package/dist/agent/adapters/claude.d.ts +93 -0
  5. package/dist/agent/adapters/claude.d.ts.map +1 -0
  6. package/dist/agent/adapters/claude.js +96 -0
  7. package/dist/agent/adapters/claude.js.map +1 -0
  8. package/dist/agent/drive.d.ts +53 -0
  9. package/dist/agent/drive.d.ts.map +1 -0
  10. package/dist/agent/drive.js +194 -0
  11. package/dist/agent/drive.js.map +1 -0
  12. package/dist/agent/loop.d.ts +40 -0
  13. package/dist/agent/loop.d.ts.map +1 -0
  14. package/dist/agent/loop.js +29 -0
  15. package/dist/agent/loop.js.map +1 -0
  16. package/dist/agent/model.d.ts +43 -0
  17. package/dist/agent/model.d.ts.map +1 -0
  18. package/dist/agent/model.js +10 -0
  19. package/dist/agent/model.js.map +1 -0
  20. package/dist/agent/observe.d.ts +48 -0
  21. package/dist/agent/observe.d.ts.map +1 -0
  22. package/dist/agent/observe.js +65 -0
  23. package/dist/agent/observe.js.map +1 -0
  24. package/dist/agent/tools.d.ts +74 -0
  25. package/dist/agent/tools.d.ts.map +1 -0
  26. package/dist/agent/tools.js +257 -0
  27. package/dist/agent/tools.js.map +1 -0
  28. package/dist/cli.d.ts +61 -0
  29. package/dist/cli.d.ts.map +1 -0
  30. package/dist/cli.js +648 -0
  31. package/dist/cli.js.map +1 -0
  32. package/dist/compiler/actions.d.ts +101 -0
  33. package/dist/compiler/actions.d.ts.map +1 -0
  34. package/dist/compiler/actions.js +13 -0
  35. package/dist/compiler/actions.js.map +1 -0
  36. package/dist/compiler/compiler.d.ts +25 -0
  37. package/dist/compiler/compiler.d.ts.map +1 -0
  38. package/dist/compiler/compiler.js +42 -0
  39. package/dist/compiler/compiler.js.map +1 -0
  40. package/dist/compiler/emit.d.ts +21 -0
  41. package/dist/compiler/emit.d.ts.map +1 -0
  42. package/dist/compiler/emit.js +164 -0
  43. package/dist/compiler/emit.js.map +1 -0
  44. package/dist/compiler/http.d.ts +30 -0
  45. package/dist/compiler/http.d.ts.map +1 -0
  46. package/dist/compiler/http.js +30 -0
  47. package/dist/compiler/http.js.map +1 -0
  48. package/dist/compiler/recorder.d.ts +62 -0
  49. package/dist/compiler/recorder.d.ts.map +1 -0
  50. package/dist/compiler/recorder.js +148 -0
  51. package/dist/compiler/recorder.js.map +1 -0
  52. package/dist/compiler/summary.d.ts +11 -0
  53. package/dist/compiler/summary.d.ts.map +1 -0
  54. package/dist/compiler/summary.js +56 -0
  55. package/dist/compiler/summary.js.map +1 -0
  56. package/dist/compiler/terminal.d.ts +42 -0
  57. package/dist/compiler/terminal.d.ts.map +1 -0
  58. package/dist/compiler/terminal.js +47 -0
  59. package/dist/compiler/terminal.js.map +1 -0
  60. package/dist/compiler/types.d.ts +25 -0
  61. package/dist/compiler/types.d.ts.map +1 -0
  62. package/dist/compiler/types.js +10 -0
  63. package/dist/compiler/types.js.map +1 -0
  64. package/dist/coverage/graph.d.ts +55 -0
  65. package/dist/coverage/graph.d.ts.map +1 -0
  66. package/dist/coverage/graph.js +87 -0
  67. package/dist/coverage/graph.js.map +1 -0
  68. package/dist/coverage/model.d.ts +36 -0
  69. package/dist/coverage/model.d.ts.map +1 -0
  70. package/dist/coverage/model.js +57 -0
  71. package/dist/coverage/model.js.map +1 -0
  72. package/dist/coverage/report.d.ts +27 -0
  73. package/dist/coverage/report.d.ts.map +1 -0
  74. package/dist/coverage/report.js +45 -0
  75. package/dist/coverage/report.js.map +1 -0
  76. package/dist/coverage/source.d.ts +23 -0
  77. package/dist/coverage/source.d.ts.map +1 -0
  78. package/dist/coverage/source.js +48 -0
  79. package/dist/coverage/source.js.map +1 -0
  80. package/dist/fidelity/gate.d.ts +34 -0
  81. package/dist/fidelity/gate.d.ts.map +1 -0
  82. package/dist/fidelity/gate.js +38 -0
  83. package/dist/fidelity/gate.js.map +1 -0
  84. package/dist/index.d.ts +69 -0
  85. package/dist/index.d.ts.map +1 -0
  86. package/dist/index.js +49 -0
  87. package/dist/index.js.map +1 -0
  88. package/dist/learning/store.d.ts +44 -0
  89. package/dist/learning/store.d.ts.map +1 -0
  90. package/dist/learning/store.js +64 -0
  91. package/dist/learning/store.js.map +1 -0
  92. package/dist/qa/concurrency.d.ts +7 -0
  93. package/dist/qa/concurrency.d.ts.map +1 -0
  94. package/dist/qa/concurrency.js +21 -0
  95. package/dist/qa/concurrency.js.map +1 -0
  96. package/dist/qa/run-qa.d.ts +87 -0
  97. package/dist/qa/run-qa.d.ts.map +1 -0
  98. package/dist/qa/run-qa.js +106 -0
  99. package/dist/qa/run-qa.js.map +1 -0
  100. package/dist/qa/run-scoped.d.ts +82 -0
  101. package/dist/qa/run-scoped.d.ts.map +1 -0
  102. package/dist/qa/run-scoped.js +96 -0
  103. package/dist/qa/run-scoped.js.map +1 -0
  104. package/dist/runner/playwright-report.d.ts +52 -0
  105. package/dist/runner/playwright-report.d.ts.map +1 -0
  106. package/dist/runner/playwright-report.js +90 -0
  107. package/dist/runner/playwright-report.js.map +1 -0
  108. package/dist/runner/playwright-runner.d.ts +38 -0
  109. package/dist/runner/playwright-runner.d.ts.map +1 -0
  110. package/dist/runner/playwright-runner.js +73 -0
  111. package/dist/runner/playwright-runner.js.map +1 -0
  112. package/dist/runner/types.d.ts +45 -0
  113. package/dist/runner/types.d.ts.map +1 -0
  114. package/dist/runner/types.js +10 -0
  115. package/dist/runner/types.js.map +1 -0
  116. package/dist/scaffold/scaffold.d.ts +22 -0
  117. package/dist/scaffold/scaffold.d.ts.map +1 -0
  118. package/dist/scaffold/scaffold.js +34 -0
  119. package/dist/scaffold/scaffold.js.map +1 -0
  120. package/dist/scope/config.d.ts +89 -0
  121. package/dist/scope/config.d.ts.map +1 -0
  122. package/dist/scope/config.js +172 -0
  123. package/dist/scope/config.js.map +1 -0
  124. package/dist/scope/diff-scope.d.ts +31 -0
  125. package/dist/scope/diff-scope.d.ts.map +1 -0
  126. package/dist/scope/diff-scope.js +42 -0
  127. package/dist/scope/diff-scope.js.map +1 -0
  128. package/dist/scope/glob.d.ts +17 -0
  129. package/dist/scope/glob.d.ts.map +1 -0
  130. package/dist/scope/glob.js +50 -0
  131. package/dist/scope/glob.js.map +1 -0
  132. package/dist/writeback/comment.d.ts +103 -0
  133. package/dist/writeback/comment.d.ts.map +1 -0
  134. package/dist/writeback/comment.js +150 -0
  135. package/dist/writeback/comment.js.map +1 -0
  136. package/dist/writeback/gateways/github-rest.d.ts +66 -0
  137. package/dist/writeback/gateways/github-rest.d.ts.map +1 -0
  138. package/dist/writeback/gateways/github-rest.js +107 -0
  139. package/dist/writeback/gateways/github-rest.js.map +1 -0
  140. package/dist/writeback/merge.d.ts +27 -0
  141. package/dist/writeback/merge.d.ts.map +1 -0
  142. package/dist/writeback/merge.js +89 -0
  143. package/dist/writeback/merge.js.map +1 -0
  144. package/dist/writeback/proposal.d.ts +52 -0
  145. package/dist/writeback/proposal.d.ts.map +1 -0
  146. package/dist/writeback/proposal.js +79 -0
  147. package/dist/writeback/proposal.js.map +1 -0
  148. package/dist/writeback/proposer.d.ts +94 -0
  149. package/dist/writeback/proposer.d.ts.map +1 -0
  150. package/dist/writeback/proposer.js +79 -0
  151. package/dist/writeback/proposer.js.map +1 -0
  152. package/dist/writeback/verified-by.d.ts +56 -0
  153. package/dist/writeback/verified-by.d.ts.map +1 -0
  154. package/dist/writeback/verified-by.js +60 -0
  155. package/dist/writeback/verified-by.js.map +1 -0
  156. package/package.json +62 -0
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The runner interface — Proofkeeper Initiative 4.
3
+ *
4
+ * A runner executes a compiled suite fast and in parallel across targets and
5
+ * operating systems, emitting a replayable trace per result. The interface is
6
+ * pluggable on purpose: the open-source local runner and the (out-of-scope for
7
+ * v0.0.1) hosted VM-fabric runner are two implementations of the same shape.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/runner/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Config scaffolding — the in-scope MVP of Factory's `/install-qa`. Generates a
3
+ * `proofkeeper.config.json` skeleton from the published Lore graph (`rac export
4
+ * --graph`), the contract Proofkeeper already consumes. It reads only that
5
+ * contract — never product source — so it stays within the verification mandate.
6
+ * The user then narrows each capability's path globs and adds auth/personas.
7
+ */
8
+ import type { Graph } from "../coverage/graph.js";
9
+ import type { ProofkeeperConfig } from "../scope/config.js";
10
+ export interface ScaffoldOptions {
11
+ /** Development environment URL. Defaults to http://localhost:3000. */
12
+ url?: string;
13
+ }
14
+ /**
15
+ * Generate a config skeleton from the graph: one capability per requirement node
16
+ * (unverified first), plus a starter environment, default target, and
17
+ * failure-learning strategy. Pure and deterministic.
18
+ */
19
+ export declare function scaffoldConfig(graph: Graph, options?: ScaffoldOptions): ProofkeeperConfig;
20
+ /** Pretty-print a scaffolded config as JSON (trailing newline). */
21
+ export declare function renderScaffoldedConfig(config: ProofkeeperConfig): string;
22
+ //# sourceMappingURL=scaffold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/scaffold/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAoB,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE9E,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,GAAE,eAAoB,GAAG,iBAAiB,CAe7F;AAED,mEAAmE;AACnE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAExE"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Config scaffolding — the in-scope MVP of Factory's `/install-qa`. Generates a
3
+ * `proofkeeper.config.json` skeleton from the published Lore graph (`rac export
4
+ * --graph`), the contract Proofkeeper already consumes. It reads only that
5
+ * contract — never product source — so it stays within the verification mandate.
6
+ * The user then narrows each capability's path globs and adds auth/personas.
7
+ */
8
+ import { computeCoverage } from "../coverage/model.js";
9
+ /**
10
+ * Generate a config skeleton from the graph: one capability per requirement node
11
+ * (unverified first), plus a starter environment, default target, and
12
+ * failure-learning strategy. Pure and deterministic.
13
+ */
14
+ export function scaffoldConfig(graph, options = {}) {
15
+ const report = computeCoverage(graph);
16
+ // Unverified capabilities first — those most in need of a verifying test.
17
+ const ordered = [...report.unverified, ...report.verified];
18
+ const capabilities = ordered.map((c) => ({
19
+ id: c.id,
20
+ paths: ["src/**"],
21
+ environment: "development",
22
+ }));
23
+ return {
24
+ environments: { development: { url: options.url ?? "http://localhost:3000" } },
25
+ defaultTarget: "development",
26
+ failureLearning: "suggest_in_report",
27
+ capabilities,
28
+ };
29
+ }
30
+ /** Pretty-print a scaffolded config as JSON (trailing newline). */
31
+ export function renderScaffoldedConfig(config) {
32
+ return JSON.stringify(config, null, 2) + "\n";
33
+ }
34
+ //# sourceMappingURL=scaffold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/scaffold/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AASvD;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,KAAY,EAAE,UAA2B,EAAE;IACxE,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACtC,0EAA0E;IAC1E,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC3D,MAAM,YAAY,GAAuB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3D,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,KAAK,EAAE,CAAC,QAAQ,CAAC;QACjB,WAAW,EAAE,aAAa;KAC3B,CAAC,CAAC,CAAC;IACJ,OAAO;QACL,YAAY,EAAE,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,uBAAuB,EAAE,EAAE;QAC9E,aAAa,EAAE,aAAa;QAC5B,eAAe,EAAE,mBAAmB;QACpC,YAAY;KACb,CAAC;AACJ,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,sBAAsB,CAAC,MAAyB;IAC9D,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;AAChD,CAAC"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * The Proofkeeper scope config — which capabilities a changed file touches.
3
+ *
4
+ * Modeled on Factory automated-qa's `path_patterns`: a config maps each
5
+ * capability to the source-path globs whose change implies it should be
6
+ * re-verified, plus optional drive overrides (start URL, goal) and the corpus
7
+ * artifact to write `## Verified By` back to. It is the only place Proofkeeper
8
+ * needs to know how product capabilities relate to source files.
9
+ */
10
+ /** One capability's scoping entry. */
11
+ export interface CapabilityConfig {
12
+ /** The requirement id (must be a capability node in the graph). */
13
+ id: string;
14
+ /** Source-path globs; a changed file matching any of these scopes this capability. */
15
+ paths: string[];
16
+ /** Optional start URL for the drive (overrides any environment). */
17
+ url?: string;
18
+ /** Optional named environment to target (else the config's default target). */
19
+ environment?: string;
20
+ /** Optional persona (role) to drive this capability as. */
21
+ persona?: string;
22
+ /** Optional goal for the model (else derived from the capability). */
23
+ goal?: string;
24
+ /** Optional corpus artifact path to propose the write-back to. */
25
+ artifact?: string;
26
+ }
27
+ /** A user role the drive can act as. */
28
+ export interface PersonaConfig {
29
+ name: string;
30
+ /** Areas this role should focus on. */
31
+ testFocus?: string[];
32
+ /** Actions this role must not perform. */
33
+ cannotDo?: string[];
34
+ }
35
+ /** A named environment the drive can target. */
36
+ export interface EnvironmentConfig {
37
+ url: string;
38
+ /** Human-readable directives the drive must respect (e.g. "read-only; never create data"). */
39
+ restrictions?: string[];
40
+ }
41
+ /** How the product authenticates — described, never the credentials themselves. */
42
+ export interface AuthConfig {
43
+ method: string;
44
+ provider?: string;
45
+ }
46
+ /** How accumulated failure knowledge is surfaced (Factory automated-qa's `failure_learning`). */
47
+ export type FailureLearningStrategy = "suggest_in_report" | "auto_commit" | "open_a_pr";
48
+ export interface ProofkeeperConfig {
49
+ capabilities: CapabilityConfig[];
50
+ /** Named environments (e.g. development, production). */
51
+ environments?: Record<string, EnvironmentConfig>;
52
+ /** The default environment name used when a capability names none. */
53
+ defaultTarget?: string;
54
+ /** How the product authenticates. */
55
+ auth?: AuthConfig;
56
+ /** User roles a capability can be driven as. */
57
+ personas?: PersonaConfig[];
58
+ /** How failure knowledge is surfaced. Defaults to `suggest_in_report`. */
59
+ failureLearning?: FailureLearningStrategy;
60
+ }
61
+ /** A capability's resolved run target. */
62
+ export interface ResolvedTarget {
63
+ name: string;
64
+ url: string;
65
+ restrictions: string[];
66
+ }
67
+ /** Raised when the config is not a recognizable shape. */
68
+ export declare class ConfigParseError extends Error {
69
+ constructor(message: string);
70
+ }
71
+ /** Parse a Proofkeeper config from JSON. Strict on the shape scoping depends on. */
72
+ export declare function parseConfig(json: string): ProofkeeperConfig;
73
+ /**
74
+ * Goal context for a capability's selected persona, or undefined when it names
75
+ * none. Throws when the named persona is not defined in the config.
76
+ */
77
+ export declare function personaContext(config: ProofkeeperConfig, cap: CapabilityConfig): string | undefined;
78
+ /**
79
+ * Resolve a capability's run target: an explicit `cap.url` wins; otherwise the
80
+ * environment named by `cap.environment ?? config.defaultTarget`; otherwise the
81
+ * caller's fallback URL. Returns undefined when no URL can be determined.
82
+ */
83
+ export declare function resolveTarget(config: ProofkeeperConfig, cap: CapabilityConfig, opts: {
84
+ fallbackUrl?: string;
85
+ defaultName: string;
86
+ }): ResolvedTarget | undefined;
87
+ /** A one-line auth context for the drive goal, or undefined when no auth is configured. */
88
+ export declare function authContext(config: ProofkeeperConfig): string | undefined;
89
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/scope/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,sCAAsC;AACtC,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,EAAE,EAAE,MAAM,CAAC;IACX,sFAAsF;IACtF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,oEAAoE;IACpE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wCAAwC;AACxC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,gDAAgD;AAChD,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,8FAA8F;IAC9F,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,mFAAmF;AACnF,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,iGAAiG;AACjG,MAAM,MAAM,uBAAuB,GAAG,mBAAmB,GAAG,aAAa,GAAG,WAAW,CAAC;AAQxF,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACjD,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;IAC3B,0EAA0E;IAC1E,eAAe,CAAC,EAAE,uBAAuB,CAAC;CAC3C;AAED,0CAA0C;AAC1C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,0DAA0D;AAC1D,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AA0ED,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAkB3D;AASD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,iBAAiB,EAAE,GAAG,EAAE,gBAAgB,GAAG,MAAM,GAAG,SAAS,CAQnG;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,iBAAiB,EACzB,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAClD,cAAc,GAAG,SAAS,CAa5B;AAED,2FAA2F;AAC3F,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAGzE"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * The Proofkeeper scope config — which capabilities a changed file touches.
3
+ *
4
+ * Modeled on Factory automated-qa's `path_patterns`: a config maps each
5
+ * capability to the source-path globs whose change implies it should be
6
+ * re-verified, plus optional drive overrides (start URL, goal) and the corpus
7
+ * artifact to write `## Verified By` back to. It is the only place Proofkeeper
8
+ * needs to know how product capabilities relate to source files.
9
+ */
10
+ const FAILURE_LEARNING_STRATEGIES = [
11
+ "suggest_in_report",
12
+ "auto_commit",
13
+ "open_a_pr",
14
+ ];
15
+ /** Raised when the config is not a recognizable shape. */
16
+ export class ConfigParseError extends Error {
17
+ constructor(message) {
18
+ super(message);
19
+ this.name = "ConfigParseError";
20
+ }
21
+ }
22
+ function isObject(value) {
23
+ return typeof value === "object" && value !== null && !Array.isArray(value);
24
+ }
25
+ function parseCapability(raw, index) {
26
+ if (!isObject(raw))
27
+ throw new ConfigParseError(`capabilities[${index}] is not an object`);
28
+ const id = raw["id"];
29
+ if (typeof id !== "string" || id === "") {
30
+ throw new ConfigParseError(`capabilities[${index}].id must be a non-empty string`);
31
+ }
32
+ const paths = raw["paths"];
33
+ if (!Array.isArray(paths) || paths.length === 0 || !paths.every((p) => typeof p === "string")) {
34
+ throw new ConfigParseError(`capabilities[${index}].paths must be a non-empty array of glob strings`);
35
+ }
36
+ const cap = { id, paths: paths };
37
+ if (typeof raw["url"] === "string")
38
+ cap.url = raw["url"];
39
+ if (typeof raw["environment"] === "string")
40
+ cap.environment = raw["environment"];
41
+ if (typeof raw["persona"] === "string")
42
+ cap.persona = raw["persona"];
43
+ if (typeof raw["goal"] === "string")
44
+ cap.goal = raw["goal"];
45
+ if (typeof raw["artifact"] === "string")
46
+ cap.artifact = raw["artifact"];
47
+ return cap;
48
+ }
49
+ function stringArray(value, where) {
50
+ if (!Array.isArray(value) || !value.every((v) => typeof v === "string")) {
51
+ throw new ConfigParseError(`${where} must be an array of strings`);
52
+ }
53
+ return value;
54
+ }
55
+ function parsePersonas(raw) {
56
+ if (!Array.isArray(raw))
57
+ throw new ConfigParseError("`personas` must be an array");
58
+ return raw.map((value, index) => {
59
+ if (!isObject(value) || typeof value["name"] !== "string" || value["name"] === "") {
60
+ throw new ConfigParseError(`personas[${index}].name must be a non-empty string`);
61
+ }
62
+ const persona = { name: value["name"] };
63
+ if (value["testFocus"] !== undefined)
64
+ persona.testFocus = stringArray(value["testFocus"], `personas[${index}].testFocus`);
65
+ if (value["cannotDo"] !== undefined)
66
+ persona.cannotDo = stringArray(value["cannotDo"], `personas[${index}].cannotDo`);
67
+ return persona;
68
+ });
69
+ }
70
+ function parseEnvironments(raw) {
71
+ if (!isObject(raw))
72
+ throw new ConfigParseError("`environments` must be an object");
73
+ const out = {};
74
+ for (const [name, value] of Object.entries(raw)) {
75
+ if (!isObject(value) || typeof value["url"] !== "string") {
76
+ throw new ConfigParseError(`environment '${name}' must have a string url`);
77
+ }
78
+ const env = { url: value["url"] };
79
+ const restrictions = value["restrictions"];
80
+ if (restrictions !== undefined) {
81
+ if (!Array.isArray(restrictions) || !restrictions.every((r) => typeof r === "string")) {
82
+ throw new ConfigParseError(`environment '${name}'.restrictions must be an array of strings`);
83
+ }
84
+ env.restrictions = restrictions;
85
+ }
86
+ out[name] = env;
87
+ }
88
+ return out;
89
+ }
90
+ function parseAuth(raw) {
91
+ if (!isObject(raw) || typeof raw["method"] !== "string") {
92
+ throw new ConfigParseError("`auth` must have a string method");
93
+ }
94
+ const auth = { method: raw["method"] };
95
+ if (typeof raw["provider"] === "string")
96
+ auth.provider = raw["provider"];
97
+ return auth;
98
+ }
99
+ /** Parse a Proofkeeper config from JSON. Strict on the shape scoping depends on. */
100
+ export function parseConfig(json) {
101
+ let raw;
102
+ try {
103
+ raw = JSON.parse(json);
104
+ }
105
+ catch (err) {
106
+ throw new ConfigParseError(`config is not valid JSON: ${err.message}`);
107
+ }
108
+ if (!isObject(raw) || !Array.isArray(raw["capabilities"])) {
109
+ throw new ConfigParseError("config must be an object with a `capabilities` array");
110
+ }
111
+ const config = { capabilities: raw["capabilities"].map(parseCapability) };
112
+ if (raw["environments"] !== undefined)
113
+ config.environments = parseEnvironments(raw["environments"]);
114
+ if (typeof raw["defaultTarget"] === "string")
115
+ config.defaultTarget = raw["defaultTarget"];
116
+ if (raw["auth"] !== undefined)
117
+ config.auth = parseAuth(raw["auth"]);
118
+ if (raw["personas"] !== undefined)
119
+ config.personas = parsePersonas(raw["personas"]);
120
+ config.failureLearning =
121
+ raw["failureLearning"] !== undefined ? parseFailureLearning(raw["failureLearning"]) : "suggest_in_report";
122
+ return config;
123
+ }
124
+ function parseFailureLearning(raw) {
125
+ if (typeof raw !== "string" || !FAILURE_LEARNING_STRATEGIES.includes(raw)) {
126
+ throw new ConfigParseError(`failureLearning must be one of: ${FAILURE_LEARNING_STRATEGIES.join(", ")}`);
127
+ }
128
+ return raw;
129
+ }
130
+ /**
131
+ * Goal context for a capability's selected persona, or undefined when it names
132
+ * none. Throws when the named persona is not defined in the config.
133
+ */
134
+ export function personaContext(config, cap) {
135
+ if (cap.persona === undefined)
136
+ return undefined;
137
+ const persona = config.personas?.find((p) => p.name === cap.persona);
138
+ if (!persona)
139
+ throw new ConfigParseError(`capability '${cap.id}' references undefined persona '${cap.persona}'`);
140
+ const parts = [`Act as the ${persona.name} persona.`];
141
+ if (persona.testFocus && persona.testFocus.length > 0)
142
+ parts.push(`Focus on: ${persona.testFocus.join(", ")}.`);
143
+ if (persona.cannotDo && persona.cannotDo.length > 0)
144
+ parts.push(`Do not: ${persona.cannotDo.join(", ")}.`);
145
+ return parts.join(" ");
146
+ }
147
+ /**
148
+ * Resolve a capability's run target: an explicit `cap.url` wins; otherwise the
149
+ * environment named by `cap.environment ?? config.defaultTarget`; otherwise the
150
+ * caller's fallback URL. Returns undefined when no URL can be determined.
151
+ */
152
+ export function resolveTarget(config, cap, opts) {
153
+ if (cap.url !== undefined) {
154
+ return { name: opts.defaultName, url: cap.url, restrictions: [] };
155
+ }
156
+ const envName = cap.environment ?? config.defaultTarget;
157
+ const env = envName !== undefined ? config.environments?.[envName] : undefined;
158
+ if (env) {
159
+ return { name: envName, url: env.url, restrictions: env.restrictions ?? [] };
160
+ }
161
+ if (opts.fallbackUrl !== undefined) {
162
+ return { name: opts.defaultName, url: opts.fallbackUrl, restrictions: [] };
163
+ }
164
+ return undefined;
165
+ }
166
+ /** A one-line auth context for the drive goal, or undefined when no auth is configured. */
167
+ export function authContext(config) {
168
+ if (!config.auth)
169
+ return undefined;
170
+ return `Authentication: ${config.auth.method}${config.auth.provider ? ` via ${config.auth.provider}` : ""}.`;
171
+ }
172
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/scope/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Scope verification to a change — Proofkeeper's PR-triggered QA.
3
+ *
4
+ * Given the files a pull request changed, the scope config, and the coverage
5
+ * graph, decide which capabilities the change touches and which of those still
6
+ * lack a verifying test. Pure: no git, no I/O. The CLI supplies the changed
7
+ * paths (from `--changed` or a `git diff`); this decides what to drive.
8
+ */
9
+ import type { Graph } from "../coverage/graph.js";
10
+ import type { CapabilityConfig, ProofkeeperConfig } from "./config.js";
11
+ /** A capability the change touched, with how it matched and its verified state. */
12
+ export interface ScopedCapability {
13
+ id: string;
14
+ title: string;
15
+ config: CapabilityConfig;
16
+ /** True when the graph already has a verifying test for it. */
17
+ verified: boolean;
18
+ /** The changed paths that matched this capability's globs. */
19
+ matchedPaths: string[];
20
+ }
21
+ export interface ScopeResult {
22
+ /** Capabilities whose source paths intersect the diff. */
23
+ scoped: ScopedCapability[];
24
+ /** The subset of `scoped` that is currently unverified — the drive targets. */
25
+ toVerify: ScopedCapability[];
26
+ /** Config ids that matched the diff but are not capability nodes in the graph. */
27
+ unknown: string[];
28
+ }
29
+ /** Decide which capabilities a set of changed paths touches, and which need verifying. */
30
+ export declare function scopeCapabilities(changedPaths: string[], config: ProofkeeperConfig, graph: Graph): ScopeResult;
31
+ //# sourceMappingURL=diff-scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-scope.d.ts","sourceRoot":"","sources":["../../src/scope/diff-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGvE,mFAAmF;AACnF,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,gBAAgB,CAAC;IACzB,+DAA+D;IAC/D,QAAQ,EAAE,OAAO,CAAC;IAClB,8DAA8D;IAC9D,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,0DAA0D;IAC1D,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,+EAA+E;IAC/E,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,kFAAkF;IAClF,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,0FAA0F;AAC1F,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,EAAE,EACtB,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,KAAK,GACX,WAAW,CA8Bb"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Scope verification to a change — Proofkeeper's PR-triggered QA.
3
+ *
4
+ * Given the files a pull request changed, the scope config, and the coverage
5
+ * graph, decide which capabilities the change touches and which of those still
6
+ * lack a verifying test. Pure: no git, no I/O. The CLI supplies the changed
7
+ * paths (from `--changed` or a `git diff`); this decides what to drive.
8
+ */
9
+ import { computeCoverage } from "../coverage/model.js";
10
+ import { matchesAnyGlob } from "./glob.js";
11
+ /** Decide which capabilities a set of changed paths touches, and which need verifying. */
12
+ export function scopeCapabilities(changedPaths, config, graph) {
13
+ const report = computeCoverage(graph);
14
+ const titleById = new Map();
15
+ const verifiedIds = new Set();
16
+ for (const c of report.verified) {
17
+ titleById.set(c.id, c.title);
18
+ verifiedIds.add(c.id);
19
+ }
20
+ for (const c of report.unverified)
21
+ titleById.set(c.id, c.title);
22
+ const scoped = [];
23
+ const unknown = [];
24
+ for (const cap of config.capabilities) {
25
+ const matchedPaths = changedPaths.filter((p) => matchesAnyGlob(p, cap.paths));
26
+ if (matchedPaths.length === 0)
27
+ continue;
28
+ if (!titleById.has(cap.id)) {
29
+ unknown.push(cap.id);
30
+ continue;
31
+ }
32
+ scoped.push({
33
+ id: cap.id,
34
+ title: titleById.get(cap.id),
35
+ config: cap,
36
+ verified: verifiedIds.has(cap.id),
37
+ matchedPaths,
38
+ });
39
+ }
40
+ return { scoped, toVerify: scoped.filter((s) => !s.verified), unknown };
41
+ }
42
+ //# sourceMappingURL=diff-scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-scope.js","sourceRoot":"","sources":["../../src/scope/diff-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAsB3C,0FAA0F;AAC1F,MAAM,UAAU,iBAAiB,CAC/B,YAAsB,EACtB,MAAyB,EACzB,KAAY;IAEZ,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QAC7B,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,UAAU;QAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;IAEhE,MAAM,MAAM,GAAuB,EAAE,CAAC;IACtC,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACtC,MAAM,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9E,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACxC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACrB,SAAS;QACX,CAAC;QACD,MAAM,CAAC,IAAI,CAAC;YACV,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAE;YAC7B,MAAM,EAAE,GAAG;YACX,QAAQ,EAAE,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACjC,YAAY;SACb,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * A tiny, dependency-free glob matcher for scoping capabilities by changed
3
+ * files (Factory automated-qa's `path_patterns`). Proofkeeper bundles no glob
4
+ * library; this covers the patterns a path map needs:
5
+ *
6
+ * - `*` matches within a path segment (any run of non-`/` characters)
7
+ * - `**` matches across segments (any characters, including `/`)
8
+ * - `**​/` matches zero or more leading directories
9
+ * - `?` matches a single non-`/` character
10
+ *
11
+ * Everything else is matched literally. Patterns are anchored to the full path.
12
+ */
13
+ /** Compile a glob to an anchored RegExp. Pure and deterministic. */
14
+ export declare function globToRegExp(glob: string): RegExp;
15
+ /** True when `path` matches any of the globs. */
16
+ export declare function matchesAnyGlob(path: string, globs: string[]): boolean;
17
+ //# sourceMappingURL=glob.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../../src/scope/glob.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAyBjD;AAED,iDAAiD;AACjD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAErE"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * A tiny, dependency-free glob matcher for scoping capabilities by changed
3
+ * files (Factory automated-qa's `path_patterns`). Proofkeeper bundles no glob
4
+ * library; this covers the patterns a path map needs:
5
+ *
6
+ * - `*` matches within a path segment (any run of non-`/` characters)
7
+ * - `**` matches across segments (any characters, including `/`)
8
+ * - `**​/` matches zero or more leading directories
9
+ * - `?` matches a single non-`/` character
10
+ *
11
+ * Everything else is matched literally. Patterns are anchored to the full path.
12
+ */
13
+ const REGEX_SPECIAL = new Set("\\^$.|+()[]{}".split(""));
14
+ /** Compile a glob to an anchored RegExp. Pure and deterministic. */
15
+ export function globToRegExp(glob) {
16
+ let re = "";
17
+ for (let i = 0; i < glob.length; i++) {
18
+ const c = glob[i];
19
+ if (c === "*") {
20
+ if (glob[i + 1] === "*") {
21
+ i++; // consume the second '*'
22
+ if (glob[i + 1] === "/") {
23
+ i++; // consume the '/'
24
+ re += "(?:.*/)?"; // '**/' → zero or more directories
25
+ }
26
+ else {
27
+ re += ".*"; // '**' → anything, across separators
28
+ }
29
+ }
30
+ else {
31
+ re += "[^/]*"; // '*' → within a segment
32
+ }
33
+ }
34
+ else if (c === "?") {
35
+ re += "[^/]";
36
+ }
37
+ else if (REGEX_SPECIAL.has(c)) {
38
+ re += "\\" + c;
39
+ }
40
+ else {
41
+ re += c;
42
+ }
43
+ }
44
+ return new RegExp("^" + re + "$");
45
+ }
46
+ /** True when `path` matches any of the globs. */
47
+ export function matchesAnyGlob(path, globs) {
48
+ return globs.some((g) => globToRegExp(g).test(path));
49
+ }
50
+ //# sourceMappingURL=glob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob.js","sourceRoot":"","sources":["../../src/scope/glob.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;AAEzD,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACd,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACxB,CAAC,EAAE,CAAC,CAAC,yBAAyB;gBAC9B,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;oBACxB,CAAC,EAAE,CAAC,CAAC,kBAAkB;oBACvB,EAAE,IAAI,UAAU,CAAC,CAAC,mCAAmC;gBACvD,CAAC;qBAAM,CAAC;oBACN,EAAE,IAAI,IAAI,CAAC,CAAC,qCAAqC;gBACnD,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,EAAE,IAAI,OAAO,CAAC,CAAC,yBAAyB;YAC1C,CAAC;QACH,CAAC;aAAM,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACrB,EAAE,IAAI,MAAM,CAAC;QACf,CAAC;aAAM,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAChC,EAAE,IAAI,IAAI,GAAG,CAAC,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,EAAE,IAAI,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IACD,OAAO,IAAI,MAAM,CAAC,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC;AACpC,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,KAAe;IAC1D,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACvD,CAAC"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Pull-request comment renderers — Proofkeeper Initiative 5.
3
+ *
4
+ * Two informational comments, both behind the human-review boundary (ADR-065):
5
+ * Proofkeeper never merges or approves; it only reports.
6
+ *
7
+ * - {@link renderWriteBackComment}: a confirmation on the write-back PR it
8
+ * raises — the linked evidence plus the fidelity result.
9
+ * - {@link renderCoverageComment}: a verification-coverage status for a
10
+ * developer's feature PR, driven by the coverage read-model.
11
+ *
12
+ * Pure string builders (no I/O) so they are unit-testable; the gateway posts.
13
+ */
14
+ import type { CoverageReport } from "../coverage/model.js";
15
+ import type { RepoGateway } from "./proposer.js";
16
+ import type { VerificationLink } from "./verified-by.js";
17
+ /**
18
+ * Hidden, namespaced markers identifying each Proofkeeper comment kind. Embedded
19
+ * as invisible HTML comments at the top of a body so a pull request carries one
20
+ * canonical comment per kind that {@link upsertComment} finds and updates in
21
+ * place, regardless of how the prose is reformatted.
22
+ */
23
+ export declare const SCOPED_QA_MARKER = "<!-- proofkeeper:scoped-qa -->";
24
+ export declare const WRITE_BACK_MARKER = "<!-- proofkeeper:write-back -->";
25
+ export declare const COVERAGE_MARKER = "<!-- proofkeeper:coverage -->";
26
+ /** Outcome of the fidelity gate, as summarized in a comment. */
27
+ export interface FidelitySummary {
28
+ attempts: number;
29
+ passed: number;
30
+ stable: boolean;
31
+ }
32
+ /** Confirmation comment for the write-back PR Proofkeeper raises. */
33
+ export declare function renderWriteBackComment(input: {
34
+ capabilityId: string;
35
+ links: VerificationLink[];
36
+ fidelity?: FidelitySummary;
37
+ /** Readable step summary of the driven flow. */
38
+ steps?: string[];
39
+ /** The Markdown test plan the model wrote before driving. */
40
+ plan?: string;
41
+ }): string;
42
+ export interface CoverageCommentOptions {
43
+ /** Optional heading override. */
44
+ title?: string;
45
+ }
46
+ /** Verification-coverage status comment for a developer's feature PR. */
47
+ export declare function renderCoverageComment(report: CoverageReport, options?: CoverageCommentOptions): string;
48
+ /** One driven capability's outcome, as summarized in the scoped-QA comment. */
49
+ export interface ScopedQaCommentRow {
50
+ id: string;
51
+ title: string;
52
+ stable?: boolean;
53
+ writeBackUrl?: string;
54
+ /** Set when the capability could not be driven. */
55
+ error?: string;
56
+ }
57
+ export interface ScopedQaCommentInput {
58
+ changedCount: number;
59
+ driven: ScopedQaCommentRow[];
60
+ /** Scoped capabilities already verified — not re-driven. */
61
+ alreadyVerified: {
62
+ id: string;
63
+ title: string;
64
+ }[];
65
+ /** Config ids that matched the diff but are not capability nodes. */
66
+ unknown: string[];
67
+ /** Recorded failure reasons per failed capability (suggest-in-report strategy). */
68
+ failureSuggestions?: {
69
+ id: string;
70
+ title: string;
71
+ reasons: string[];
72
+ }[];
73
+ }
74
+ /** Scoped-QA evidence comment for the feature PR that triggered the run. */
75
+ export declare function renderScopedQaComment(input: ScopedQaCommentInput): string;
76
+ /**
77
+ * Maintain exactly one comment per kind on a pull request: find the existing
78
+ * comment whose body carries `marker` and update it in place; otherwise create
79
+ * one (the body itself carries the marker, so it is self-identifying next time).
80
+ * Keys only on the marker, never on prose.
81
+ */
82
+ export declare function upsertComment(gateway: RepoGateway, input: {
83
+ number: number;
84
+ marker: string;
85
+ body: string;
86
+ }): Promise<{
87
+ url: string;
88
+ updated: boolean;
89
+ }>;
90
+ /**
91
+ * Post (or update in place) a verification-coverage status comment on a feature
92
+ * pull request. The report comes from the coverage read-model (`computeCoverage`).
93
+ * Informational only — it never approves or merges.
94
+ */
95
+ export declare function commentCoverageStatus(gateway: RepoGateway, input: {
96
+ prNumber: number;
97
+ report: CoverageReport;
98
+ options?: CoverageCommentOptions;
99
+ }): Promise<{
100
+ url: string;
101
+ updated: boolean;
102
+ }>;
103
+ //# sourceMappingURL=comment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment.d.ts","sourceRoot":"","sources":["../../src/writeback/comment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAKzD;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,mCAAmC,CAAC;AACjE,eAAO,MAAM,iBAAiB,oCAAoC,CAAC;AACnE,eAAO,MAAM,eAAe,kCAAkC,CAAC;AAE/D,gEAAgE;AAChE,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB;AAMD,qEAAqE;AACrE,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,MAAM,CA4BT;AAED,MAAM,WAAW,sBAAsB;IACrC,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,yEAAyE;AACzE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,GAAE,sBAA2B,GAAG,MAAM,CA4B1G;AAED,+EAA+E;AAC/E,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,4DAA4D;IAC5D,eAAe,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACjD,qEAAqE;IACrE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,mFAAmF;IACnF,kBAAkB,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;CACzE;AAED,4EAA4E;AAC5E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAkCzE;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACtD,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAS5C;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,cAAc,CAAC;IAAC,OAAO,CAAC,EAAE,sBAAsB,CAAA;CAAE,GACpF,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAM5C"}