@ccdd/project 2.0.1

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 (163) hide show
  1. package/README.md +25 -0
  2. package/dist/monitor-ui/assets/GraphView-CYMJ1Nb7.css +1 -0
  3. package/dist/monitor-ui/assets/GraphView-UjtW4QRC.js +27 -0
  4. package/dist/monitor-ui/assets/ValidationView-CC1FvqUl.js +1 -0
  5. package/dist/monitor-ui/assets/ValidationView-DWl4b8Ug.css +1 -0
  6. package/dist/monitor-ui/assets/_plugin-vue_export-helper-BDNMzG2s.js +1 -0
  7. package/dist/monitor-ui/assets/elk-api-yRi2AOS6.js +1 -0
  8. package/dist/monitor-ui/assets/elk.bundled-CtLobQTy.js +24 -0
  9. package/dist/monitor-ui/assets/graph-layout-worker-CgfWoa9t.js +22 -0
  10. package/dist/monitor-ui/assets/index-CUzg-dht.css +1 -0
  11. package/dist/monitor-ui/assets/index-Cpm0fC0p.js +8 -0
  12. package/dist/monitor-ui/index.html +15 -0
  13. package/dist/scripts/prepare-demo.d.ts +26 -0
  14. package/dist/scripts/prepare-demo.js +121 -0
  15. package/dist/scripts/prepare-demo.js.map +1 -0
  16. package/dist/src/artifacts/groups.d.ts +9 -0
  17. package/dist/src/artifacts/groups.js +77 -0
  18. package/dist/src/artifacts/groups.js.map +1 -0
  19. package/dist/src/artifacts/human.d.ts +38 -0
  20. package/dist/src/artifacts/human.js +156 -0
  21. package/dist/src/artifacts/human.js.map +1 -0
  22. package/dist/src/artifacts/index.d.ts +149 -0
  23. package/dist/src/artifacts/index.js +354 -0
  24. package/dist/src/artifacts/index.js.map +1 -0
  25. package/dist/src/artifacts/instruction.d.ts +23 -0
  26. package/dist/src/artifacts/instruction.js +94 -0
  27. package/dist/src/artifacts/instruction.js.map +1 -0
  28. package/dist/src/artifacts/mcp-server.d.ts +6 -0
  29. package/dist/src/artifacts/mcp-server.js +96 -0
  30. package/dist/src/artifacts/mcp-server.js.map +1 -0
  31. package/dist/src/artifacts/tool-check.d.ts +40 -0
  32. package/dist/src/artifacts/tool-check.js +113 -0
  33. package/dist/src/artifacts/tool-check.js.map +1 -0
  34. package/dist/src/artifacts/types.d.ts +43 -0
  35. package/dist/src/artifacts/types.js +97 -0
  36. package/dist/src/artifacts/types.js.map +1 -0
  37. package/dist/src/broker/config.d.ts +11 -0
  38. package/dist/src/broker/config.js +141 -0
  39. package/dist/src/broker/config.js.map +1 -0
  40. package/dist/src/broker/graph.d.ts +69 -0
  41. package/dist/src/broker/graph.js +94 -0
  42. package/dist/src/broker/graph.js.map +1 -0
  43. package/dist/src/broker/index.d.ts +170 -0
  44. package/dist/src/broker/index.js +931 -0
  45. package/dist/src/broker/index.js.map +1 -0
  46. package/dist/src/cli.d.ts +24 -0
  47. package/dist/src/cli.js +340 -0
  48. package/dist/src/cli.js.map +1 -0
  49. package/dist/src/contracts.d.ts +116 -0
  50. package/dist/src/contracts.js +2 -0
  51. package/dist/src/contracts.js.map +1 -0
  52. package/dist/src/definitions.d.ts +53 -0
  53. package/dist/src/definitions.js +2 -0
  54. package/dist/src/definitions.js.map +1 -0
  55. package/dist/src/doctor/index.d.ts +41 -0
  56. package/dist/src/doctor/index.js +189 -0
  57. package/dist/src/doctor/index.js.map +1 -0
  58. package/dist/src/executors/auth.d.ts +16 -0
  59. package/dist/src/executors/auth.js +150 -0
  60. package/dist/src/executors/auth.js.map +1 -0
  61. package/dist/src/executors/errors.d.ts +6 -0
  62. package/dist/src/executors/errors.js +10 -0
  63. package/dist/src/executors/errors.js.map +1 -0
  64. package/dist/src/executors/index.d.ts +20 -0
  65. package/dist/src/executors/index.js +262 -0
  66. package/dist/src/executors/index.js.map +1 -0
  67. package/dist/src/executors/pi.d.ts +32 -0
  68. package/dist/src/executors/pi.js +190 -0
  69. package/dist/src/executors/pi.js.map +1 -0
  70. package/dist/src/executors/process.d.ts +22 -0
  71. package/dist/src/executors/process.js +70 -0
  72. package/dist/src/executors/process.js.map +1 -0
  73. package/dist/src/local.d.ts +13 -0
  74. package/dist/src/local.js +20 -0
  75. package/dist/src/local.js.map +1 -0
  76. package/dist/src/monitor/actions.d.ts +12 -0
  77. package/dist/src/monitor/actions.js +74 -0
  78. package/dist/src/monitor/actions.js.map +1 -0
  79. package/dist/src/monitor/server.d.ts +8 -0
  80. package/dist/src/monitor/server.js +493 -0
  81. package/dist/src/monitor/server.js.map +1 -0
  82. package/dist/src/monitor/store.d.ts +22 -0
  83. package/dist/src/monitor/store.js +517 -0
  84. package/dist/src/monitor/store.js.map +1 -0
  85. package/dist/src/monitor/types.d.ts +143 -0
  86. package/dist/src/monitor/types.js +2 -0
  87. package/dist/src/monitor/types.js.map +1 -0
  88. package/dist/src/monitor/ui/api.d.ts +11 -0
  89. package/dist/src/monitor/ui/api.js +29 -0
  90. package/dist/src/monitor/ui/api.js.map +1 -0
  91. package/dist/src/monitor/ui/critic-presentation.d.ts +11 -0
  92. package/dist/src/monitor/ui/critic-presentation.js +60 -0
  93. package/dist/src/monitor/ui/critic-presentation.js.map +1 -0
  94. package/dist/src/monitor/ui/format.d.ts +9 -0
  95. package/dist/src/monitor/ui/format.js +22 -0
  96. package/dist/src/monitor/ui/format.js.map +1 -0
  97. package/dist/src/monitor/ui/graph-layout.d.ts +43 -0
  98. package/dist/src/monitor/ui/graph-layout.js +191 -0
  99. package/dist/src/monitor/ui/graph-layout.js.map +1 -0
  100. package/dist/src/monitor/ui/tool-content.d.ts +13 -0
  101. package/dist/src/monitor/ui/tool-content.js +22 -0
  102. package/dist/src/monitor/ui/tool-content.js.map +1 -0
  103. package/dist/src/monitor/ui/tool-input.d.ts +23 -0
  104. package/dist/src/monitor/ui/tool-input.js +112 -0
  105. package/dist/src/monitor/ui/tool-input.js.map +1 -0
  106. package/dist/src/project/cli.d.ts +9 -0
  107. package/dist/src/project/cli.js +306 -0
  108. package/dist/src/project/cli.js.map +1 -0
  109. package/dist/src/project/graph.d.ts +4 -0
  110. package/dist/src/project/graph.js +26 -0
  111. package/dist/src/project/graph.js.map +1 -0
  112. package/dist/src/project/identity.d.ts +5 -0
  113. package/dist/src/project/identity.js +87 -0
  114. package/dist/src/project/identity.js.map +1 -0
  115. package/dist/src/project/index.d.ts +19 -0
  116. package/dist/src/project/index.js +26 -0
  117. package/dist/src/project/index.js.map +1 -0
  118. package/dist/src/project/query.d.ts +9 -0
  119. package/dist/src/project/query.js +136 -0
  120. package/dist/src/project/query.js.map +1 -0
  121. package/dist/src/project/store.d.ts +15 -0
  122. package/dist/src/project/store.js +47 -0
  123. package/dist/src/project/store.js.map +1 -0
  124. package/dist/src/project/types.d.ts +106 -0
  125. package/dist/src/project/types.js +2 -0
  126. package/dist/src/project/types.js.map +1 -0
  127. package/dist/src/requester/index.d.ts +16 -0
  128. package/dist/src/requester/index.js +96 -0
  129. package/dist/src/requester/index.js.map +1 -0
  130. package/dist/src/runtime-paths.d.ts +1 -0
  131. package/dist/src/runtime-paths.js +4 -0
  132. package/dist/src/runtime-paths.js.map +1 -0
  133. package/dist/src/sdk.d.ts +9 -0
  134. package/dist/src/sdk.js +3 -0
  135. package/dist/src/sdk.js.map +1 -0
  136. package/dist/src/tools/contracts.d.ts +108 -0
  137. package/dist/src/tools/contracts.js +2 -0
  138. package/dist/src/tools/contracts.js.map +1 -0
  139. package/dist/src/tools/host.d.ts +7 -0
  140. package/dist/src/tools/host.js +98 -0
  141. package/dist/src/tools/host.js.map +1 -0
  142. package/dist/src/tools/paths.d.ts +2 -0
  143. package/dist/src/tools/paths.js +18 -0
  144. package/dist/src/tools/paths.js.map +1 -0
  145. package/dist/src/tools/runner.d.ts +54 -0
  146. package/dist/src/tools/runner.js +194 -0
  147. package/dist/src/tools/runner.js.map +1 -0
  148. package/dist/src/tools/runtime-host.d.ts +1 -0
  149. package/dist/src/tools/runtime-host.js +116 -0
  150. package/dist/src/tools/runtime-host.js.map +1 -0
  151. package/dist/src/tools/schema.d.ts +6 -0
  152. package/dist/src/tools/schema.js +106 -0
  153. package/dist/src/tools/schema.js.map +1 -0
  154. package/dist/src/worker-client.d.ts +27 -0
  155. package/dist/src/worker-client.js +96 -0
  156. package/dist/src/worker-client.js.map +1 -0
  157. package/dist/src/worker.d.ts +1 -0
  158. package/dist/src/worker.js +50 -0
  159. package/dist/src/worker.js.map +1 -0
  160. package/dist/src/workspaces/index.d.ts +33 -0
  161. package/dist/src/workspaces/index.js +394 -0
  162. package/dist/src/workspaces/index.js.map +1 -0
  163. package/package.json +26 -0
@@ -0,0 +1,87 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { createReadStream } from 'node:fs';
3
+ import { lstat, readdir } from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import { isArtifactGroup, resolveArtifactScope } from '../artifacts/groups.js';
6
+ import { createGraphDefinition } from '../broker/graph.js';
7
+ import { validateRelativePath } from '../broker/config.js';
8
+ import { packageVersion } from '../runtime-paths.js';
9
+ export function canonical(value) {
10
+ if (Array.isArray(value))
11
+ return `[${value.map(canonical).join(',')}]`;
12
+ if (value !== null && typeof value === 'object')
13
+ return `{${Object.entries(value).filter(([, v]) => v !== undefined).sort(([a], [b]) => a.localeCompare(b, 'en')).map(([k, v]) => `${JSON.stringify(k)}:${canonical(v)}`).join(',')}}`;
14
+ return JSON.stringify(value) ?? 'null';
15
+ }
16
+ export const inputHash = (value) => createHash('sha256').update(canonical(value)).digest('hex');
17
+ /** Hash declared content, including additions, removals, names and empty directories. */
18
+ async function hashPath(root, relative, signal) {
19
+ validateRelativePath(relative);
20
+ // Check every ancestor before following a path: a file under a symlink is not scoped input.
21
+ let current = root;
22
+ for (const component of relative.split('/')) {
23
+ current = path.join(current, component);
24
+ const info = await lstat(current).catch(error => { if (error.code === 'ENOENT')
25
+ return null; throw error; });
26
+ if (!info)
27
+ return inputHash({ path: relative, type: 'missing' });
28
+ if (info.isSymbolicLink())
29
+ throw new Error(`Stale input must not contain symlinks: ${relative}`);
30
+ }
31
+ const entries = [];
32
+ const walk = async (absolute, name) => {
33
+ signal?.throwIfAborted();
34
+ const info = await lstat(absolute);
35
+ if (info.isSymbolicLink())
36
+ throw new Error(`Stale input must not contain symlinks: ${name}`);
37
+ if (info.isDirectory()) {
38
+ entries.push({ name, type: 'directory' });
39
+ for (const child of (await readdir(absolute)).sort())
40
+ await walk(path.join(absolute, child), `${name}/${child}`);
41
+ }
42
+ else if (info.isFile()) {
43
+ const hash = createHash('sha256');
44
+ for await (const bytes of createReadStream(absolute, { signal }))
45
+ hash.update(bytes);
46
+ entries.push({ name, type: 'file', executable: info.mode & 0o111, hash: hash.digest('hex') });
47
+ }
48
+ else
49
+ throw new Error(`Unsupported stale input: ${name}`);
50
+ };
51
+ await walk(path.join(root, relative), relative);
52
+ return inputHash(entries);
53
+ }
54
+ export async function createProjectSnapshot(config, root, snapshotHash, signal) {
55
+ createGraphDefinition(config);
56
+ const artifactHashes = {}, reusable = {};
57
+ const paths = new Map();
58
+ const fingerprintPath = (value) => { if (!paths.has(value))
59
+ paths.set(value, hashPath(root, value, signal)); return paths.get(value); };
60
+ const visit = async (id) => {
61
+ if (artifactHashes[id])
62
+ return artifactHashes[id];
63
+ const artifact = config.artifacts[id];
64
+ const extraPaths = artifact.stale?.kind === 'file-hash' ? artifact.stale.paths : undefined;
65
+ const fingerprints = await Promise.all((extraPaths ?? (isArtifactGroup(artifact) ? [] : [artifact.path])).slice().sort().map(async (name) => ({ path: name, hash: await fingerprintPath(name) })));
66
+ const members = isArtifactGroup(artifact) ? await Promise.all(artifact.members.map(async (member) => ({ id: member, hash: await visit(member) }))) : [];
67
+ reusable[id] = artifact.stale?.kind !== 'always' && members.every(member => reusable[member.id]);
68
+ return artifactHashes[id] = inputHash({ definition: artifact, fingerprints, members });
69
+ };
70
+ for (const id of Object.keys(config.artifacts))
71
+ await visit(id);
72
+ const inputs = {};
73
+ for (const critic of config.critics) {
74
+ const scope = resolveArtifactScope(config.artifacts, [critic.target, ...critic.deps]);
75
+ const types = Object.fromEntries([...new Set(scope.artifacts.map(a => a.type))].sort().map(type => [type, config.artifactTypes[type]]));
76
+ // A TS tool can close over arbitrary imported values. Keep its module snapshot in
77
+ // the identity rather than falsely treating identical function text as identical behavior.
78
+ const modules = config.configManifest?.modules;
79
+ const tools = config.configManifest ? Object.fromEntries(Object.keys(types).map(type => [type, config.configManifest.types[type]])) : types;
80
+ const criticHash = inputHash({ version: 1, executorVersion: packageVersion, critic, tools, modules, runtime: critic.profile.kind === 'runtime' ? { node: process.versions.node, platform: process.platform, arch: process.arch } : undefined });
81
+ const target = { id: critic.target, hash: artifactHashes[critic.target] };
82
+ const deps = critic.deps.slice().sort().map(id => ({ id, hash: artifactHashes[id] }));
83
+ inputs[critic.id] = { version: 1, key: inputHash({ criticHash, target, deps }), criticHash, target, deps, reusable: [critic.target, ...critic.deps].every(id => reusable[id]) };
84
+ }
85
+ return { version: 1, config: structuredClone(config), snapshotHash, artifactHashes, inputs };
86
+ }
87
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../../src/project/identity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { ProjectSelection } from './types.js';
2
+ export type * from './types.js';
3
+ export { createProjectSnapshot } from './identity.js';
4
+ export { queryProject, planProject } from './query.js';
5
+ export { projectHistory, projectRun, projectRuns, projectRequests } from './store.js';
6
+ export { createBroker } from '../broker/index.js';
7
+ export { createExecutorRegistry } from '../executors/index.js';
8
+ /** Explicit CLI query: briefly observe the current workspace without creating a store. */
9
+ export declare function inspectProject({ repoPath, stateDir, selection, recursive, force, signal }: {
10
+ repoPath: string;
11
+ stateDir: string;
12
+ selection?: ProjectSelection;
13
+ recursive?: boolean;
14
+ force?: boolean;
15
+ signal?: AbortSignal;
16
+ }): Promise<{
17
+ snapshot: import("./types.js").ProjectSnapshot;
18
+ plan: import("./types.js").ProjectPlan;
19
+ }>;
@@ -0,0 +1,26 @@
1
+ import { readWorkspaceConfig } from '../broker/config.js';
2
+ import { prepareWorkspace } from '../workspaces/index.js';
3
+ import { createProjectSnapshot } from './identity.js';
4
+ import { planProject } from './query.js';
5
+ import { projectHistory } from './store.js';
6
+ export { createProjectSnapshot } from './identity.js';
7
+ export { queryProject, planProject } from './query.js';
8
+ export { projectHistory, projectRun, projectRuns, projectRequests } from './store.js';
9
+ export { createBroker } from '../broker/index.js';
10
+ export { createExecutorRegistry } from '../executors/index.js';
11
+ /** Explicit CLI query: briefly observe the current workspace without creating a store. */
12
+ export async function inspectProject({ repoPath, stateDir, selection, recursive = false, force = false, signal }) {
13
+ const workspace = await prepareWorkspace({ repoPath, stateDir, mode: 'lock', signal });
14
+ try {
15
+ const { config } = await readWorkspaceConfig(workspace.descriptor.path, workspace.signal);
16
+ const snapshot = await createProjectSnapshot(config, workspace.descriptor.path, workspace.descriptor.hash, workspace.signal);
17
+ const history = projectHistory(stateDir);
18
+ const plan = planProject(snapshot, history, { selection, recursive, force });
19
+ await workspace.assertUnchanged();
20
+ return { snapshot, plan };
21
+ }
22
+ finally {
23
+ await workspace.close();
24
+ }
25
+ }
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/project/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAI5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,0FAA0F;AAC1F,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,GAAG,KAAK,EAAE,KAAK,GAAG,KAAK,EAAE,MAAM,EAAoI;IAChP,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvF,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,mBAAmB,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;QAC1F,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,MAAM,EAAE,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;QAC7H,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7E,MAAM,SAAS,CAAC,eAAe,EAAE,CAAC;QAClC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC5B,CAAC;YAAS,CAAC;QAAC,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;IAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { ProjectSnapshot, ProjectSelection, QueryOptions, ValidationEvidence, ProjectQuery, ProjectPlan } from './types.js';
2
+ export declare function selectedCritics(snapshot: ProjectSnapshot, selection: ProjectSelection): string[];
3
+ export declare function includedCritics(snapshot: ProjectSnapshot, selection: ProjectSelection, recursive: boolean): string[];
4
+ /** No stored staleState: these memo tables live for precisely one pull query. */
5
+ export declare function queryProject(snapshot: ProjectSnapshot, history: readonly ValidationEvidence[], options?: QueryOptions): ProjectQuery;
6
+ export declare function planProject(snapshot: ProjectSnapshot, history: readonly ValidationEvidence[], options?: QueryOptions & {
7
+ recursive?: boolean;
8
+ force?: boolean;
9
+ }): ProjectPlan;
@@ -0,0 +1,136 @@
1
+ import { createGraphDefinition } from '../broker/graph.js';
2
+ export function selectedCritics(snapshot, selection) {
3
+ const config = snapshot.config;
4
+ if (selection.kind === 'all')
5
+ return config.critics.map(c => c.id);
6
+ if (selection.kind === 'critic') {
7
+ if (!config.critics.some(c => c.id === selection.criticId))
8
+ throw new Error(`Unknown Critic: ${selection.criticId}`);
9
+ return [selection.criticId];
10
+ }
11
+ if (!Object.hasOwn(config.artifacts, selection.artifactId))
12
+ throw new Error(`Unknown Artifact: ${selection.artifactId}`);
13
+ return config.critics.filter(c => c.target === selection.artifactId).map(c => c.id);
14
+ }
15
+ export function includedCritics(snapshot, selection, recursive) {
16
+ const included = new Set(selectedCritics(snapshot, selection));
17
+ if (recursive || selection.kind === 'all') {
18
+ const visit = (id) => {
19
+ const critic = snapshot.config.critics.find(c => c.id === id);
20
+ for (const parent of snapshot.config.critics.filter(c => critic.deps.includes(c.target))) {
21
+ if (included.has(parent.id))
22
+ continue;
23
+ included.add(parent.id);
24
+ visit(parent.id);
25
+ }
26
+ };
27
+ for (const id of [...included])
28
+ visit(id);
29
+ }
30
+ return snapshot.config.critics.filter(c => included.has(c.id)).map(c => c.id);
31
+ }
32
+ /** No stored staleState: these memo tables live for precisely one pull query. */
33
+ export function queryProject(snapshot, history, options = {}) {
34
+ createGraphDefinition(snapshot.config);
35
+ const selection = options.selection ?? { kind: 'all' };
36
+ selectedCritics(snapshot, selection);
37
+ const byKey = new Map(), byRunKey = new Map(), byCritic = new Map();
38
+ // The store orders ties by insertion order. Stable sorting keeps that order here.
39
+ for (const evidence of [...history].sort((a, b) => a.completedAt.localeCompare(b.completedAt))) {
40
+ byKey.set(evidence.input.key, evidence);
41
+ byCritic.set(evidence.criticId, evidence);
42
+ if (evidence.runId === options.runId)
43
+ byRunKey.set(evidence.input.key, evidence);
44
+ }
45
+ const attempts = new Map(options.attempts?.map(request => [request.criticId, request]));
46
+ const forced = new Set(options.forceCriticIds ?? []);
47
+ const artifactMemo = new Map(), criticMemo = new Map();
48
+ const critic = (id) => {
49
+ if (criticMemo.has(id))
50
+ return criticMemo.get(id);
51
+ const definition = snapshot.config.critics.find(c => c.id === id);
52
+ const input = snapshot.inputs[id];
53
+ if (!input)
54
+ throw new Error(`Missing recorded validation input: ${id}`);
55
+ const found = (input.reusable && !forced.has(id) ? byKey : byRunKey).get(input.key);
56
+ const attempt = attempts.get(id);
57
+ const evidence = found && found.criticId === id && (input.reusable && !forced.has(id) || found.runId === options.runId) ? found : null;
58
+ const blockedBy = definition.deps.filter(dep => artifact(dep).isStale);
59
+ const ownPass = evidence?.verdict === 'GREEN';
60
+ let status, reason;
61
+ if (attempt && ['QUEUED', 'RUNNING', 'WAITING_HUMAN'].includes(attempt.status)) {
62
+ status = attempt.status;
63
+ reason = 'A review of this input is in progress.';
64
+ }
65
+ else if (attempt?.status === 'ERROR') {
66
+ status = 'ERROR';
67
+ reason = attempt.error ?? 'The review could not complete.';
68
+ }
69
+ else if (blockedBy.length) {
70
+ status = 'BLOCKED';
71
+ reason = `Required Artifact validation is not satisfied: ${blockedBy.map(dep => `${dep} (${artifact(dep).criticIds.filter(id => critic(id).isStale).map(id => `${id}: ${critic(id).status}`).join(', ') || 'no evaluator'})`).join('; ')}.`;
72
+ }
73
+ else if (ownPass) {
74
+ status = 'PASS';
75
+ reason = `Reusing actual PASS evidence ${evidence.requestId}.`;
76
+ }
77
+ else if (evidence?.verdict === 'RED') {
78
+ status = 'RED';
79
+ reason = evidence.summary;
80
+ }
81
+ else if (forced.has(id)) {
82
+ status = 'STALE';
83
+ reason = 'This request explicitly requires a new review.';
84
+ }
85
+ else if (!input.reusable) {
86
+ status = 'STALE';
87
+ reason = 'The always strategy requires a review in this validation request.';
88
+ }
89
+ else if (byCritic.has(id)) {
90
+ const previous = byCritic.get(id).input;
91
+ const changed = [previous.criticHash !== input.criticHash ? 'Critic conditions' : '', previous.target.hash !== input.target.hash ? `target ${input.target.id}` : '', ...input.deps.filter(dep => previous.deps.find(p => p.id === dep.id)?.hash !== dep.hash).map(dep => `dependency ${dep.id}`)].filter(Boolean);
92
+ status = 'STALE';
93
+ reason = `Validation input changed: ${changed.join(', ') || 'dependency scope'}.`;
94
+ }
95
+ else {
96
+ status = 'UNREVIEWED';
97
+ reason = 'No actual review has been recorded for this input.';
98
+ }
99
+ const value = { id, title: definition.title, target: definition.target, deps: [...definition.deps], status,
100
+ isStale: status !== 'PASS', needsReview: !ownPass || forced.has(id) && evidence?.runId !== options.runId,
101
+ canExecute: blockedBy.length === 0 && !ownPass && !attempt,
102
+ blockedBy, reason, input, result: evidence, requestId: attempt?.id ?? null };
103
+ criticMemo.set(id, value);
104
+ return value;
105
+ };
106
+ const artifact = (id) => {
107
+ if (artifactMemo.has(id))
108
+ return artifactMemo.get(id);
109
+ const definition = snapshot.config.artifacts[id];
110
+ const own = snapshot.config.critics.filter(c => c.target === id).map(c => critic(c.id));
111
+ const passed = own.filter(c => !c.isStale).length;
112
+ const status = definition.basis ? 'BASIS' : own.length && passed === own.length ? 'PASS' :
113
+ ['RUNNING', 'QUEUED', 'WAITING_HUMAN', 'ERROR', 'RED', 'BLOCKED', 'STALE', 'UNREVIEWED'].find(s => own.some(c => c.status === s)) ?? 'UNREVIEWED';
114
+ const value = { id, hash: snapshot.artifactHashes[id], status, isStale: status !== 'PASS' && status !== 'BASIS', criticIds: own.map(c => c.id), passed, total: own.length };
115
+ artifactMemo.set(id, value);
116
+ return value;
117
+ };
118
+ const artifacts = Object.keys(snapshot.config.artifacts).map(artifact);
119
+ const critics = snapshot.config.critics.map(c => critic(c.id));
120
+ const satisfied = selection.kind === 'artifact' ? !artifact(selection.artifactId).isStale : selection.kind === 'critic' ? !critic(selection.criticId).isStale : critics.every(c => !c.isStale);
121
+ return { snapshotHash: snapshot.snapshotHash, selection, satisfied, artifacts, critics };
122
+ }
123
+ export function planProject(snapshot, history, options = {}) {
124
+ const selection = options.selection ?? { kind: 'all' };
125
+ const selectedCriticIds = selectedCritics(snapshot, selection);
126
+ const includedCriticIds = includedCritics(snapshot, selection, Boolean(options.recursive));
127
+ const forceCriticIds = options.force ? selectedCriticIds : [];
128
+ const query = queryProject(snapshot, history, { ...options, selection, forceCriticIds });
129
+ const items = query.critics.filter(c => includedCriticIds.includes(c.id)).map(c => {
130
+ const action = (c.status === 'PASS' ? 'REUSE' : ['QUEUED', 'RUNNING', 'WAITING_HUMAN'].includes(c.status) ? 'ACTIVE' : c.canExecute ? 'EXECUTE' : c.requestId && ['ERROR', 'RED'].includes(c.status) ? 'FAILED' : 'WAIT');
131
+ return { ...c, action };
132
+ });
133
+ return { ...query, recursive: Boolean(options.recursive), force: Boolean(options.force), selectedCriticIds, includedCriticIds, items,
134
+ counts: { reuse: items.filter(c => c.action === 'REUSE').length, execute: items.filter(c => c.action === 'EXECUTE').length, wait: items.filter(c => c.action === 'WAIT').length, active: items.filter(c => c.action === 'ACTIVE').length, failed: items.filter(c => c.action === 'FAILED').length } };
135
+ }
136
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../../src/project/query.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { DatabaseSync } from 'node:sqlite';
2
+ import type { ReviewRequest } from '../contracts.js';
3
+ import type { RunView } from '../broker/index.js';
4
+ import type { ValidationEvidence, ProjectPlan } from './types.js';
5
+ export declare function readEvidence(database: DatabaseSync): ValidationEvidence[];
6
+ /** Existing databases only; no migrations, ownership reconciliation or write connection. */
7
+ export declare function withProjectStore<T>(stateDir: string, read: (database: DatabaseSync) => T, empty: T): T;
8
+ export declare function projectHistory(stateDir: string): ValidationEvidence[];
9
+ export type ProjectRunView = RunView & {
10
+ validation?: ProjectPlan;
11
+ };
12
+ export declare function storedRun(database: DatabaseSync, id: string): ProjectRunView | null;
13
+ export declare function projectRun(stateDir: string, id: string): ProjectRunView | null;
14
+ export declare function projectRuns(stateDir: string): ProjectRunView[];
15
+ export declare function projectRequests(stateDir: string, runId?: string): ReviewRequest[];
@@ -0,0 +1,47 @@
1
+ import { DatabaseSync } from 'node:sqlite';
2
+ import { existsSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { planProject } from './query.js';
5
+ export function readEvidence(database) {
6
+ const rows = database.prepare("SELECT data FROM requests WHERE status IN ('GREEN','RED') AND json_extract(data, '$.validationInput.version') = 1 ORDER BY json_extract(data, '$.completedAt'), rowid").all();
7
+ return rows.flatMap(row => {
8
+ const request = JSON.parse(String(row.data));
9
+ if (!request.validationInput || !/^[a-f0-9]{64}$/.test(request.validationInput.key) || !request.result || request.result.verdict !== request.status || !request.completedAt)
10
+ return [];
11
+ return [{ requestId: request.id, runId: request.runId, criticId: request.criticId, input: request.validationInput, completedAt: request.completedAt, verdict: request.result.verdict, summary: request.result.summary, evidence: request.result.evidence }];
12
+ });
13
+ }
14
+ /** Existing databases only; no migrations, ownership reconciliation or write connection. */
15
+ export function withProjectStore(stateDir, read, empty) {
16
+ const filename = join(stateDir, 'broker.sqlite');
17
+ if (!existsSync(filename))
18
+ return empty;
19
+ const database = new DatabaseSync(filename, { readOnly: true });
20
+ try {
21
+ database.exec('BEGIN');
22
+ const result = read(database);
23
+ database.exec('COMMIT');
24
+ return result;
25
+ }
26
+ finally {
27
+ database.close();
28
+ }
29
+ }
30
+ export function projectHistory(stateDir) { return withProjectStore(stateDir, readEvidence, []); }
31
+ export function storedRun(database, id) {
32
+ const row = database.prepare('SELECT data FROM runs WHERE id = ?').get(id);
33
+ if (!row)
34
+ return null;
35
+ const run = JSON.parse(String(row.data));
36
+ const requests = database.prepare('SELECT data FROM requests WHERE run_id = ? ORDER BY ordinal').all(id).map(row => JSON.parse(String(row.data)));
37
+ const events = database.prepare('SELECT * FROM (SELECT * FROM events WHERE run_id = ? ORDER BY id DESC LIMIT 500) ORDER BY id').all(id).map(event => ({ id: Number(event.id), runId: String(event.run_id), requestId: event.request_id === null ? null : String(event.request_id), createdAt: String(event.created_at), type: String(event.type), message: String(event.message) }));
38
+ const owner = database.prepare('SELECT pid, claimed_at FROM run_owners WHERE run_id = ?').get(id);
39
+ return { ...run, scope: run.scope ?? { kind: run.graph ? 'graph' : 'chain' }, requests, events, owner: owner ? { pid: Number(owner.pid), claimedAt: String(owner.claimed_at) } : null,
40
+ ...(run.project ? { validation: planProject(run.project.snapshot, readEvidence(database).filter(e => !run.project.evidenceRequestIds || run.project.evidenceRequestIds.includes(e.requestId)), { selection: run.project.selection, recursive: run.project.recursive, force: run.project.force, runId: id, attempts: requests }) } : {}) };
41
+ }
42
+ export function projectRun(stateDir, id) { return withProjectStore(stateDir, db => storedRun(db, id), null); }
43
+ export function projectRuns(stateDir) { return withProjectStore(stateDir, db => db.prepare('SELECT id FROM runs ORDER BY created_at DESC, rowid DESC').all().map(row => storedRun(db, String(row.id))), []); }
44
+ export function projectRequests(stateDir, runId) {
45
+ return withProjectStore(stateDir, db => (runId ? db.prepare('SELECT data FROM requests WHERE run_id = ? ORDER BY ordinal').all(runId) : db.prepare('SELECT data FROM requests ORDER BY created_at DESC, rowid DESC').all()).map(row => JSON.parse(String(row.data))), []);
46
+ }
47
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/project/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ import type { RepoConfig, ReviewEnvelope, ReviewResult, ReviewRequest } from '../contracts.js';
2
+ export type ProjectSelection = {
3
+ kind: 'all';
4
+ } | {
5
+ kind: 'artifact';
6
+ artifactId: string;
7
+ } | {
8
+ kind: 'critic';
9
+ criticId: string;
10
+ };
11
+ export interface ValidationInput {
12
+ version: 1;
13
+ key: string;
14
+ criticHash: string;
15
+ target: {
16
+ id: string;
17
+ hash: string;
18
+ };
19
+ deps: {
20
+ id: string;
21
+ hash: string;
22
+ }[];
23
+ reusable: boolean;
24
+ }
25
+ export interface ProjectSnapshot {
26
+ version: 1;
27
+ config: RepoConfig;
28
+ snapshotHash: string;
29
+ artifactHashes: Record<string, string>;
30
+ inputs: Record<string, ValidationInput>;
31
+ }
32
+ export interface ValidationEvidence {
33
+ requestId: string;
34
+ runId: string;
35
+ criticId: string;
36
+ input: ValidationInput;
37
+ completedAt: string;
38
+ verdict: ReviewResult['verdict'];
39
+ summary: string;
40
+ evidence: string[];
41
+ }
42
+ export interface ProjectRunDefinition {
43
+ version: 1;
44
+ snapshot: ProjectSnapshot;
45
+ selection: ProjectSelection;
46
+ recursive: boolean;
47
+ force: boolean;
48
+ /** Prepared definitions, not tickets or persisted stale states. */
49
+ templates: ReviewEnvelope[];
50
+ /** Original evidence consumed by a completed execution; never a cached stale flag. */
51
+ evidenceRequestIds?: string[];
52
+ }
53
+ export type ValidationStatus = 'PASS' | 'BASIS' | 'UNREVIEWED' | 'STALE' | 'RED' | 'ERROR' | 'BLOCKED' | 'QUEUED' | 'RUNNING' | 'WAITING_HUMAN';
54
+ export interface CriticValidation {
55
+ id: string;
56
+ title: string;
57
+ target: string;
58
+ deps: string[];
59
+ status: ValidationStatus;
60
+ isStale: boolean;
61
+ canExecute: boolean;
62
+ needsReview: boolean;
63
+ blockedBy: string[];
64
+ reason: string;
65
+ input: ValidationInput;
66
+ result: ValidationEvidence | null;
67
+ requestId: string | null;
68
+ }
69
+ export interface ArtifactValidation {
70
+ id: string;
71
+ hash: string;
72
+ status: ValidationStatus;
73
+ isStale: boolean;
74
+ criticIds: string[];
75
+ passed: number;
76
+ total: number;
77
+ }
78
+ export interface ProjectQuery {
79
+ snapshotHash: string;
80
+ selection: ProjectSelection;
81
+ satisfied: boolean;
82
+ artifacts: ArtifactValidation[];
83
+ critics: CriticValidation[];
84
+ }
85
+ export interface ProjectPlan extends ProjectQuery {
86
+ recursive: boolean;
87
+ force: boolean;
88
+ selectedCriticIds: string[];
89
+ includedCriticIds: string[];
90
+ items: (CriticValidation & {
91
+ action: 'REUSE' | 'EXECUTE' | 'WAIT' | 'ACTIVE' | 'FAILED';
92
+ })[];
93
+ counts: {
94
+ reuse: number;
95
+ execute: number;
96
+ wait: number;
97
+ active: number;
98
+ failed: number;
99
+ };
100
+ }
101
+ export interface QueryOptions {
102
+ selection?: ProjectSelection;
103
+ forceCriticIds?: readonly string[];
104
+ runId?: string;
105
+ attempts?: readonly ReviewRequest[];
106
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/project/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ import type { ReviewEnvelope, RepoConfig } from '../contracts.js';
2
+ /** Repo-side adapter: prepare explicit envelopes from one prepared workspace definition. */
3
+ export declare function prepareReviewRequests({ repoPath, repoId, snapshotHash, criticId, allowLegacyTools, preparedConfig }: {
4
+ repoPath: string;
5
+ repoId?: unknown;
6
+ snapshotHash: unknown;
7
+ criticId?: unknown;
8
+ allowLegacyTools?: boolean;
9
+ preparedConfig?: RepoConfig;
10
+ }): Promise<ReviewEnvelope[]>;
11
+ /** Reopen the declared observation scope of a stored review, including historical snapshots.
12
+ * This is never used for admission, scheduling or inferring a legacy target. */
13
+ export declare function readStoredArtifactScope({ repoPath, criticId }: {
14
+ repoPath: string;
15
+ criticId: string;
16
+ }): Promise<Pick<ReviewEnvelope, 'artifacts' | 'artifactGroups' | 'artifactTypes' | 'profile'>>;
@@ -0,0 +1,96 @@
1
+ import { readFile, lstat } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { readWorkspaceConfig, validateRelativePath } from '../broker/config.js';
4
+ import { assertArtifactAudience } from '../artifacts/types.js';
5
+ import { createArtifactViewer, createArtifactTools } from '../artifacts/index.js';
6
+ import { createHumanArtifactTools } from '../artifacts/human.js';
7
+ import { describeReviewTools } from '../tools/runner.js';
8
+ import { resolveArtifactScope } from '../artifacts/groups.js';
9
+ /** Repo-side adapter: prepare explicit envelopes from one prepared workspace definition. */
10
+ export async function prepareReviewRequests({ repoPath, repoId = 'demo', snapshotHash, criticId, allowLegacyTools = false, preparedConfig }) {
11
+ if (typeof repoId !== 'string' || !repoId.trim() || repoId.length > 200)
12
+ throw new Error('A registered repoId is required (maximum 200 characters).');
13
+ if (typeof snapshotHash !== 'string' || !/^[a-f0-9]{64}$/.test(snapshotHash))
14
+ throw new Error('snapshotHash must be a full workspace SHA-256 content hash.');
15
+ if (criticId !== undefined && (typeof criticId !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/.test(criticId))) {
16
+ throw new Error('criticId must be a non-empty safe Critic identifier.');
17
+ }
18
+ const snapshot = preparedConfig ? { config: preparedConfig } : await readWorkspaceConfig(repoPath);
19
+ const critics = criticId === undefined ? snapshot.config.critics : snapshot.config.critics.filter(critic => critic.id === criticId);
20
+ if (!critics.length)
21
+ throw new Error(`Unknown Critic in the requested snapshot: ${criticId}`);
22
+ const requests = critics.map(critic => structuredClone({
23
+ repoId,
24
+ snapshotHash,
25
+ criticId: critic.id,
26
+ title: critic.title,
27
+ ...resolveArtifactScope(snapshot.config.artifacts, [critic.target, ...critic.deps]),
28
+ artifactTypes: snapshot.config.artifactTypes,
29
+ ...(snapshot.config.configManifest ? { configManifest: snapshot.config.configManifest } : {}),
30
+ payload: critic.payload,
31
+ profile: critic.profile,
32
+ target: critic.target,
33
+ deps: critic.deps,
34
+ }));
35
+ for (const request of requests) {
36
+ if (request.profile.kind === 'runtime')
37
+ continue;
38
+ if (request.configManifest) {
39
+ const tools = describeReviewTools({ artifacts: request.artifacts, configManifest: request.configManifest, audience: request.profile.kind });
40
+ for (const artifact of request.artifacts) {
41
+ const info = await lstat(join(repoPath, artifact.path));
42
+ if (!tools.some(tool => tool.artifactId === artifact.id && (!tool.metadata?.artifactKind || tool.metadata.artifactKind === 'any' || tool.metadata.artifactKind === 'file' && info.isFile() || tool.metadata.artifactKind === 'directory' && info.isDirectory())))
43
+ throw Object.assign(new Error(`Artifact ${artifact.id} has no usable ${request.profile.kind} tools.`), { code: 'ARTIFACT_TOOLS_UNAVAILABLE' });
44
+ }
45
+ continue;
46
+ }
47
+ assertArtifactAudience(request, { allowLegacy: allowLegacyTools });
48
+ const tools = request.profile.kind === 'human'
49
+ ? (await createHumanArtifactTools({ worktreePath: repoPath, artifacts: request.artifacts, artifactTypes: request.artifactTypes, allowLegacy: allowLegacyTools })).tools
50
+ : createArtifactTools(await createArtifactViewer({ worktreePath: repoPath, artifacts: request.artifacts, artifactTypes: request.artifactTypes })).tools;
51
+ for (const artifact of request.artifacts) {
52
+ if (!tools.some(tool => 'artifactId' in tool ? tool.artifactId === artifact.id : tool.name === `read_${artifact.id}` || tool.name === `list_${artifact.id}`)) {
53
+ throw new Error(`Artifact ${artifact.id} has no usable ${request.profile.kind} tools for its file or directory shape.`);
54
+ }
55
+ }
56
+ }
57
+ return requests;
58
+ }
59
+ /** Reopen the declared observation scope of a stored review, including historical snapshots.
60
+ * This is never used for admission, scheduling or inferring a legacy target. */
61
+ export async function readStoredArtifactScope({ repoPath, criticId }) {
62
+ const object = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
63
+ const raw = JSON.parse(await readFile(join(repoPath, 'ccdd.config.json'), 'utf8'));
64
+ if (!object(raw) || !object(raw.artifacts) || !object(raw.artifactTypes) || !Array.isArray(raw.critics))
65
+ throw new Error('Invalid stored Artifact configuration.');
66
+ const matches = raw.critics.filter(critic => object(critic) && critic.id === criticId);
67
+ if (matches.length !== 1 || !object(matches[0]))
68
+ throw new Error('Unknown stored Critic.');
69
+ const critic = matches[0];
70
+ if (!object(critic.profile) || !['agent', 'runtime', 'human'].includes(String(critic.profile.kind)))
71
+ throw new Error('Invalid stored Critic profile.');
72
+ const legacy = !Object.hasOwn(critic, 'target') && Object.hasOwn(critic, 'dependsOn');
73
+ let ids;
74
+ if (legacy)
75
+ ids = critic.artifacts;
76
+ else {
77
+ const { config } = await readWorkspaceConfig(repoPath);
78
+ const definition = config.critics.find(item => item.id === criticId);
79
+ const scope = { ...resolveArtifactScope(config.artifacts, [definition.target, ...definition.deps]), artifactTypes: config.artifactTypes, profile: definition.profile };
80
+ await createArtifactViewer({ worktreePath: repoPath, artifacts: scope.artifacts, artifactTypes: scope.artifactTypes });
81
+ return scope;
82
+ }
83
+ if (!Array.isArray(ids) || !ids.length || new Set(ids).size !== ids.length || ids.some(id => typeof id !== 'string' || !Object.hasOwn(raw.artifacts, id)))
84
+ throw new Error('Invalid stored Artifact references.');
85
+ const definitions = raw.artifacts;
86
+ const artifacts = ids.map(id => {
87
+ const artifact = definitions[id];
88
+ if (!/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/.test(id) || !object(artifact) || typeof artifact.type !== 'string' || !Object.hasOwn(raw.artifactTypes, artifact.type))
89
+ throw new Error('Invalid stored Artifact definition.');
90
+ return { id, type: artifact.type, path: validateRelativePath(artifact.path) };
91
+ });
92
+ const scope = { artifacts, artifactTypes: raw.artifactTypes, profile: critic.profile };
93
+ await createArtifactViewer({ worktreePath: repoPath, artifacts: scope.artifacts, artifactTypes: scope.artifactTypes });
94
+ return scope;
95
+ }
96
+ //# sourceMappingURL=index.js.map