ndrstnd 0.1.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 (83) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +56 -0
  3. package/dist/server/agent.d.ts +51 -0
  4. package/dist/server/agent.js +77 -0
  5. package/dist/server/agent.js.map +1 -0
  6. package/dist/server/analysis-core.d.ts +93 -0
  7. package/dist/server/analysis-core.js +442 -0
  8. package/dist/server/analysis-core.js.map +1 -0
  9. package/dist/server/analyze.d.ts +55 -0
  10. package/dist/server/analyze.js +72 -0
  11. package/dist/server/analyze.js.map +1 -0
  12. package/dist/server/artifact.d.ts +8 -0
  13. package/dist/server/artifact.js +43 -0
  14. package/dist/server/artifact.js.map +1 -0
  15. package/dist/server/claude.d.ts +29 -0
  16. package/dist/server/claude.js +243 -0
  17. package/dist/server/claude.js.map +1 -0
  18. package/dist/server/cli-support.d.ts +7 -0
  19. package/dist/server/cli-support.js +13 -0
  20. package/dist/server/cli-support.js.map +1 -0
  21. package/dist/server/cli.d.ts +2 -0
  22. package/dist/server/cli.js +276 -0
  23. package/dist/server/cli.js.map +1 -0
  24. package/dist/server/codex.d.ts +34 -0
  25. package/dist/server/codex.js +256 -0
  26. package/dist/server/codex.js.map +1 -0
  27. package/dist/server/conversation.d.ts +9 -0
  28. package/dist/server/conversation.js +57 -0
  29. package/dist/server/conversation.js.map +1 -0
  30. package/dist/server/evidence-ordering.d.ts +13 -0
  31. package/dist/server/evidence-ordering.js +143 -0
  32. package/dist/server/evidence-ordering.js.map +1 -0
  33. package/dist/server/git-model.d.ts +15 -0
  34. package/dist/server/git-model.js +156 -0
  35. package/dist/server/git-model.js.map +1 -0
  36. package/dist/server/git.d.ts +29 -0
  37. package/dist/server/git.js +124 -0
  38. package/dist/server/git.js.map +1 -0
  39. package/dist/server/http.d.ts +14 -0
  40. package/dist/server/http.js +139 -0
  41. package/dist/server/http.js.map +1 -0
  42. package/dist/server/preview-fixture.d.ts +1 -0
  43. package/dist/server/preview-fixture.js +23 -0
  44. package/dist/server/preview-fixture.js.map +1 -0
  45. package/dist/server/review-presentation.d.ts +3 -0
  46. package/dist/server/review-presentation.js +14 -0
  47. package/dist/server/review-presentation.js.map +1 -0
  48. package/dist/server/skill.d.ts +14 -0
  49. package/dist/server/skill.js +94 -0
  50. package/dist/server/skill.js.map +1 -0
  51. package/dist/server/store.d.ts +36 -0
  52. package/dist/server/store.js +134 -0
  53. package/dist/server/store.js.map +1 -0
  54. package/dist/server/version.d.ts +2 -0
  55. package/dist/server/version.js +13 -0
  56. package/dist/server/version.js.map +1 -0
  57. package/dist/shared/analysis-schema.d.ts +325 -0
  58. package/dist/shared/analysis-schema.js +50 -0
  59. package/dist/shared/analysis-schema.js.map +1 -0
  60. package/dist/shared/domain.d.ts +33 -0
  61. package/dist/shared/domain.js +2 -0
  62. package/dist/shared/domain.js.map +1 -0
  63. package/dist/web/evidence-model.d.ts +36 -0
  64. package/dist/web/evidence-model.js +134 -0
  65. package/dist/web/evidence-model.js.map +1 -0
  66. package/dist/web/frozen-review-data.d.ts +3 -0
  67. package/dist/web/frozen-review-data.js +202 -0
  68. package/dist/web/frozen-review-data.js.map +1 -0
  69. package/dist/web/language.d.ts +4 -0
  70. package/dist/web/language.js +14 -0
  71. package/dist/web/language.js.map +1 -0
  72. package/dist/web/page.d.ts +10 -0
  73. package/dist/web/page.js +1038 -0
  74. package/dist/web/page.js.map +1 -0
  75. package/dist/web/review-data.d.ts +20 -0
  76. package/dist/web/review-data.js +2 -0
  77. package/dist/web/review-data.js.map +1 -0
  78. package/dist/web/test-plan-model.d.ts +27 -0
  79. package/dist/web/test-plan-model.js +89 -0
  80. package/dist/web/test-plan-model.js.map +1 -0
  81. package/package.json +47 -0
  82. package/src/skill-assets/ndrstnd/SKILL.md +22 -0
  83. package/src/skill-assets/ndrstnd/agents/openai.yaml +4 -0
@@ -0,0 +1,94 @@
1
+ import { cp, mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { reviewAgents, reviewAgentById } from "./agent.js";
5
+ function bundledSkillDirectory() {
6
+ return join(dirname(fileURLToPath(import.meta.url)), "../../src/skill-assets/ndrstnd");
7
+ }
8
+ function installedSkillDirectory(agent) {
9
+ return join(agent.homeDirectory(), "skills", "ndrstnd");
10
+ }
11
+ /** True when any installed skill differs from the bundled one in any file, meaning that agent follows outdated instructions or assets. */
12
+ export async function installedSkillIsStale() {
13
+ for (const agent of reviewAgents) {
14
+ const destination = installedSkillDirectory(agent);
15
+ if (!(await exists(destination)))
16
+ continue;
17
+ try {
18
+ const [bundled, installed] = await Promise.all([skillFiles(bundledSkillDirectory()), skillFiles(destination)]);
19
+ if (bundled.size !== installed.size)
20
+ return true;
21
+ for (const [path, content] of bundled) {
22
+ if (installed.get(path) !== content)
23
+ return true;
24
+ }
25
+ }
26
+ catch {
27
+ // An unreadable installation is reported at install time, not on every review.
28
+ }
29
+ }
30
+ return false;
31
+ }
32
+ async function skillFiles(root) {
33
+ const files = new Map();
34
+ const walk = async (relative) => {
35
+ for (const entry of await readdir(join(root, relative), { withFileTypes: true })) {
36
+ const childRelative = join(relative, entry.name);
37
+ if (entry.isDirectory())
38
+ await walk(childRelative);
39
+ else
40
+ files.set(childRelative, await readFile(join(root, childRelative), "utf8"));
41
+ }
42
+ };
43
+ await walk(".");
44
+ return files;
45
+ }
46
+ /**
47
+ * Installs the bundled skill for the requested agent, or for every agent whose
48
+ * configuration directory exists when none is requested explicitly.
49
+ */
50
+ export async function installSkill(force = false, agentId) {
51
+ const source = bundledSkillDirectory();
52
+ const targets = agentId === undefined ? await detectedAgents() : [requireAgent(agentId)];
53
+ if (targets.length === 0) {
54
+ throw new Error(`No supported agent is set up: none of ${reviewAgents.map((agent) => agent.homeDirectory()).join(", ")} exists. Install Codex or Claude Code first, or pass --agent to choose one explicitly.`);
55
+ }
56
+ const installations = [];
57
+ for (const agent of targets) {
58
+ const destination = installedSkillDirectory(agent);
59
+ if (!force && await exists(destination)) {
60
+ installations.push({ agent, destination, status: "skipped", reason: `the ndrstnd skill already exists at ${destination}; re-run with --force to replace it` });
61
+ continue;
62
+ }
63
+ await mkdir(dirname(destination), { recursive: true });
64
+ // A merge-copy would leave files a newer release removed; replace the installation wholesale.
65
+ await rm(destination, { recursive: true, force: true });
66
+ await cp(source, destination, { recursive: true, force: true });
67
+ installations.push({ agent, destination, status: "installed" });
68
+ }
69
+ return installations;
70
+ }
71
+ function requireAgent(agentId) {
72
+ const agent = reviewAgentById(agentId);
73
+ if (agent === undefined)
74
+ throw new Error(`Unknown analysis agent: ${agentId}.`);
75
+ return agent;
76
+ }
77
+ async function detectedAgents() {
78
+ const detected = [];
79
+ for (const agent of reviewAgents) {
80
+ if (await exists(agent.homeDirectory()))
81
+ detected.push(agent);
82
+ }
83
+ return detected;
84
+ }
85
+ async function exists(path) {
86
+ try {
87
+ await stat(path);
88
+ return true;
89
+ }
90
+ catch {
91
+ return false;
92
+ }
93
+ }
94
+ //# sourceMappingURL=skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/server/skill.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { ConversationContext } from "./conversation.js";
2
+ import { type AnalysisDocument } from "../shared/analysis-schema.js";
3
+ import type { CollectedReviewInput } from "./git.js";
4
+ export interface StoredReviewSession {
5
+ id: string;
6
+ repoPath: string;
7
+ targetRef: string;
8
+ baseRef: string;
9
+ mergeBase: string;
10
+ inputHash: string;
11
+ input: CollectedReviewInput;
12
+ conversation?: ConversationContext;
13
+ createdAt: string;
14
+ }
15
+ export interface AnalysisRevision {
16
+ id: string;
17
+ sessionId: string;
18
+ status: "partial" | "complete" | "failed";
19
+ source: "fallback" | "codex" | "claude";
20
+ document: AnalysisDocument;
21
+ createdAt: string;
22
+ }
23
+ /** True for revisions produced by a real analysis agent, excluding legacy fallback rows. */
24
+ export declare function isAgentRevision(revision: AnalysisRevision): boolean;
25
+ /** A cached revision may only stand in for a new analysis when the requested agent produced it and it completed. */
26
+ export declare function selectReusableRevision(revisions: readonly AnalysisRevision[], agentId: string): AnalysisRevision | undefined;
27
+ export declare class ReviewStore {
28
+ private readonly database;
29
+ constructor(databasePath?: string);
30
+ getOrCreateSession(input: CollectedReviewInput, conversation?: ConversationContext): StoredReviewSession;
31
+ getSession(id: string): StoredReviewSession | undefined;
32
+ createRevision(sessionId: string, source: AnalysisRevision["source"], status: AnalysisRevision["status"], document: AnalysisDocument): AnalysisRevision;
33
+ /** Rows written for another document version, or whose stored document no longer validates, read as absent so the caller re-analyzes instead of rendering a broken artifact. */
34
+ listRevisions(sessionId: string): AnalysisRevision[];
35
+ close(): void;
36
+ }
@@ -0,0 +1,134 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { mkdirSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { dirname, join } from "node:path";
5
+ import Database from "better-sqlite3";
6
+ import { ANALYSIS_DOCUMENT_VERSION, AnalysisDocumentSchema } from "../shared/analysis-schema.js";
7
+ /** True for revisions produced by a real analysis agent, excluding legacy fallback rows. */
8
+ export function isAgentRevision(revision) {
9
+ return revision.source !== "fallback";
10
+ }
11
+ /** A cached revision may only stand in for a new analysis when the requested agent produced it and it completed. */
12
+ export function selectReusableRevision(revisions, agentId) {
13
+ return revisions.find((revision) => revision.source === agentId && revision.status === "complete");
14
+ }
15
+ export class ReviewStore {
16
+ database;
17
+ constructor(databasePath = defaultDatabasePath()) {
18
+ mkdirSync(dirname(databasePath), { recursive: true });
19
+ this.database = new Database(databasePath);
20
+ this.database.pragma("journal_mode = WAL");
21
+ this.database.exec(`
22
+ CREATE TABLE IF NOT EXISTS review_session (
23
+ id TEXT PRIMARY KEY,
24
+ repo_path TEXT NOT NULL,
25
+ target_ref TEXT NOT NULL,
26
+ base_ref TEXT NOT NULL,
27
+ merge_base TEXT NOT NULL,
28
+ input_hash TEXT NOT NULL UNIQUE,
29
+ input_json TEXT NOT NULL,
30
+ created_at TEXT NOT NULL
31
+ );
32
+ CREATE TABLE IF NOT EXISTS analysis_revision (
33
+ id TEXT PRIMARY KEY,
34
+ session_id TEXT NOT NULL REFERENCES review_session(id),
35
+ status TEXT NOT NULL,
36
+ source TEXT NOT NULL,
37
+ document_json TEXT NOT NULL,
38
+ created_at TEXT NOT NULL
39
+ );
40
+ `);
41
+ const columns = this.database.prepare("PRAGMA table_info(review_session)").all();
42
+ if (!columns.some((column) => column.name === "conversation_json")) {
43
+ this.database.exec("ALTER TABLE review_session ADD COLUMN conversation_json TEXT");
44
+ }
45
+ const revisionColumns = this.database.prepare("PRAGMA table_info(analysis_revision)").all();
46
+ if (!revisionColumns.some((column) => column.name === "document_version")) {
47
+ this.database.exec("ALTER TABLE analysis_revision ADD COLUMN document_version INTEGER");
48
+ }
49
+ }
50
+ getOrCreateSession(input, conversation) {
51
+ const inputHash = hashInput(input, conversation);
52
+ const session = {
53
+ id: randomUUID(),
54
+ repoPath: input.repoPath,
55
+ targetRef: input.targetRef,
56
+ baseRef: input.baseRef,
57
+ mergeBase: input.mergeBase,
58
+ inputHash,
59
+ input,
60
+ conversation,
61
+ createdAt: new Date().toISOString(),
62
+ };
63
+ // Insert-then-select keeps concurrent reviews of the same input from racing a separate existence check into a UNIQUE violation.
64
+ this.database.prepare(`
65
+ INSERT INTO review_session (id, repo_path, target_ref, base_ref, merge_base, input_hash, input_json, conversation_json, created_at)
66
+ VALUES (@id, @repoPath, @targetRef, @baseRef, @mergeBase, @inputHash, @inputJson, @conversationJson, @createdAt)
67
+ ON CONFLICT(input_hash) DO NOTHING
68
+ `).run({ ...session, inputJson: JSON.stringify(input), conversationJson: conversation === undefined ? null : JSON.stringify(conversation) });
69
+ const row = this.database.prepare("SELECT * FROM review_session WHERE input_hash = ?").get(inputHash);
70
+ return deserialize(row);
71
+ }
72
+ getSession(id) {
73
+ const row = this.database.prepare("SELECT * FROM review_session WHERE id = ?").get(id);
74
+ return row === undefined ? undefined : deserialize(row);
75
+ }
76
+ createRevision(sessionId, source, status, document) {
77
+ const revision = { id: randomUUID(), sessionId, source, status, document, createdAt: new Date().toISOString() };
78
+ this.database.prepare(`
79
+ INSERT INTO analysis_revision (id, session_id, status, source, document_json, document_version, created_at)
80
+ VALUES (@id, @sessionId, @status, @source, @documentJson, @documentVersion, @createdAt)
81
+ `).run({ ...revision, documentJson: JSON.stringify(document), documentVersion: ANALYSIS_DOCUMENT_VERSION });
82
+ return revision;
83
+ }
84
+ /** Rows written for another document version, or whose stored document no longer validates, read as absent so the caller re-analyzes instead of rendering a broken artifact. */
85
+ listRevisions(sessionId) {
86
+ const rows = this.database.prepare("SELECT * FROM analysis_revision WHERE session_id = ? ORDER BY created_at DESC").all(sessionId);
87
+ return rows.flatMap((row) => {
88
+ if (row.document_version !== null && row.document_version !== ANALYSIS_DOCUMENT_VERSION)
89
+ return [];
90
+ const document = parseStoredDocument(row.document_json);
91
+ if (document === undefined)
92
+ return [];
93
+ return [{ id: row.id, sessionId: row.session_id, status: row.status, source: row.source, document, createdAt: row.created_at }];
94
+ });
95
+ }
96
+ close() {
97
+ this.database.close();
98
+ }
99
+ }
100
+ function parseStoredDocument(documentJson) {
101
+ try {
102
+ const parsed = AnalysisDocumentSchema.safeParse(JSON.parse(documentJson));
103
+ return parsed.success ? parsed.data : undefined;
104
+ }
105
+ catch {
106
+ return undefined;
107
+ }
108
+ }
109
+ function deserialize(row) {
110
+ return {
111
+ id: row.id,
112
+ repoPath: row.repo_path,
113
+ targetRef: row.target_ref,
114
+ baseRef: row.base_ref,
115
+ mergeBase: row.merge_base,
116
+ inputHash: row.input_hash,
117
+ input: JSON.parse(row.input_json),
118
+ conversation: row.conversation_json === null ? undefined : JSON.parse(row.conversation_json),
119
+ createdAt: row.created_at,
120
+ };
121
+ }
122
+ function hashInput(input, conversation) {
123
+ return createHash("sha256").update(JSON.stringify({ input, conversation })).digest("hex");
124
+ }
125
+ function defaultDatabasePath() {
126
+ if (process.env.NDRSTND_DATA_DIR !== undefined)
127
+ return join(process.env.NDRSTND_DATA_DIR, "ndrstnd.sqlite");
128
+ if (process.platform === "darwin")
129
+ return join(homedir(), "Library", "Application Support", "ndrstnd", "ndrstnd.sqlite");
130
+ if (process.platform === "win32")
131
+ return join(process.env.LOCALAPPDATA ?? homedir(), "ndrstnd", "ndrstnd.sqlite");
132
+ return join(process.env.XDG_DATA_HOME ?? join(homedir(), ".local", "share"), "ndrstnd", "ndrstnd.sqlite");
133
+ }
134
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/server/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ /** The version shipped in package.json, so --version and agent handshakes can never drift from the release. */
2
+ export declare function packageVersion(): Promise<string>;
@@ -0,0 +1,13 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ let cached;
5
+ /** The version shipped in package.json, so --version and agent handshakes can never drift from the release. */
6
+ export async function packageVersion() {
7
+ if (cached === undefined) {
8
+ const manifest = JSON.parse(await readFile(join(dirname(fileURLToPath(import.meta.url)), "../../package.json"), "utf8"));
9
+ cached = manifest.version ?? "unknown";
10
+ }
11
+ return cached;
12
+ }
13
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/server/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,IAAI,MAA0B,CAAC;AAE/B,+GAA+G;AAC/G,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC,CAAyB,CAAC;QACjJ,MAAM,GAAG,QAAQ,CAAC,OAAO,IAAI,SAAS,CAAC;IACzC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,325 @@
1
+ import { z } from "zod";
2
+ export declare const RiskCategorySchema: z.ZodEnum<["formatting", "refactor", "behavior", "performance", "security"]>;
3
+ export declare const AttentionSchema: z.ZodEnum<["low", "contained", "elevated", "high", "critical"]>;
4
+ export declare const ChapterSchema: z.ZodObject<{
5
+ id: z.ZodString;
6
+ title: z.ZodString;
7
+ kind: z.ZodEnum<["feature", "decision", "behavior", "non_functional", "risk", "test", "other"]>;
8
+ synopsis: z.ZodString;
9
+ before: z.ZodOptional<z.ZodString>;
10
+ after: z.ZodOptional<z.ZodString>;
11
+ confidence: z.ZodEnum<["high", "medium", "low"]>;
12
+ attention: z.ZodEnum<["low", "contained", "elevated", "high", "critical"]>;
13
+ riskCategories: z.ZodArray<z.ZodEnum<["formatting", "refactor", "behavior", "performance", "security"]>, "many">;
14
+ evidenceIds: z.ZodArray<z.ZodString, "many">;
15
+ }, "strip", z.ZodTypeAny, {
16
+ id: string;
17
+ title: string;
18
+ kind: "behavior" | "feature" | "decision" | "non_functional" | "risk" | "test" | "other";
19
+ synopsis: string;
20
+ confidence: "low" | "high" | "medium";
21
+ attention: "low" | "contained" | "elevated" | "high" | "critical";
22
+ riskCategories: ("formatting" | "refactor" | "behavior" | "performance" | "security")[];
23
+ evidenceIds: string[];
24
+ before?: string | undefined;
25
+ after?: string | undefined;
26
+ }, {
27
+ id: string;
28
+ title: string;
29
+ kind: "behavior" | "feature" | "decision" | "non_functional" | "risk" | "test" | "other";
30
+ synopsis: string;
31
+ confidence: "low" | "high" | "medium";
32
+ attention: "low" | "contained" | "elevated" | "high" | "critical";
33
+ riskCategories: ("formatting" | "refactor" | "behavior" | "performance" | "security")[];
34
+ evidenceIds: string[];
35
+ before?: string | undefined;
36
+ after?: string | undefined;
37
+ }>;
38
+ export declare const AnalysisStepSchema: z.ZodObject<{
39
+ id: z.ZodString;
40
+ title: z.ZodString;
41
+ goal: z.ZodString;
42
+ youNowHave: z.ZodString;
43
+ deferred: z.ZodArray<z.ZodObject<{
44
+ concern: z.ZodString;
45
+ resolvedByStepId: z.ZodOptional<z.ZodString>;
46
+ }, "strip", z.ZodTypeAny, {
47
+ concern: string;
48
+ resolvedByStepId?: string | undefined;
49
+ }, {
50
+ concern: string;
51
+ resolvedByStepId?: string | undefined;
52
+ }>, "many">;
53
+ dependsOn: z.ZodArray<z.ZodString, "many">;
54
+ forwardRefs: z.ZodRecord<z.ZodString, z.ZodString>;
55
+ advancesChapterIds: z.ZodArray<z.ZodString, "many">;
56
+ evidenceIds: z.ZodArray<z.ZodString, "many">;
57
+ }, "strip", z.ZodTypeAny, {
58
+ id: string;
59
+ title: string;
60
+ evidenceIds: string[];
61
+ goal: string;
62
+ youNowHave: string;
63
+ deferred: {
64
+ concern: string;
65
+ resolvedByStepId?: string | undefined;
66
+ }[];
67
+ dependsOn: string[];
68
+ forwardRefs: Record<string, string>;
69
+ advancesChapterIds: string[];
70
+ }, {
71
+ id: string;
72
+ title: string;
73
+ evidenceIds: string[];
74
+ goal: string;
75
+ youNowHave: string;
76
+ deferred: {
77
+ concern: string;
78
+ resolvedByStepId?: string | undefined;
79
+ }[];
80
+ dependsOn: string[];
81
+ forwardRefs: Record<string, string>;
82
+ advancesChapterIds: string[];
83
+ }>;
84
+ export declare const FocusRangeSchema: z.ZodObject<{
85
+ start: z.ZodNumber;
86
+ end: z.ZodNumber;
87
+ }, "strip", z.ZodTypeAny, {
88
+ end: number;
89
+ start: number;
90
+ }, {
91
+ end: number;
92
+ start: number;
93
+ }>;
94
+ export declare const TestExecutionSchema: z.ZodObject<{
95
+ command: z.ZodString;
96
+ outcome: z.ZodEnum<["passed", "failed", "mixed", "unknown"]>;
97
+ summary: z.ZodString;
98
+ source: z.ZodEnum<["conversation", "repository"]>;
99
+ }, "strip", z.ZodTypeAny, {
100
+ command: string;
101
+ outcome: "unknown" | "passed" | "failed" | "mixed";
102
+ summary: string;
103
+ source: "conversation" | "repository";
104
+ }, {
105
+ command: string;
106
+ outcome: "unknown" | "passed" | "failed" | "mixed";
107
+ summary: string;
108
+ source: "conversation" | "repository";
109
+ }>;
110
+ export declare const AnalysisDocumentSchema: z.ZodObject<{
111
+ summary: z.ZodString;
112
+ chapters: z.ZodArray<z.ZodObject<{
113
+ id: z.ZodString;
114
+ title: z.ZodString;
115
+ kind: z.ZodEnum<["feature", "decision", "behavior", "non_functional", "risk", "test", "other"]>;
116
+ synopsis: z.ZodString;
117
+ before: z.ZodOptional<z.ZodString>;
118
+ after: z.ZodOptional<z.ZodString>;
119
+ confidence: z.ZodEnum<["high", "medium", "low"]>;
120
+ attention: z.ZodEnum<["low", "contained", "elevated", "high", "critical"]>;
121
+ riskCategories: z.ZodArray<z.ZodEnum<["formatting", "refactor", "behavior", "performance", "security"]>, "many">;
122
+ evidenceIds: z.ZodArray<z.ZodString, "many">;
123
+ }, "strip", z.ZodTypeAny, {
124
+ id: string;
125
+ title: string;
126
+ kind: "behavior" | "feature" | "decision" | "non_functional" | "risk" | "test" | "other";
127
+ synopsis: string;
128
+ confidence: "low" | "high" | "medium";
129
+ attention: "low" | "contained" | "elevated" | "high" | "critical";
130
+ riskCategories: ("formatting" | "refactor" | "behavior" | "performance" | "security")[];
131
+ evidenceIds: string[];
132
+ before?: string | undefined;
133
+ after?: string | undefined;
134
+ }, {
135
+ id: string;
136
+ title: string;
137
+ kind: "behavior" | "feature" | "decision" | "non_functional" | "risk" | "test" | "other";
138
+ synopsis: string;
139
+ confidence: "low" | "high" | "medium";
140
+ attention: "low" | "contained" | "elevated" | "high" | "critical";
141
+ riskCategories: ("formatting" | "refactor" | "behavior" | "performance" | "security")[];
142
+ evidenceIds: string[];
143
+ before?: string | undefined;
144
+ after?: string | undefined;
145
+ }>, "many">;
146
+ steps: z.ZodArray<z.ZodObject<{
147
+ id: z.ZodString;
148
+ title: z.ZodString;
149
+ goal: z.ZodString;
150
+ youNowHave: z.ZodString;
151
+ deferred: z.ZodArray<z.ZodObject<{
152
+ concern: z.ZodString;
153
+ resolvedByStepId: z.ZodOptional<z.ZodString>;
154
+ }, "strip", z.ZodTypeAny, {
155
+ concern: string;
156
+ resolvedByStepId?: string | undefined;
157
+ }, {
158
+ concern: string;
159
+ resolvedByStepId?: string | undefined;
160
+ }>, "many">;
161
+ dependsOn: z.ZodArray<z.ZodString, "many">;
162
+ forwardRefs: z.ZodRecord<z.ZodString, z.ZodString>;
163
+ advancesChapterIds: z.ZodArray<z.ZodString, "many">;
164
+ evidenceIds: z.ZodArray<z.ZodString, "many">;
165
+ }, "strip", z.ZodTypeAny, {
166
+ id: string;
167
+ title: string;
168
+ evidenceIds: string[];
169
+ goal: string;
170
+ youNowHave: string;
171
+ deferred: {
172
+ concern: string;
173
+ resolvedByStepId?: string | undefined;
174
+ }[];
175
+ dependsOn: string[];
176
+ forwardRefs: Record<string, string>;
177
+ advancesChapterIds: string[];
178
+ }, {
179
+ id: string;
180
+ title: string;
181
+ evidenceIds: string[];
182
+ goal: string;
183
+ youNowHave: string;
184
+ deferred: {
185
+ concern: string;
186
+ resolvedByStepId?: string | undefined;
187
+ }[];
188
+ dependsOn: string[];
189
+ forwardRefs: Record<string, string>;
190
+ advancesChapterIds: string[];
191
+ }>, "many">;
192
+ omittedGroups: z.ZodArray<z.ZodObject<{
193
+ title: z.ZodString;
194
+ reason: z.ZodString;
195
+ evidenceIds: z.ZodArray<z.ZodString, "many">;
196
+ }, "strip", z.ZodTypeAny, {
197
+ reason: string;
198
+ title: string;
199
+ evidenceIds: string[];
200
+ }, {
201
+ reason: string;
202
+ title: string;
203
+ evidenceIds: string[];
204
+ }>, "many">;
205
+ unclassifiedEvidenceIds: z.ZodArray<z.ZodString, "many">;
206
+ /** Reviewer-critical new-file line ranges per evidence ID; they drive the focused excerpts at the Evidence zoom. */
207
+ focus: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodObject<{
208
+ start: z.ZodNumber;
209
+ end: z.ZodNumber;
210
+ }, "strip", z.ZodTypeAny, {
211
+ end: number;
212
+ start: number;
213
+ }, {
214
+ end: number;
215
+ start: number;
216
+ }>, "many">>>;
217
+ /** Test or build runs actually observed in the conversation or repository; never inferred. */
218
+ testExecution: z.ZodOptional<z.ZodArray<z.ZodObject<{
219
+ command: z.ZodString;
220
+ outcome: z.ZodEnum<["passed", "failed", "mixed", "unknown"]>;
221
+ summary: z.ZodString;
222
+ source: z.ZodEnum<["conversation", "repository"]>;
223
+ }, "strip", z.ZodTypeAny, {
224
+ command: string;
225
+ outcome: "unknown" | "passed" | "failed" | "mixed";
226
+ summary: string;
227
+ source: "conversation" | "repository";
228
+ }, {
229
+ command: string;
230
+ outcome: "unknown" | "passed" | "failed" | "mixed";
231
+ summary: string;
232
+ source: "conversation" | "repository";
233
+ }>, "many">>;
234
+ }, "strip", z.ZodTypeAny, {
235
+ summary: string;
236
+ chapters: {
237
+ id: string;
238
+ title: string;
239
+ kind: "behavior" | "feature" | "decision" | "non_functional" | "risk" | "test" | "other";
240
+ synopsis: string;
241
+ confidence: "low" | "high" | "medium";
242
+ attention: "low" | "contained" | "elevated" | "high" | "critical";
243
+ riskCategories: ("formatting" | "refactor" | "behavior" | "performance" | "security")[];
244
+ evidenceIds: string[];
245
+ before?: string | undefined;
246
+ after?: string | undefined;
247
+ }[];
248
+ steps: {
249
+ id: string;
250
+ title: string;
251
+ evidenceIds: string[];
252
+ goal: string;
253
+ youNowHave: string;
254
+ deferred: {
255
+ concern: string;
256
+ resolvedByStepId?: string | undefined;
257
+ }[];
258
+ dependsOn: string[];
259
+ forwardRefs: Record<string, string>;
260
+ advancesChapterIds: string[];
261
+ }[];
262
+ omittedGroups: {
263
+ reason: string;
264
+ title: string;
265
+ evidenceIds: string[];
266
+ }[];
267
+ unclassifiedEvidenceIds: string[];
268
+ focus?: Record<string, {
269
+ end: number;
270
+ start: number;
271
+ }[]> | undefined;
272
+ testExecution?: {
273
+ command: string;
274
+ outcome: "unknown" | "passed" | "failed" | "mixed";
275
+ summary: string;
276
+ source: "conversation" | "repository";
277
+ }[] | undefined;
278
+ }, {
279
+ summary: string;
280
+ chapters: {
281
+ id: string;
282
+ title: string;
283
+ kind: "behavior" | "feature" | "decision" | "non_functional" | "risk" | "test" | "other";
284
+ synopsis: string;
285
+ confidence: "low" | "high" | "medium";
286
+ attention: "low" | "contained" | "elevated" | "high" | "critical";
287
+ riskCategories: ("formatting" | "refactor" | "behavior" | "performance" | "security")[];
288
+ evidenceIds: string[];
289
+ before?: string | undefined;
290
+ after?: string | undefined;
291
+ }[];
292
+ steps: {
293
+ id: string;
294
+ title: string;
295
+ evidenceIds: string[];
296
+ goal: string;
297
+ youNowHave: string;
298
+ deferred: {
299
+ concern: string;
300
+ resolvedByStepId?: string | undefined;
301
+ }[];
302
+ dependsOn: string[];
303
+ forwardRefs: Record<string, string>;
304
+ advancesChapterIds: string[];
305
+ }[];
306
+ omittedGroups: {
307
+ reason: string;
308
+ title: string;
309
+ evidenceIds: string[];
310
+ }[];
311
+ unclassifiedEvidenceIds: string[];
312
+ focus?: Record<string, {
313
+ end: number;
314
+ start: number;
315
+ }[]> | undefined;
316
+ testExecution?: {
317
+ command: string;
318
+ outcome: "unknown" | "passed" | "failed" | "mixed";
319
+ summary: string;
320
+ source: "conversation" | "repository";
321
+ }[] | undefined;
322
+ }>;
323
+ export type AnalysisDocument = z.infer<typeof AnalysisDocumentSchema>;
324
+ /** Bump on any incompatible change to AnalysisDocument so cached revisions from older versions are re-analyzed instead of rendered broken. */
325
+ export declare const ANALYSIS_DOCUMENT_VERSION = 1;