@ccdd/core 3.3.1 → 4.0.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 (38) hide show
  1. package/README.md +69 -62
  2. package/dist/src/artifact-scope.d.ts +6 -0
  3. package/dist/src/artifact-scope.js +27 -0
  4. package/dist/src/artifact-scope.js.map +1 -0
  5. package/dist/src/definitions.d.ts +33 -23
  6. package/dist/src/sdk.d.ts +3 -8
  7. package/dist/src/sdk.js +2 -3
  8. package/dist/src/sdk.js.map +1 -1
  9. package/dist/src/tools/contracts.d.ts +34 -78
  10. package/examples/artifact-folders/README.md +18 -0
  11. package/examples/artifact-folders/coding-style/ccdd.json +128 -0
  12. package/examples/artifact-folders/coding-style/style.md +3 -0
  13. package/examples/artifact-folders/explosion/blind-pair.mjs +19 -0
  14. package/examples/artifact-folders/explosion/ccdd.json +220 -0
  15. package/examples/artifact-folders/explosion/effect/ccdd.json +128 -0
  16. package/examples/artifact-folders/explosion/preview/ccdd.json +142 -0
  17. package/examples/artifact-folders/theme-image/ccdd.json +128 -0
  18. package/examples/artifact-folders/theme-image/theme.png +0 -0
  19. package/examples/computed-views/README.md +12 -0
  20. package/examples/computed-views/checkout/ccdd.json +133 -0
  21. package/examples/computed-views/search/ccdd.json +133 -0
  22. package/examples/computed-views/view.mjs +13 -0
  23. package/examples/custom-text-reader/README.md +7 -19
  24. package/examples/custom-text-reader/spec/ccdd.json +60 -0
  25. package/examples/custom-text-reader/view.mjs +20 -0
  26. package/examples/custom-text-reader/why/ccdd.json +46 -0
  27. package/package.json +21 -7
  28. package/examples/artifact-groups/README.md +0 -60
  29. package/examples/artifact-groups/ccdd.config.ts +0 -37
  30. package/examples/custom-text-reader/ccdd.config.ts +0 -64
  31. package/examples/generated-artifacts/README.md +0 -55
  32. package/examples/generated-artifacts/ccdd.config.ts +0 -86
  33. /package/examples/{artifact-groups → artifact-folders/explosion/effect}/effect.md +0 -0
  34. /package/examples/{artifact-groups → artifact-folders/explosion/preview}/preview.png +0 -0
  35. /package/examples/{generated-artifacts/scenarios/checkout.json → computed-views/checkout/scenario.json} +0 -0
  36. /package/examples/{generated-artifacts/scenarios/search.json → computed-views/search/scenario.json} +0 -0
  37. /package/examples/custom-text-reader/{spec.md → spec/spec.md} +0 -0
  38. /package/examples/custom-text-reader/{why.md → why/why.md} +0 -0
@@ -0,0 +1,133 @@
1
+ {
2
+ "name": "checkout",
3
+ "views": {
4
+ "agentTools": {
5
+ "overview": {
6
+ "metadata": {
7
+ "description": "Inspect {artifactName} with overview.",
8
+ "inputSchema": {
9
+ "type": "object",
10
+ "properties": {},
11
+ "additionalProperties": false
12
+ },
13
+ "resultKinds": [
14
+ "json"
15
+ ],
16
+ "observation": "content",
17
+ "executionPaths": [
18
+ "view.mjs"
19
+ ]
20
+ },
21
+ "script": {
22
+ "command": "node",
23
+ "args": [
24
+ "../view.mjs",
25
+ "overview"
26
+ ]
27
+ }
28
+ },
29
+ "detail": {
30
+ "metadata": {
31
+ "description": "Inspect {artifactName} with detail.",
32
+ "inputSchema": {
33
+ "type": "object",
34
+ "properties": {
35
+ "id": {
36
+ "type": "string",
37
+ "minLength": 1
38
+ }
39
+ },
40
+ "additionalProperties": false,
41
+ "required": [
42
+ "id"
43
+ ]
44
+ },
45
+ "resultKinds": [
46
+ "json"
47
+ ],
48
+ "observation": "content",
49
+ "executionPaths": [
50
+ "view.mjs"
51
+ ]
52
+ },
53
+ "script": {
54
+ "command": "node",
55
+ "args": [
56
+ "../view.mjs",
57
+ "detail"
58
+ ]
59
+ }
60
+ }
61
+ },
62
+ "humanTools": {
63
+ "overview": {
64
+ "metadata": {
65
+ "description": "Inspect {artifactName} with overview.",
66
+ "inputSchema": {
67
+ "type": "object",
68
+ "properties": {},
69
+ "additionalProperties": false
70
+ },
71
+ "resultKinds": [
72
+ "json"
73
+ ],
74
+ "observation": "content",
75
+ "executionPaths": [
76
+ "view.mjs"
77
+ ]
78
+ },
79
+ "script": {
80
+ "command": "node",
81
+ "args": [
82
+ "../view.mjs",
83
+ "overview"
84
+ ]
85
+ }
86
+ },
87
+ "detail": {
88
+ "metadata": {
89
+ "description": "Inspect {artifactName} with detail.",
90
+ "inputSchema": {
91
+ "type": "object",
92
+ "properties": {
93
+ "id": {
94
+ "type": "string",
95
+ "minLength": 1
96
+ }
97
+ },
98
+ "additionalProperties": false,
99
+ "required": [
100
+ "id"
101
+ ]
102
+ },
103
+ "resultKinds": [
104
+ "json"
105
+ ],
106
+ "observation": "content",
107
+ "executionPaths": [
108
+ "view.mjs"
109
+ ]
110
+ },
111
+ "script": {
112
+ "command": "node",
113
+ "args": [
114
+ "../view.mjs",
115
+ "detail"
116
+ ]
117
+ }
118
+ }
119
+ }
120
+ },
121
+ "critics": [
122
+ {
123
+ "id": "review",
124
+ "title": "Review the checkout scenario",
125
+ "profile": {
126
+ "kind": "human"
127
+ },
128
+ "payload": {
129
+ "instruction": "Read the overview of {checkout}, then inspect every listed detail. Decide whether observations satisfy each criterion. Cite detail IDs and explain missing or contradictory evidence."
130
+ }
131
+ }
132
+ ]
133
+ }
@@ -0,0 +1,133 @@
1
+ {
2
+ "name": "search",
3
+ "views": {
4
+ "agentTools": {
5
+ "overview": {
6
+ "metadata": {
7
+ "description": "Inspect {artifactName} with overview.",
8
+ "inputSchema": {
9
+ "type": "object",
10
+ "properties": {},
11
+ "additionalProperties": false
12
+ },
13
+ "resultKinds": [
14
+ "json"
15
+ ],
16
+ "observation": "content",
17
+ "executionPaths": [
18
+ "view.mjs"
19
+ ]
20
+ },
21
+ "script": {
22
+ "command": "node",
23
+ "args": [
24
+ "../view.mjs",
25
+ "overview"
26
+ ]
27
+ }
28
+ },
29
+ "detail": {
30
+ "metadata": {
31
+ "description": "Inspect {artifactName} with detail.",
32
+ "inputSchema": {
33
+ "type": "object",
34
+ "properties": {
35
+ "id": {
36
+ "type": "string",
37
+ "minLength": 1
38
+ }
39
+ },
40
+ "additionalProperties": false,
41
+ "required": [
42
+ "id"
43
+ ]
44
+ },
45
+ "resultKinds": [
46
+ "json"
47
+ ],
48
+ "observation": "content",
49
+ "executionPaths": [
50
+ "view.mjs"
51
+ ]
52
+ },
53
+ "script": {
54
+ "command": "node",
55
+ "args": [
56
+ "../view.mjs",
57
+ "detail"
58
+ ]
59
+ }
60
+ }
61
+ },
62
+ "humanTools": {
63
+ "overview": {
64
+ "metadata": {
65
+ "description": "Inspect {artifactName} with overview.",
66
+ "inputSchema": {
67
+ "type": "object",
68
+ "properties": {},
69
+ "additionalProperties": false
70
+ },
71
+ "resultKinds": [
72
+ "json"
73
+ ],
74
+ "observation": "content",
75
+ "executionPaths": [
76
+ "view.mjs"
77
+ ]
78
+ },
79
+ "script": {
80
+ "command": "node",
81
+ "args": [
82
+ "../view.mjs",
83
+ "overview"
84
+ ]
85
+ }
86
+ },
87
+ "detail": {
88
+ "metadata": {
89
+ "description": "Inspect {artifactName} with detail.",
90
+ "inputSchema": {
91
+ "type": "object",
92
+ "properties": {
93
+ "id": {
94
+ "type": "string",
95
+ "minLength": 1
96
+ }
97
+ },
98
+ "additionalProperties": false,
99
+ "required": [
100
+ "id"
101
+ ]
102
+ },
103
+ "resultKinds": [
104
+ "json"
105
+ ],
106
+ "observation": "content",
107
+ "executionPaths": [
108
+ "view.mjs"
109
+ ]
110
+ },
111
+ "script": {
112
+ "command": "node",
113
+ "args": [
114
+ "../view.mjs",
115
+ "detail"
116
+ ]
117
+ }
118
+ }
119
+ }
120
+ },
121
+ "critics": [
122
+ {
123
+ "id": "review",
124
+ "title": "Review the search scenario",
125
+ "profile": {
126
+ "kind": "human"
127
+ },
128
+ "payload": {
129
+ "instruction": "Read the overview of {search}, then inspect every listed detail. Decide whether observations satisfy each criterion. Cite detail IDs and explain missing or contradictory evidence."
130
+ }
131
+ }
132
+ ]
133
+ }
@@ -0,0 +1,13 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ let text = '';
4
+ for await (const chunk of process.stdin) text += chunk;
5
+ const { version, context, args } = JSON.parse(text);
6
+ if (version !== 1) throw new Error('Unsupported request version.');
7
+ const scenario = JSON.parse(await readFile(join(context.artifactPath, 'scenario.json'), 'utf8'));
8
+ if (!Array.isArray(scenario.details) || !Array.isArray(scenario.criteria)) throw new Error('Invalid scenario.');
9
+ const data = process.argv[2] === 'overview'
10
+ ? { name: scenario.name, objective: scenario.objective, criteria: scenario.criteria, detailIds: scenario.details.map(item => item.id) }
11
+ : scenario.details.find(item => item.id === args.id);
12
+ if (!data) throw new Error('Unknown scenario detail.');
13
+ process.stdout.write(JSON.stringify({ content: [{ type: 'json', data }], observation: { kind: 'content' } }));
@@ -1,25 +1,13 @@
1
- # Custom Reader
1
+ # Custom text reader
2
2
 
3
- This example directly registers `{ metadata, execute }` without the default tool library. `customTextReader()` creates a definition; actual file reading occurs when an Agent calls `read_spec` or `read_why`.
3
+ `why/ccdd.json` declares an explicit basis. `spec/ccdd.json` owns its alignment Critic and reader. The instruction `{why}` derives the dependency; no `target`, `deps`, type registry or config factory is needed.
4
4
 
5
- Each project must include its own dependencies. Copy this folder into a new project outside the repository, then install core and Project. The commands below work after npm v3.1.0 publication; before that, use the local tarballs described below. The example is included in the source repository and the core package's `examples/custom-text-reader`. It does not rely on CCDD installed in a parent repository.
5
+ Install `@ccdd/core` and `@ccdd/project` in this example directory. The custom `view.mjs` requires only Node; default tools are optional.
6
6
 
7
7
  ```sh
8
- # Copy the example from the CCDD source repository.
9
- cp -R examples/custom-text-reader /tmp/ccdd-custom-reader
10
- cd /tmp/ccdd-custom-reader
11
- npm init -y
12
- npm pkg set type=module
13
- npm install --ignore-scripts @ccdd/core@3.1.0 @ccdd/project@3.1.0
14
- npx ccdd tools check --artifact spec --for agent --tool read
15
- npx ccdd tools check --artifact spec --for agent --tool read --execute --args '{"startLine":1,"lineCount":20}'
16
- npx ccdd run --copy --critic spec-why --codex-auth-file "$HOME/.codex/auth.json" --wait
8
+ ccdd-project config check
9
+ ccdd-project tools check --artifact spec --for agent --tool read --execute --args '{"startLine":1,"lineCount":20}'
10
+ ccdd-project verify spec --recursive --wait
17
11
  ```
18
12
 
19
- This example installs core and Project without the default tool library. Alternatively, in the source repository run `npm run release:npm -- --commit <40-character SHA> --dry-run` to verify and generate matching `ccdd-core-3.1.0.tgz` and `ccdd-project-3.1.0.tgz` files, then install with `npm install --ignore-scripts <core.tgz> <project.tgz>`. This local verification requires no GitHub authentication. If CCDD is already installed, change the first `cp` source to `node_modules/@ccdd/core/examples/custom-text-reader`.
20
-
21
- The tool omits `preflight`. The default check distinguishes confirmed registration from unverified execution; `--execute` actually reads the file. Agent review requires valid Provider authentication.
22
-
23
- This Reader is a small implementation illustrating the structure. It reads the file into memory before checking the 1MiB limit and limits returned text to 64KiB. A streaming reader is more appropriate for large files. It preserves UTF-8, CRLF, and the final newline, and distinguishes an empty file from a read past EOF. It returns an observation receipt only when actual content or an empty file was observed.
24
-
25
- There is no Human duplicate of the Agent Reader. This type has no Human tools, so a Human Critic cannot use it. To add human viewing, write a custom tool that opens a desktop application or explicitly register `human.desktop.open()` from `@ccdd/default-tools`.
13
+ The last command makes a real Agent request and needs configured Provider credentials outside this workspace. `view.mjs` receives the standard JSON request on stdin and returns one `ToolResult` on stdout. The fixed filename is an argv value from each Artifact's declaration. The shared script is explicitly fingerprinted by `executionPaths`.
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "spec",
3
+ "views": {
4
+ "agentTools": {
5
+ "read": {
6
+ "metadata": {
7
+ "description": "Inspect {artifactName} with read.",
8
+ "inputSchema": {
9
+ "type": "object",
10
+ "properties": {
11
+ "startLine": {
12
+ "type": "integer",
13
+ "minimum": 1
14
+ },
15
+ "lineCount": {
16
+ "type": "integer",
17
+ "minimum": 1,
18
+ "maximum": 80
19
+ }
20
+ },
21
+ "additionalProperties": false,
22
+ "required": [
23
+ "startLine",
24
+ "lineCount"
25
+ ]
26
+ },
27
+ "resultKinds": [
28
+ "json"
29
+ ],
30
+ "observation": "content",
31
+ "executionPaths": [
32
+ "view.mjs"
33
+ ]
34
+ },
35
+ "script": {
36
+ "command": "node",
37
+ "args": [
38
+ "../view.mjs",
39
+ "spec.md"
40
+ ]
41
+ }
42
+ }
43
+ }
44
+ },
45
+ "critics": [
46
+ {
47
+ "id": "alignment",
48
+ "title": "Does Spec match Why?",
49
+ "profile": {
50
+ "kind": "agent",
51
+ "provider": "openai-codex",
52
+ "model": "gpt-6-astra",
53
+ "reasoning": "medium"
54
+ },
55
+ "payload": {
56
+ "instruction": "Read {spec} and {why}; decide whether Spec satisfies the maximum task count in Why."
57
+ }
58
+ }
59
+ ]
60
+ }
@@ -0,0 +1,20 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+
4
+ // A small standard-protocol script with no SDK or Provider dependency.
5
+ let input = '';
6
+ for await (const chunk of process.stdin) input += chunk;
7
+ const { version, context, args } = JSON.parse(input);
8
+ if (version !== 1) throw new Error('Unsupported request version.');
9
+ const bytes = await readFile(join(context.artifactPath, process.argv[2]));
10
+ if (bytes.length > 1024 * 1024) throw new Error('This example accepts files up to 1 MiB.');
11
+ const text = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(bytes);
12
+ if (text.includes('\0')) throw new Error('This example accepts text, not binary data.');
13
+ const lines = text.match(/[^\n]*\n|[^\n]+$/g) ?? [];
14
+ const selected = lines.slice(args.startLine - 1, args.startLine - 1 + args.lineCount);
15
+ const content = selected.join('');
16
+ if (Buffer.byteLength(content) > 64 * 1024) throw new Error('Select a smaller line range.');
17
+ process.stdout.write(JSON.stringify({
18
+ content: [{ type: 'json', data: { content, startLine: args.startLine, lineCount: selected.length, totalLines: lines.length } }],
19
+ ...(selected.length ? { observation: { kind: 'content' } } : lines.length === 0 ? { observation: { kind: 'empty' } } : {}),
20
+ }));
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "why",
3
+ "views": {
4
+ "agentTools": {
5
+ "read": {
6
+ "metadata": {
7
+ "description": "Inspect {artifactName} with read.",
8
+ "inputSchema": {
9
+ "type": "object",
10
+ "properties": {
11
+ "startLine": {
12
+ "type": "integer",
13
+ "minimum": 1
14
+ },
15
+ "lineCount": {
16
+ "type": "integer",
17
+ "minimum": 1,
18
+ "maximum": 80
19
+ }
20
+ },
21
+ "additionalProperties": false,
22
+ "required": [
23
+ "startLine",
24
+ "lineCount"
25
+ ]
26
+ },
27
+ "resultKinds": [
28
+ "json"
29
+ ],
30
+ "observation": "content",
31
+ "executionPaths": [
32
+ "view.mjs"
33
+ ]
34
+ },
35
+ "script": {
36
+ "command": "node",
37
+ "args": [
38
+ "../view.mjs",
39
+ "why.md"
40
+ ]
41
+ }
42
+ }
43
+ }
44
+ },
45
+ "basis": true
46
+ }
package/package.json CHANGED
@@ -1,14 +1,28 @@
1
1
  {
2
2
  "name": "@ccdd/core",
3
- "version": "3.3.1",
3
+ "version": "4.0.0",
4
4
  "license": "MIT",
5
- "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" },
6
- "repository": { "type": "git", "url": "git+https://github.com/lhj6102/ccdd.git" },
5
+ "publishConfig": {
6
+ "access": "public",
7
+ "registry": "https://registry.npmjs.org/"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/lhj6102/ccdd.git"
12
+ },
7
13
  "description": "Artifact, Critic, relationship and tool definitions for CCDD",
8
14
  "type": "module",
9
15
  "types": "./dist/src/sdk.d.ts",
10
- "exports": { ".": { "types": "./dist/src/sdk.d.ts", "import": "./dist/src/sdk.js" } },
11
- "workspaces": ["packages/default-tools", "packages/project"],
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/src/sdk.d.ts",
19
+ "import": "./dist/src/sdk.js"
20
+ }
21
+ },
22
+ "workspaces": [
23
+ "packages/default-tools",
24
+ "packages/project"
25
+ ],
12
26
  "engines": {
13
27
  "node": "^22.19.0"
14
28
  },
@@ -27,13 +41,13 @@
27
41
  "release": "node scripts/local-release.mjs",
28
42
  "release:npm": "node scripts/local-release.mjs --npm",
29
43
  "release:npm:check": "node scripts/check-npm.mjs",
30
- "demo:prepare": "npm run build && node dist/src/cli.js prepare-demo",
31
- "demo": "npm run build && node dist/src/cli.js run --demo --copy --wait"
44
+ "demo:prepare": "npm run build && node dist/src/cli.js prepare-demo"
32
45
  },
33
46
  "files": [
34
47
  "dist/src/sdk.*",
35
48
  "dist/src/definitions.*",
36
49
  "dist/src/tools/contracts.*",
50
+ "dist/src/artifact-scope.*",
37
51
  "LICENSE",
38
52
  "README.md",
39
53
  "examples/"
@@ -1,60 +0,0 @@
1
- # Default image tool and Artifact groups
2
-
3
- The `effect` document and `preview` image are independent Artifacts. `explosion` is a group referencing both IDs, with no path or type. Tools for the document and image are explicitly registered. This example is a static sample, not an actual VFX asset.
4
-
5
- - `preview-review`: Evaluates one image. Only `view_image_preview` is supplied.
6
- - `explosion-review`: Evaluates the group. `read_effect` and `view_image_preview` are supplied. Tools are not duplicated when `preview` is both a member and a dependency.
7
- - `explosion-human`: Opens the group's document and image in desktop applications, then accepts a submitted verdict.
8
-
9
- In a full Run, both group Critics must wait for the image review to pass because of explicit `deps: ['preview']`. Membership alone does not require prior evaluation. Once both group Critics are GREEN, `explosion` is GREEN while `effect` remains unreviewed.
10
-
11
- ## Running the example
12
-
13
- Install the three v3.1.0 packages on Node 22 LTS (22.19.0 or later). The following command works after npm publication; before that, use the local source build below. Start in the CCDD source repository and copy the example into a new project outside it.
14
-
15
- ```sh
16
- CCDD_EXAMPLE_ROOT=$(mktemp -d /tmp/ccdd-groups.XXXXXX)
17
- cp -R examples/artifact-groups "$CCDD_EXAMPLE_ROOT/project"
18
- cd "$CCDD_EXAMPLE_ROOT/project"
19
- npm init -y
20
- npm pkg set type=module
21
- npm install --ignore-scripts @ccdd/core@3.1.0 @ccdd/project@3.1.0 @ccdd/default-tools@3.1.0
22
-
23
- # Check group member tool readiness without calling a Provider.
24
- npx ccdd tools check --artifact explosion --for agent
25
- # Select an individual Artifact for actual image reading.
26
- npx ccdd tools check --artifact preview --for agent --tool view_image --execute
27
-
28
- # Review one Critic; this legacy command skips waiting for prerequisite verdicts.
29
- npx ccdd run --copy --critic explosion-review --codex-auth-file "$HOME/.codex/auth.json" --wait
30
- ```
31
-
32
- Actual Agent review requires authentication and access to a model supporting image input. See the [reviewer guide](../../docs/reviewers.md) for authentication methods. Tool checks do not call a model. The `--execute` output above includes actual image blocks in base64.
33
-
34
- If core is already installed, change the first `cp` source to `node_modules/@ccdd/core/examples/artifact-groups`.
35
-
36
- Start a full Run with Human review by registering a local notification:
37
-
38
- ```sh
39
- npx ccdd run --copy --human-inbox --codex-auth-file "$HOME/.codex/auth.json"
40
- npx ccdd monitor
41
- ```
42
-
43
- Select a project and Run in the monitor, then click the group node in Graph to inspect its members. Claim the Human request, click `{explosion}`, execute each member's `open` tool, and submit a verdict with evidence. Default desktop opening targets macOS; explicitly register an executable on other operating systems.
44
-
45
- `view_image` reuses Pi `read` image results. It detects PNG/JPEG/WebP from file content, with a 4MiB limit. GIF, BMP, animated PNG, and text results fail; no automatic conversion or resizing occurs. When registered on a directory Artifact, pass an internal path such as `{"path":"frames/preview.png"}`.
46
-
47
- ## Using a local source build
48
-
49
- To test modified source, prepare three tarballs in the CCDD repository:
50
-
51
- ```sh
52
- npm ci
53
- npm run build
54
- CCDD_LOCAL_PACKAGES=$(mktemp -d /tmp/ccdd-group-packages.XXXXXX)
55
- npm pack --ignore-scripts --pack-destination "$CCDD_LOCAL_PACKAGES"
56
- npm pack --ignore-scripts --workspace @ccdd/project --pack-destination "$CCDD_LOCAL_PACKAGES"
57
- npm pack --ignore-scripts --workspace @ccdd/default-tools --pack-destination "$CCDD_LOCAL_PACKAGES"
58
- ```
59
-
60
- In the same shell, create the new example project from the steps above, then replace the npm version installation with `npm install --ignore-scripts "$CCDD_LOCAL_PACKAGES"/*.tgz`. Subsequent tool checks and review commands are the same. To also run the full test suite and separate installation checks on source fixed to a commit, use `--dry-run` with the [local Release command](../../docs/releases.md#releasing-a-specific-commit-locally).
@@ -1,37 +0,0 @@
1
- import { defineConfig } from '@ccdd/core';
2
- import { agent, human } from '@ccdd/default-tools';
3
-
4
- export default defineConfig({
5
- artifacts: {
6
- effect: { type: 'markdown', path: 'effect.md' },
7
- preview: { type: 'image', path: 'preview.png' },
8
- explosion: { kind: 'group', members: ['effect', 'preview'] },
9
- },
10
- artifactTypes: {
11
- markdown: {
12
- agentTools: { read: agent.text.read() },
13
- humanTools: { open: human.desktop.open() },
14
- },
15
- image: {
16
- agentTools: { view_image: agent.image.view() },
17
- humanTools: { open: human.desktop.open() },
18
- },
19
- },
20
- critics: [
21
- {
22
- id: 'preview-review', title: 'Image visibility', target: 'preview', deps: [],
23
- profile: { kind: 'agent', provider: 'openai-codex', model: 'gpt-6-astra', reasoning: 'medium' },
24
- payload: { instruction: 'Check whether {preview} has a bright center and an orange ring distinguishable from the dark background. Review the image itself; matching the effect specification is outside this review.' },
25
- },
26
- {
27
- id: 'explosion-review', title: 'Match the effect description and preview', target: 'explosion', deps: ['preview'],
28
- profile: { kind: 'agent', provider: 'openai-codex', model: 'gpt-6-astra', reasoning: 'medium' },
29
- payload: { instruction: 'Observe every member of {explosion} and evaluate whether {preview} matches the static appearance specified in {effect}. Animation timing and actual VFX runtime behavior are outside the scope of this static example.' },
30
- },
31
- {
32
- id: 'explosion-human', title: 'Review the group on the desktop', target: 'explosion', deps: ['preview'],
33
- profile: { kind: 'human' },
34
- payload: { instruction: 'Open the document and image in {explosion} with their desktop programs, compare them, and submit your verdict.' },
35
- },
36
- ],
37
- });
@@ -1,64 +0,0 @@
1
- import { readFile } from 'node:fs/promises';
2
- import { defineConfig, defineTool } from '@ccdd/core';
3
-
4
- // This factory defines a tool. It does not read the Artifact or execute an app.
5
- function customTextReader() {
6
- return defineTool({
7
- metadata: {
8
- description: 'Read the specified line range from {artifactName}.',
9
- inputSchema: {
10
- type: 'object',
11
- properties: {
12
- startLine: { type: 'integer', minimum: 1 },
13
- lineCount: { type: 'integer', minimum: 1, maximum: 80 },
14
- },
15
- required: ['startLine', 'lineCount'],
16
- additionalProperties: false,
17
- } as const,
18
- resultKinds: ['json'],
19
- observation: 'content',
20
- artifactKind: 'file',
21
- },
22
- async execute(context, args) {
23
- // Deliberately small teaching example: it accepts files up to 1 MiB.
24
- const file = await context.resolvePath();
25
- const bytes = await readFile(file, { signal: context.signal });
26
- if (bytes.length > 1024 * 1024) throw new Error('This example reader supports files up to 1 MiB.');
27
- const text = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(bytes);
28
- if (text.includes('\0')) throw new Error('This example reader accepts text, not binary data.');
29
- const lines = text.match(/[^\n]*\n|[^\n]+$/g) ?? [];
30
- const offset = args.startLine - 1;
31
- const selected = lines.slice(offset, offset + args.lineCount);
32
- const content = selected.join('');
33
- if (Buffer.byteLength(content) > 64 * 1024) throw new Error('Select a smaller line range.');
34
- const nextOffset = offset + selected.length;
35
- return {
36
- content: [{ type: 'json', data: {
37
- content,
38
- startLine: args.startLine,
39
- endLine: selected.length ? nextOffset : null,
40
- lineCount: selected.length,
41
- totalLines: lines.length,
42
- nextStartLine: nextOffset < lines.length ? nextOffset + 1 : null,
43
- } }],
44
- ...(selected.length ? { observation: { kind: 'content' as const } }
45
- : lines.length === 0 ? { observation: { kind: 'empty' as const } } : {}),
46
- };
47
- },
48
- });
49
- }
50
-
51
- export default defineConfig(() => ({
52
- artifactTypes: {
53
- document: { agentTools: { read: customTextReader() } },
54
- },
55
- artifacts: {
56
- why: { type: 'document', path: 'why.md', basis: true },
57
- spec: { type: 'document', path: 'spec.md' },
58
- },
59
- critics: [{
60
- id: 'spec-why', title: 'Does Spec match Why?', target: 'spec', deps: ['why'],
61
- profile: { kind: 'agent', provider: 'openai-codex', model: 'gpt-6-astra', reasoning: 'medium' },
62
- payload: { instruction: 'Read both documents and evaluate whether Spec satisfies the maximum task count in Why.' },
63
- }],
64
- }));