@alevental/cccp 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 (127) hide show
  1. package/.claude/skills/cccp-pipeline/SKILL.md +562 -0
  2. package/.claude/skills/cccp-run/SKILL.md +111 -0
  3. package/README.md +280 -0
  4. package/dist/activity-bus.d.ts +9 -0
  5. package/dist/activity-bus.js +10 -0
  6. package/dist/activity-bus.js.map +1 -0
  7. package/dist/agent-resolver.d.ts +29 -0
  8. package/dist/agent-resolver.js +122 -0
  9. package/dist/agent-resolver.js.map +1 -0
  10. package/dist/agent.d.ts +39 -0
  11. package/dist/agent.js +117 -0
  12. package/dist/agent.js.map +1 -0
  13. package/dist/autoresearch.d.ts +11 -0
  14. package/dist/autoresearch.js +295 -0
  15. package/dist/autoresearch.js.map +1 -0
  16. package/dist/cli.d.ts +2 -0
  17. package/dist/cli.js +157 -0
  18. package/dist/cli.js.map +1 -0
  19. package/dist/config.d.ts +126 -0
  20. package/dist/config.js +76 -0
  21. package/dist/config.js.map +1 -0
  22. package/dist/context.d.ts +24 -0
  23. package/dist/context.js +82 -0
  24. package/dist/context.js.map +1 -0
  25. package/dist/contract.d.ts +26 -0
  26. package/dist/contract.js +65 -0
  27. package/dist/contract.js.map +1 -0
  28. package/dist/db.d.ts +70 -0
  29. package/dist/db.js +358 -0
  30. package/dist/db.js.map +1 -0
  31. package/dist/dispatcher.d.ts +9 -0
  32. package/dist/dispatcher.js +7 -0
  33. package/dist/dispatcher.js.map +1 -0
  34. package/dist/errors.d.ts +16 -0
  35. package/dist/errors.js +30 -0
  36. package/dist/errors.js.map +1 -0
  37. package/dist/evaluator.d.ts +23 -0
  38. package/dist/evaluator.js +49 -0
  39. package/dist/evaluator.js.map +1 -0
  40. package/dist/gate/auto-approve.d.ts +9 -0
  41. package/dist/gate/auto-approve.js +11 -0
  42. package/dist/gate/auto-approve.js.map +1 -0
  43. package/dist/gate/gate-strategy.d.ts +22 -0
  44. package/dist/gate/gate-strategy.js +2 -0
  45. package/dist/gate/gate-strategy.js.map +1 -0
  46. package/dist/gate/gate-watcher.d.ts +15 -0
  47. package/dist/gate/gate-watcher.js +64 -0
  48. package/dist/gate/gate-watcher.js.map +1 -0
  49. package/dist/logger.d.ts +24 -0
  50. package/dist/logger.js +22 -0
  51. package/dist/logger.js.map +1 -0
  52. package/dist/mcp/gate-notifier.d.ts +26 -0
  53. package/dist/mcp/gate-notifier.js +161 -0
  54. package/dist/mcp/gate-notifier.js.map +1 -0
  55. package/dist/mcp/mcp-config.d.ts +25 -0
  56. package/dist/mcp/mcp-config.js +80 -0
  57. package/dist/mcp/mcp-config.js.map +1 -0
  58. package/dist/mcp/mcp-server.d.ts +1 -0
  59. package/dist/mcp/mcp-server.js +262 -0
  60. package/dist/mcp/mcp-server.js.map +1 -0
  61. package/dist/pge.d.ts +12 -0
  62. package/dist/pge.js +361 -0
  63. package/dist/pge.js.map +1 -0
  64. package/dist/pipeline.d.ts +6 -0
  65. package/dist/pipeline.js +120 -0
  66. package/dist/pipeline.js.map +1 -0
  67. package/dist/prompt.d.ts +67 -0
  68. package/dist/prompt.js +121 -0
  69. package/dist/prompt.js.map +1 -0
  70. package/dist/runner.d.ts +11 -0
  71. package/dist/runner.js +494 -0
  72. package/dist/runner.js.map +1 -0
  73. package/dist/scaffold/index.d.ts +14 -0
  74. package/dist/scaffold/index.js +260 -0
  75. package/dist/scaffold/index.js.map +1 -0
  76. package/dist/scaffold/templates.d.ts +47 -0
  77. package/dist/scaffold/templates.js +2177 -0
  78. package/dist/scaffold/templates.js.map +1 -0
  79. package/dist/stage-helpers.d.ts +7 -0
  80. package/dist/stage-helpers.js +27 -0
  81. package/dist/stage-helpers.js.map +1 -0
  82. package/dist/state.d.ts +43 -0
  83. package/dist/state.js +177 -0
  84. package/dist/state.js.map +1 -0
  85. package/dist/stream/stream-tail.d.ts +17 -0
  86. package/dist/stream/stream-tail.js +95 -0
  87. package/dist/stream/stream-tail.js.map +1 -0
  88. package/dist/stream/stream.d.ts +142 -0
  89. package/dist/stream/stream.js +251 -0
  90. package/dist/stream/stream.js.map +1 -0
  91. package/dist/temp-tracker.d.ts +6 -0
  92. package/dist/temp-tracker.js +24 -0
  93. package/dist/temp-tracker.js.map +1 -0
  94. package/dist/tui/cmux.d.ts +22 -0
  95. package/dist/tui/cmux.js +82 -0
  96. package/dist/tui/cmux.js.map +1 -0
  97. package/dist/tui/components.d.ts +21 -0
  98. package/dist/tui/components.js +108 -0
  99. package/dist/tui/components.js.map +1 -0
  100. package/dist/tui/dashboard.d.ts +6 -0
  101. package/dist/tui/dashboard.js +125 -0
  102. package/dist/tui/dashboard.js.map +1 -0
  103. package/dist/tui/detail-log.d.ts +10 -0
  104. package/dist/tui/detail-log.js +171 -0
  105. package/dist/tui/detail-log.js.map +1 -0
  106. package/dist/types.d.ts +273 -0
  107. package/dist/types.js +2 -0
  108. package/dist/types.js.map +1 -0
  109. package/examples/agents/diff-evaluator.md +57 -0
  110. package/examples/agents/prompt-tuner.md +30 -0
  111. package/examples/agents/summarizer.md +14 -0
  112. package/examples/autoresearch-artifacts/expected-output.md +17 -0
  113. package/examples/autoresearch-artifacts/prompt.md +35 -0
  114. package/examples/autoresearch-artifacts/source-material.md +28 -0
  115. package/examples/business-case.yaml +41 -0
  116. package/examples/cccp.yaml +48 -0
  117. package/examples/content-calendar.yaml +59 -0
  118. package/examples/customer-feedback-loop.yaml +44 -0
  119. package/examples/design-sprint.yaml +54 -0
  120. package/examples/feature-development.yaml +96 -0
  121. package/examples/growth-experiment.yaml +49 -0
  122. package/examples/incident-runbook.yaml +43 -0
  123. package/examples/product-launch.yaml +85 -0
  124. package/examples/prompt-tuning.yaml +25 -0
  125. package/examples/quarterly-planning.yaml +51 -0
  126. package/examples/sprint-cycle.yaml +67 -0
  127. package/package.json +47 -0
package/dist/config.js ADDED
@@ -0,0 +1,76 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { resolve, dirname } from "node:path";
3
+ import { parse as parseYaml } from "yaml";
4
+ import { z } from "zod";
5
+ // ---------------------------------------------------------------------------
6
+ // Zod schema for cccp.yaml
7
+ // ---------------------------------------------------------------------------
8
+ const McpServerSchema = z.object({
9
+ command: z.string(),
10
+ args: z.array(z.string()).optional(),
11
+ env: z.record(z.string()).optional(),
12
+ });
13
+ const McpProfileSchema = z.object({
14
+ extends: z.string().optional(),
15
+ servers: z.record(McpServerSchema).optional(),
16
+ });
17
+ const ProjectConfigSchema = z.object({
18
+ /** Ordered list of directories to search for agent definitions. */
19
+ agent_paths: z.array(z.string()).optional(),
20
+ /** Named MCP server profiles. */
21
+ mcp_profiles: z.record(McpProfileSchema).optional(),
22
+ /** Artifact output directory pattern (supports {project}, {pipeline_name}). */
23
+ artifact_dir: z.string().optional(),
24
+ /** Default MCP profile applied when a stage doesn't specify one. */
25
+ default_mcp_profile: z.string().optional(),
26
+ /** Claude config directory (default: inherits CLAUDE_CONFIG_DIR or ~/.claude). */
27
+ claude_config_dir: z.string().optional(),
28
+ /** Permission mode for agent subprocesses (default: bypassPermissions). */
29
+ permission_mode: z.enum(["default", "acceptEdits", "bypassPermissions", "auto"]).optional(),
30
+ });
31
+ // ---------------------------------------------------------------------------
32
+ // Public API
33
+ // ---------------------------------------------------------------------------
34
+ /**
35
+ * Load a cccp.yaml project config from the given directory.
36
+ * Returns an empty config (all defaults) if the file doesn't exist.
37
+ *
38
+ * Paths in `agent_paths` are resolved relative to the config file's directory.
39
+ */
40
+ export async function loadProjectConfig(projectDir) {
41
+ const configPath = resolve(projectDir, "cccp.yaml");
42
+ let raw;
43
+ try {
44
+ raw = await readFile(configPath, "utf-8");
45
+ }
46
+ catch {
47
+ // No config file — return empty defaults.
48
+ return {};
49
+ }
50
+ let parsed;
51
+ try {
52
+ parsed = parseYaml(raw);
53
+ }
54
+ catch (err) {
55
+ throw new Error(`Invalid YAML in config file: ${configPath}`, {
56
+ cause: err,
57
+ });
58
+ }
59
+ if (parsed == null) {
60
+ return {};
61
+ }
62
+ const result = ProjectConfigSchema.safeParse(parsed);
63
+ if (!result.success) {
64
+ const issues = result.error.issues
65
+ .map((i) => ` - ${i.path.join(".")}: ${i.message}`)
66
+ .join("\n");
67
+ throw new Error(`Config validation failed for ${configPath}:\n${issues}`);
68
+ }
69
+ const config = result.data;
70
+ // Resolve agent_paths relative to config file location.
71
+ if (config.agent_paths) {
72
+ config.agent_paths = config.agent_paths.map((p) => resolve(dirname(configPath), p));
73
+ }
74
+ return config;
75
+ }
76
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { ProjectConfig } from "./config.js";
2
+ import type { Pipeline, RunContext } from "./types.js";
3
+ export declare function buildAgentSearchPaths(pipelineFile: string, projectDir: string, projectConfig: ProjectConfig): string[];
4
+ export declare function resolveArtifactDir(opts: {
5
+ artifactDir?: string;
6
+ projectDir: string;
7
+ projectConfig: ProjectConfig;
8
+ project: string;
9
+ pipelineName: string;
10
+ }): string;
11
+ export declare function parseCLIVars(vars?: string[]): Record<string, string>;
12
+ export interface BuildRunContextOptions {
13
+ project: string;
14
+ projectDir: string;
15
+ pipelineFile: string;
16
+ pipeline: Pipeline;
17
+ artifactDir: string;
18
+ projectConfig: ProjectConfig;
19
+ dryRun?: boolean;
20
+ headless?: boolean;
21
+ showTui?: boolean;
22
+ cliVars?: Record<string, string>;
23
+ }
24
+ export declare function buildRunContext(opts: BuildRunContextOptions): RunContext;
@@ -0,0 +1,82 @@
1
+ import { resolve, dirname } from "node:path";
2
+ import { interpolate } from "./prompt.js";
3
+ import { AutoApproveStrategy } from "./gate/auto-approve.js";
4
+ import { ConsoleLogger, QuietLogger } from "./logger.js";
5
+ import { TempFileTracker } from "./temp-tracker.js";
6
+ // ---------------------------------------------------------------------------
7
+ // Agent search paths — 4-source priority order
8
+ // ---------------------------------------------------------------------------
9
+ export function buildAgentSearchPaths(pipelineFile, projectDir, projectConfig) {
10
+ const paths = [];
11
+ paths.push(resolve(dirname(pipelineFile), "agents"));
12
+ paths.push(resolve(projectDir, ".claude", "agents"));
13
+ paths.push(resolve(projectDir, "agents"));
14
+ if (projectConfig.agent_paths) {
15
+ paths.push(...projectConfig.agent_paths);
16
+ }
17
+ return paths;
18
+ }
19
+ // ---------------------------------------------------------------------------
20
+ // Artifact directory resolution — CLI flag > cccp.yaml > default pattern
21
+ // ---------------------------------------------------------------------------
22
+ export function resolveArtifactDir(opts) {
23
+ if (opts.artifactDir)
24
+ return resolve(opts.artifactDir);
25
+ if (opts.projectConfig.artifact_dir) {
26
+ return resolve(opts.projectDir, interpolate(opts.projectConfig.artifact_dir, {
27
+ project: opts.project,
28
+ pipeline_name: opts.pipelineName,
29
+ }));
30
+ }
31
+ return resolve(opts.projectDir, `docs/projects/${opts.project}/${opts.pipelineName}`);
32
+ }
33
+ // ---------------------------------------------------------------------------
34
+ // CLI variable parsing
35
+ // ---------------------------------------------------------------------------
36
+ export function parseCLIVars(vars) {
37
+ const result = {};
38
+ if (!vars)
39
+ return result;
40
+ for (const v of vars) {
41
+ const eq = v.indexOf("=");
42
+ if (eq === -1) {
43
+ throw new Error(`Invalid variable format: ${v} (expected key=value)`);
44
+ }
45
+ result[v.slice(0, eq)] = v.slice(eq + 1);
46
+ }
47
+ return result;
48
+ }
49
+ export function buildRunContext(opts) {
50
+ const agentSearchPaths = buildAgentSearchPaths(opts.pipelineFile, opts.projectDir, opts.projectConfig);
51
+ const variables = {
52
+ project: opts.project,
53
+ project_dir: opts.projectDir,
54
+ artifact_dir: opts.artifactDir,
55
+ pipeline_name: opts.pipeline.name,
56
+ ...(opts.pipeline.variables ?? {}),
57
+ ...(opts.cliVars ?? {}),
58
+ };
59
+ // Gate strategy: headless → auto-approve immediately.
60
+ // Interactive → FilesystemGateStrategy, but it needs a runId which doesn't
61
+ // exist yet. The runner creates it after state initialization.
62
+ const gateStrategy = opts.headless
63
+ ? new AutoApproveStrategy()
64
+ : undefined;
65
+ return {
66
+ project: opts.project,
67
+ projectDir: opts.projectDir,
68
+ artifactDir: opts.artifactDir,
69
+ pipelineFile: opts.pipelineFile,
70
+ pipeline: opts.pipeline,
71
+ dryRun: opts.dryRun ?? false,
72
+ variables,
73
+ agentSearchPaths,
74
+ projectConfig: opts.projectConfig,
75
+ gateStrategy,
76
+ headless: opts.headless,
77
+ quiet: opts.showTui,
78
+ logger: opts.showTui ? new QuietLogger() : new ConsoleLogger(),
79
+ tempTracker: new TempFileTracker(),
80
+ };
81
+ }
82
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { ContractCriterion } from "./types.js";
2
+ export interface ContractOptions {
3
+ /** Sub-stage / stage name. */
4
+ stageName: string;
5
+ /** Path where the deliverable will be written. */
6
+ deliverable: string;
7
+ /** Success criteria from the pipeline YAML. */
8
+ criteria: ContractCriterion[];
9
+ /** Maximum PGE iterations. */
10
+ maxIterations: number;
11
+ /** Optional path to a custom contract template. */
12
+ templatePath?: string;
13
+ }
14
+ /**
15
+ * Generate a contract markdown file from criteria.
16
+ *
17
+ * If `templatePath` is provided, reads and uses that template (must contain
18
+ * `{stage_name}`, `{deliverable}`, `{criteria_table}`, `{max_iterations}`
19
+ * placeholders). Otherwise uses the built-in default.
20
+ */
21
+ export declare function generateContract(opts: ContractOptions): Promise<string>;
22
+ /**
23
+ * Generate and write a contract file to disk.
24
+ * Creates parent directories as needed.
25
+ */
26
+ export declare function writeContract(contractPath: string, opts: ContractOptions): Promise<void>;
@@ -0,0 +1,65 @@
1
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
2
+ import { dirname } from "node:path";
3
+ /**
4
+ * Generate a contract markdown file from criteria.
5
+ *
6
+ * If `templatePath` is provided, reads and uses that template (must contain
7
+ * `{stage_name}`, `{deliverable}`, `{criteria_table}`, `{max_iterations}`
8
+ * placeholders). Otherwise uses the built-in default.
9
+ */
10
+ export async function generateContract(opts) {
11
+ if (opts.templatePath) {
12
+ const template = await readFile(opts.templatePath, "utf-8");
13
+ return applyTemplate(template, opts);
14
+ }
15
+ return buildDefaultContract(opts);
16
+ }
17
+ /**
18
+ * Generate and write a contract file to disk.
19
+ * Creates parent directories as needed.
20
+ */
21
+ export async function writeContract(contractPath, opts) {
22
+ const content = await generateContract(opts);
23
+ await mkdir(dirname(contractPath), { recursive: true });
24
+ await writeFile(contractPath, content, "utf-8");
25
+ }
26
+ // ---------------------------------------------------------------------------
27
+ // Default contract format (matches squatlypowers contract template)
28
+ // ---------------------------------------------------------------------------
29
+ function buildDefaultContract(opts) {
30
+ const criteriaRows = opts.criteria
31
+ .map((c, i) => `| ${i + 1} | ${c.name} | ${c.description} |`)
32
+ .join("\n");
33
+ return `## Contract: ${opts.stageName}
34
+
35
+ ### Deliverable
36
+
37
+ ${opts.deliverable}
38
+
39
+ ### Success Criteria
40
+
41
+ | # | Criterion | Description |
42
+ |---|-----------|-------------|
43
+ ${criteriaRows}
44
+
45
+ ### Pass Rule
46
+
47
+ ALL criteria must pass. Any single failure = overall FAIL.
48
+
49
+ ### Max Iterations: ${opts.maxIterations}
50
+ `;
51
+ }
52
+ // ---------------------------------------------------------------------------
53
+ // Custom template support
54
+ // ---------------------------------------------------------------------------
55
+ function applyTemplate(template, opts) {
56
+ const criteriaRows = opts.criteria
57
+ .map((c, i) => `| ${i + 1} | ${c.name} | ${c.description} |`)
58
+ .join("\n");
59
+ return template
60
+ .replace(/\{stage_name\}/g, opts.stageName)
61
+ .replace(/\{deliverable\}/g, opts.deliverable)
62
+ .replace(/\{criteria_table\}/g, criteriaRows)
63
+ .replace(/\{max_iterations\}/g, String(opts.maxIterations));
64
+ }
65
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoBpC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAqB;IAErB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC5D,OAAO,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,YAAoB,EACpB,IAAqB;IAErB,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,MAAM,SAAS,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC;AAED,8EAA8E;AAC9E,oEAAoE;AACpE,8EAA8E;AAE9E,SAAS,oBAAoB,CAAC,IAAqB;IACjD,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ;SAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,WAAW,IAAI,CAAC;SAC5D,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,gBAAgB,IAAI,CAAC,SAAS;;;;EAIrC,IAAI,CAAC,WAAW;;;;;;EAMhB,YAAY;;;;;;sBAMQ,IAAI,CAAC,aAAa;CACvC,CAAC;AACF,CAAC;AAED,8EAA8E;AAC9E,0BAA0B;AAC1B,8EAA8E;AAE9E,SAAS,aAAa,CAAC,QAAgB,EAAE,IAAqB;IAC5D,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ;SAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,WAAW,IAAI,CAAC;SAC5D,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,QAAQ;SACZ,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC;SAC1C,OAAO,CAAC,kBAAkB,EAAE,IAAI,CAAC,WAAW,CAAC;SAC7C,OAAO,CAAC,qBAAqB,EAAE,YAAY,CAAC;SAC5C,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;AAChE,CAAC"}
package/dist/db.d.ts ADDED
@@ -0,0 +1,70 @@
1
+ import type { PipelineState, StateEvent, DiscoveredRun } from "./types.js";
2
+ /** Filter criteria for querying pipeline runs. */
3
+ export interface RunFilter {
4
+ project?: string;
5
+ pipeline?: string;
6
+ status?: string;
7
+ artifactDir?: string;
8
+ }
9
+ export declare function dbPath(projectDir: string): string;
10
+ export declare class CccpDatabase {
11
+ private db;
12
+ private filePath;
13
+ private constructor();
14
+ /**
15
+ * Open or create a database. If the file exists, load it. Otherwise create
16
+ * a new empty DB with the schema.
17
+ */
18
+ static open(projectDir: string): Promise<CccpDatabase>;
19
+ /**
20
+ * Open a read-only copy of the database (for standalone dashboard / MCP server).
21
+ * Re-reads the file from disk each time — safe for cross-process access.
22
+ */
23
+ static openReadOnly(projectDir: string): Promise<CccpDatabase>;
24
+ private migrate;
25
+ private pragma;
26
+ insertRun(state: PipelineState, artifactDir: string): void;
27
+ updateRun(state: PipelineState, artifactDir: string): void;
28
+ /**
29
+ * Insert or update — tries update first, inserts if no row exists.
30
+ */
31
+ upsertRun(state: PipelineState, artifactDir: string): void;
32
+ getRun(runId: string): PipelineState | null;
33
+ /**
34
+ * @deprecated Use getRun(runId) instead.
35
+ */
36
+ getRunByArtifactDir(artifactDir: string): PipelineState | null;
37
+ /**
38
+ * Find a run by ID prefix. Returns null if zero or multiple matches.
39
+ */
40
+ getRunByIdPrefix(prefix: string): PipelineState | null;
41
+ listRuns(): DiscoveredRun[];
42
+ /**
43
+ * Find runs matching optional filters. All filters are AND-combined.
44
+ * Results sorted running-first, then by start time descending.
45
+ */
46
+ findRuns(filter?: RunFilter): DiscoveredRun[];
47
+ private rowToState;
48
+ appendEvent(runId: string, eventType: string, stageName?: string, data?: unknown): void;
49
+ getEvents(runId: string, sinceId?: number): StateEvent[];
50
+ setCheckpoint(runId: string, stageName: string, key: string, value: string): void;
51
+ getCheckpoint(runId: string, stageName: string, key: string): string | null;
52
+ /**
53
+ * Atomically write the database to disk (write to .tmp then rename).
54
+ */
55
+ flush(): void;
56
+ /**
57
+ * Reload the database from disk (for read-only consumers in separate processes).
58
+ */
59
+ reload(): void;
60
+ close(): void;
61
+ }
62
+ /**
63
+ * Get or create a CccpDatabase for the given project directory.
64
+ * Caches the instance for reuse within the same process.
65
+ */
66
+ export declare function openDatabase(projectDir: string): Promise<CccpDatabase>;
67
+ /**
68
+ * Close and remove a cached database instance.
69
+ */
70
+ export declare function closeDatabase(projectDir: string): void;