opencastle 0.31.7 → 0.32.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.
- package/README.md +4 -0
- package/bin/cli.mjs +15 -0
- package/dist/cli/agents.d.ts.map +1 -1
- package/dist/cli/agents.js +19 -5
- package/dist/cli/agents.js.map +1 -1
- package/dist/cli/artifacts-cli.d.ts +3 -0
- package/dist/cli/artifacts-cli.d.ts.map +1 -0
- package/dist/cli/artifacts-cli.js +36 -0
- package/dist/cli/artifacts-cli.js.map +1 -0
- package/dist/cli/baselines.d.ts.map +1 -1
- package/dist/cli/baselines.js +11 -0
- package/dist/cli/baselines.js.map +1 -1
- package/dist/cli/convoy/artifacts.d.ts +25 -0
- package/dist/cli/convoy/artifacts.d.ts.map +1 -0
- package/dist/cli/convoy/artifacts.js +129 -0
- package/dist/cli/convoy/artifacts.js.map +1 -0
- package/dist/cli/convoy/artifacts.test.d.ts +2 -0
- package/dist/cli/convoy/artifacts.test.d.ts.map +1 -0
- package/dist/cli/convoy/artifacts.test.js +169 -0
- package/dist/cli/convoy/artifacts.test.js.map +1 -0
- package/dist/cli/convoy/compaction.d.ts +23 -0
- package/dist/cli/convoy/compaction.d.ts.map +1 -0
- package/dist/cli/convoy/compaction.js +117 -0
- package/dist/cli/convoy/compaction.js.map +1 -0
- package/dist/cli/convoy/compaction.test.d.ts +2 -0
- package/dist/cli/convoy/compaction.test.d.ts.map +1 -0
- package/dist/cli/convoy/compaction.test.js +205 -0
- package/dist/cli/convoy/compaction.test.js.map +1 -0
- package/dist/cli/convoy/contracts.d.ts +22 -0
- package/dist/cli/convoy/contracts.d.ts.map +1 -0
- package/dist/cli/convoy/contracts.js +254 -0
- package/dist/cli/convoy/contracts.js.map +1 -0
- package/dist/cli/convoy/contracts.test.d.ts +2 -0
- package/dist/cli/convoy/contracts.test.d.ts.map +1 -0
- package/dist/cli/convoy/contracts.test.js +239 -0
- package/dist/cli/convoy/contracts.test.js.map +1 -0
- package/dist/cli/convoy/dag-analysis.d.ts +40 -0
- package/dist/cli/convoy/dag-analysis.d.ts.map +1 -0
- package/dist/cli/convoy/dag-analysis.js +282 -0
- package/dist/cli/convoy/dag-analysis.js.map +1 -0
- package/dist/cli/convoy/dag-analysis.test.d.ts +2 -0
- package/dist/cli/convoy/dag-analysis.test.d.ts.map +1 -0
- package/dist/cli/convoy/dag-analysis.test.js +289 -0
- package/dist/cli/convoy/dag-analysis.test.js.map +1 -0
- package/dist/cli/convoy/effort-scaling.d.ts +20 -0
- package/dist/cli/convoy/effort-scaling.d.ts.map +1 -0
- package/dist/cli/convoy/effort-scaling.js +82 -0
- package/dist/cli/convoy/effort-scaling.js.map +1 -0
- package/dist/cli/convoy/effort-scaling.test.d.ts +2 -0
- package/dist/cli/convoy/effort-scaling.test.d.ts.map +1 -0
- package/dist/cli/convoy/effort-scaling.test.js +120 -0
- package/dist/cli/convoy/effort-scaling.test.js.map +1 -0
- package/dist/cli/convoy/engine.d.ts.map +1 -1
- package/dist/cli/convoy/engine.js +280 -6
- package/dist/cli/convoy/engine.js.map +1 -1
- package/dist/cli/convoy/engine.test.js +155 -18
- package/dist/cli/convoy/engine.test.js.map +1 -1
- package/dist/cli/convoy/event-schemas.d.ts.map +1 -1
- package/dist/cli/convoy/event-schemas.js +55 -0
- package/dist/cli/convoy/event-schemas.js.map +1 -1
- package/dist/cli/convoy/isolation.d.ts +27 -0
- package/dist/cli/convoy/isolation.d.ts.map +1 -0
- package/dist/cli/convoy/isolation.js +120 -0
- package/dist/cli/convoy/isolation.js.map +1 -0
- package/dist/cli/convoy/isolation.test.d.ts +2 -0
- package/dist/cli/convoy/isolation.test.d.ts.map +1 -0
- package/dist/cli/convoy/isolation.test.js +105 -0
- package/dist/cli/convoy/isolation.test.js.map +1 -0
- package/dist/cli/convoy/review-stages.d.ts +9 -0
- package/dist/cli/convoy/review-stages.d.ts.map +1 -0
- package/dist/cli/convoy/review-stages.js +134 -0
- package/dist/cli/convoy/review-stages.js.map +1 -0
- package/dist/cli/convoy/review-stages.test.d.ts +2 -0
- package/dist/cli/convoy/review-stages.test.d.ts.map +1 -0
- package/dist/cli/convoy/review-stages.test.js +197 -0
- package/dist/cli/convoy/review-stages.test.js.map +1 -0
- package/dist/cli/convoy/skill-refinement.d.ts +39 -0
- package/dist/cli/convoy/skill-refinement.d.ts.map +1 -0
- package/dist/cli/convoy/skill-refinement.js +239 -0
- package/dist/cli/convoy/skill-refinement.js.map +1 -0
- package/dist/cli/convoy/skill-refinement.test.d.ts +2 -0
- package/dist/cli/convoy/skill-refinement.test.d.ts.map +1 -0
- package/dist/cli/convoy/skill-refinement.test.js +230 -0
- package/dist/cli/convoy/skill-refinement.test.js.map +1 -0
- package/dist/cli/convoy/spec-builder.d.ts +1 -0
- package/dist/cli/convoy/spec-builder.d.ts.map +1 -1
- package/dist/cli/convoy/spec-builder.js +11 -0
- package/dist/cli/convoy/spec-builder.js.map +1 -1
- package/dist/cli/convoy/spec-builder.test.js +54 -0
- package/dist/cli/convoy/spec-builder.test.js.map +1 -1
- package/dist/cli/convoy/store.d.ts +3 -2
- package/dist/cli/convoy/store.d.ts.map +1 -1
- package/dist/cli/convoy/store.js +20 -2
- package/dist/cli/convoy/store.js.map +1 -1
- package/dist/cli/convoy/store.test.js +15 -15
- package/dist/cli/convoy/store.test.js.map +1 -1
- package/dist/cli/convoy/tdd-gate.d.ts +15 -0
- package/dist/cli/convoy/tdd-gate.d.ts.map +1 -0
- package/dist/cli/convoy/tdd-gate.js +119 -0
- package/dist/cli/convoy/tdd-gate.js.map +1 -0
- package/dist/cli/convoy/tdd-gate.test.d.ts +2 -0
- package/dist/cli/convoy/tdd-gate.test.d.ts.map +1 -0
- package/dist/cli/convoy/tdd-gate.test.js +227 -0
- package/dist/cli/convoy/tdd-gate.test.js.map +1 -0
- package/dist/cli/convoy/types.d.ts +91 -0
- package/dist/cli/convoy/types.d.ts.map +1 -1
- package/dist/cli/convoy/types.js +8 -0
- package/dist/cli/convoy/types.js.map +1 -1
- package/dist/cli/insights.d.ts +3 -0
- package/dist/cli/insights.d.ts.map +1 -0
- package/dist/cli/insights.js +94 -0
- package/dist/cli/insights.js.map +1 -0
- package/dist/cli/lesson.d.ts.map +1 -1
- package/dist/cli/lesson.js +7 -0
- package/dist/cli/lesson.js.map +1 -1
- package/dist/cli/log.d.ts.map +1 -1
- package/dist/cli/log.js +7 -0
- package/dist/cli/log.js.map +1 -1
- package/dist/cli/package-config.d.ts +12 -0
- package/dist/cli/package-config.d.ts.map +1 -0
- package/dist/cli/package-config.js +37 -0
- package/dist/cli/package-config.js.map +1 -0
- package/dist/cli/package.d.ts +23 -0
- package/dist/cli/package.d.ts.map +1 -0
- package/dist/cli/package.js +285 -0
- package/dist/cli/package.js.map +1 -0
- package/dist/cli/package.test.d.ts +2 -0
- package/dist/cli/package.test.d.ts.map +1 -0
- package/dist/cli/package.test.js +236 -0
- package/dist/cli/package.test.js.map +1 -0
- package/dist/cli/pipeline.d.ts +6 -0
- package/dist/cli/pipeline.d.ts.map +1 -1
- package/dist/cli/pipeline.js +15 -2
- package/dist/cli/pipeline.js.map +1 -1
- package/dist/cli/run/schema.d.ts.map +1 -1
- package/dist/cli/run/schema.js +32 -0
- package/dist/cli/run/schema.js.map +1 -1
- package/dist/cli/run/schema.test.js +51 -0
- package/dist/cli/run/schema.test.js.map +1 -1
- package/dist/cli/skills.d.ts +3 -0
- package/dist/cli/skills.d.ts.map +1 -0
- package/dist/cli/skills.js +107 -0
- package/dist/cli/skills.js.map +1 -0
- package/dist/cli/types.d.ts +4 -1
- package/dist/cli/types.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/cli/agents.ts +20 -5
- package/src/cli/artifacts-cli.ts +41 -0
- package/src/cli/baselines.ts +12 -0
- package/src/cli/convoy/artifacts.test.ts +201 -0
- package/src/cli/convoy/artifacts.ts +186 -0
- package/src/cli/convoy/compaction.test.ts +245 -0
- package/src/cli/convoy/compaction.ts +164 -0
- package/src/cli/convoy/contracts.test.ts +279 -0
- package/src/cli/convoy/contracts.ts +280 -0
- package/src/cli/convoy/dag-analysis.test.ts +349 -0
- package/src/cli/convoy/dag-analysis.ts +371 -0
- package/src/cli/convoy/effort-scaling.test.ts +140 -0
- package/src/cli/convoy/effort-scaling.ts +90 -0
- package/src/cli/convoy/engine.test.ts +175 -18
- package/src/cli/convoy/engine.ts +301 -7
- package/src/cli/convoy/event-schemas.ts +55 -0
- package/src/cli/convoy/isolation.test.ts +137 -0
- package/src/cli/convoy/isolation.ts +165 -0
- package/src/cli/convoy/review-stages.test.ts +235 -0
- package/src/cli/convoy/review-stages.ts +166 -0
- package/src/cli/convoy/skill-refinement.test.ts +277 -0
- package/src/cli/convoy/skill-refinement.ts +306 -0
- package/src/cli/convoy/spec-builder.test.ts +61 -0
- package/src/cli/convoy/spec-builder.ts +9 -0
- package/src/cli/convoy/store.test.ts +15 -15
- package/src/cli/convoy/store.ts +26 -4
- package/src/cli/convoy/tdd-gate.test.ts +281 -0
- package/src/cli/convoy/tdd-gate.ts +154 -0
- package/src/cli/convoy/types.ts +51 -0
- package/src/cli/insights.ts +99 -0
- package/src/cli/lesson.ts +8 -0
- package/src/cli/log.ts +8 -0
- package/src/cli/package-config.ts +48 -0
- package/src/cli/package.test.ts +276 -0
- package/src/cli/package.ts +329 -0
- package/src/cli/pipeline.ts +21 -2
- package/src/cli/run/schema.test.ts +58 -0
- package/src/cli/run/schema.ts +33 -0
- package/src/cli/skills.ts +121 -0
- package/src/cli/types.ts +4 -1
- package/src/dashboard/node_modules/.vite/deps/_metadata.json +6 -6
- package/src/orchestrator/prompts/assess-complexity.prompt.md +13 -0
- package/src/orchestrator/prompts/generate-convoy.prompt.md +19 -0
package/README.md
CHANGED
|
@@ -82,6 +82,10 @@ MCP servers are auto-configured for your stack in each IDE's native format.
|
|
|
82
82
|
| `opencastle baselines` | Manage visual regression baselines |
|
|
83
83
|
| `opencastle log` | Append a structured event to the observability log |
|
|
84
84
|
| `opencastle lesson` | Append a structured lesson to LESSONS-LEARNED.md |
|
|
85
|
+
| `opencastle artifacts` | Manage filesystem artifact storage (prune old convoy artifacts) |
|
|
86
|
+
| `opencastle insights` | Analyze convoy execution history and generate recommendations |
|
|
87
|
+
| `opencastle skills` | Skill refinement and failure tracking |
|
|
88
|
+
| `opencastle package` | Package orchestrator as a plugin for IDE marketplaces |
|
|
85
89
|
|
|
86
90
|
Add `--dry-run` to any command to preview what it would change without writing files.
|
|
87
91
|
|
package/bin/cli.mjs
CHANGED
|
@@ -39,6 +39,8 @@ const HELP = `
|
|
|
39
39
|
baselines Manage visual regression baselines
|
|
40
40
|
log Append a structured event to the observability log
|
|
41
41
|
lesson Append a structured lesson to LESSONS-LEARNED.md
|
|
42
|
+
artifacts Manage filesystem artifact storage (prune old convoy artifacts)
|
|
43
|
+
insights Analyze convoy execution history and generate recommendations
|
|
42
44
|
|
|
43
45
|
Options:
|
|
44
46
|
--dry-run Preview what a command would change without writing files
|
|
@@ -59,6 +61,15 @@ if (command === '--version' || command === '-v') {
|
|
|
59
61
|
process.exit(0)
|
|
60
62
|
}
|
|
61
63
|
|
|
64
|
+
// Handle --version anywhere in args (e.g., "opencastle init --version")
|
|
65
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
66
|
+
const pkg = JSON.parse(
|
|
67
|
+
await readFile(resolve(pkgRoot, 'package.json'), 'utf8')
|
|
68
|
+
)
|
|
69
|
+
console.log(pkg.version)
|
|
70
|
+
process.exit(0)
|
|
71
|
+
}
|
|
72
|
+
|
|
62
73
|
const commands = {
|
|
63
74
|
init: () => import('../dist/cli/init.js'),
|
|
64
75
|
update: () => import('../dist/cli/update.js'),
|
|
@@ -75,6 +86,10 @@ const commands = {
|
|
|
75
86
|
dispute: () => import('../dist/cli/dispute.js'),
|
|
76
87
|
baselines: () => import('../dist/cli/baselines.js'),
|
|
77
88
|
validate: () => import('../dist/cli/validate.js'),
|
|
89
|
+
artifacts: () => import('../dist/cli/artifacts-cli.js'),
|
|
90
|
+
insights: () => import('../dist/cli/insights.js'),
|
|
91
|
+
skills: () => import('../dist/cli/skills.js'),
|
|
92
|
+
package: () => import('../dist/cli/package.js'),
|
|
78
93
|
}
|
|
79
94
|
|
|
80
95
|
if (!commands[command]) {
|
package/dist/cli/agents.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/cli/agents.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/cli/agents.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAgF5C,wBAA8B,MAAM,CAAC,EAAE,IAAI,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA6GxE"}
|
package/dist/cli/agents.js
CHANGED
|
@@ -15,6 +15,7 @@ const HELP = `
|
|
|
15
15
|
Options:
|
|
16
16
|
--older-than <days> Days threshold for compact subcommand
|
|
17
17
|
--yes, -y Skip confirmation prompt
|
|
18
|
+
--dry-run Preview what would be deleted without deleting
|
|
18
19
|
--help, -h Show this help
|
|
19
20
|
`;
|
|
20
21
|
function parseAgentsArgs(args) {
|
|
@@ -23,6 +24,7 @@ function parseAgentsArgs(args) {
|
|
|
23
24
|
agentName: null,
|
|
24
25
|
olderThan: null,
|
|
25
26
|
yes: false,
|
|
27
|
+
dryRun: false,
|
|
26
28
|
help: false,
|
|
27
29
|
};
|
|
28
30
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -47,6 +49,10 @@ function parseAgentsArgs(args) {
|
|
|
47
49
|
case '-y':
|
|
48
50
|
opts.yes = true;
|
|
49
51
|
break;
|
|
52
|
+
case '--dry-run':
|
|
53
|
+
case '--dryRun':
|
|
54
|
+
opts.dryRun = true;
|
|
55
|
+
break;
|
|
50
56
|
default:
|
|
51
57
|
if (arg.startsWith('--')) {
|
|
52
58
|
console.error(` \u2717 Unknown option: ${arg}`);
|
|
@@ -125,12 +131,16 @@ export default async function agents({ args }) {
|
|
|
125
131
|
console.error(' \u2717 purge requires an agent name: opencastle agents purge <agent>');
|
|
126
132
|
process.exit(1);
|
|
127
133
|
}
|
|
134
|
+
const existing = store.getAgentIdentities(opts.agentName, 1000);
|
|
135
|
+
if (existing.length === 0) {
|
|
136
|
+
console.log(` No identities found for agent "${opts.agentName}".`);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (opts.dryRun) {
|
|
140
|
+
console.log(` [dry-run] Would purge ${existing.length} identities for agent "${opts.agentName}"`);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
128
143
|
if (!opts.yes) {
|
|
129
|
-
const existing = store.getAgentIdentities(opts.agentName, 1000);
|
|
130
|
-
if (existing.length === 0) {
|
|
131
|
-
console.log(` No identities found for agent "${opts.agentName}".`);
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
144
|
console.log(`\n This will delete ${existing.length} identities for agent "${opts.agentName}".`);
|
|
135
145
|
console.log(` Use --yes or -y to confirm.`);
|
|
136
146
|
return;
|
|
@@ -144,6 +154,10 @@ export default async function agents({ args }) {
|
|
|
144
154
|
console.error(' \u2717 compact requires --older-than <days>');
|
|
145
155
|
process.exit(1);
|
|
146
156
|
}
|
|
157
|
+
if (opts.dryRun) {
|
|
158
|
+
console.log(` [dry-run] Would delete identities older than ${opts.olderThan} days`);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
147
161
|
const deleted = store.deleteAgentIdentitiesOlderThan(opts.olderThan);
|
|
148
162
|
console.log(` \u2713 Deleted ${deleted} identities older than ${opts.olderThan} days.`);
|
|
149
163
|
break;
|
package/dist/cli/agents.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/cli/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,OAAO,EAAE,CAAC,EAAE,MAAM,aAAa,CAAA;AAE/B,MAAM,IAAI,GAAG
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/cli/agents.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts-cli.d.ts","sourceRoot":"","sources":["../../src/cli/artifacts-cli.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAgB5C,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EAAE,IAAI,EAAE,EAAE,UAAU,GAAG,IAAI,CAuB/D"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { pruneArtifacts } from './convoy/artifacts.js';
|
|
2
|
+
const HELP = `
|
|
3
|
+
opencastle artifacts <subcommand> [options]
|
|
4
|
+
|
|
5
|
+
Manage filesystem artifact storage.
|
|
6
|
+
|
|
7
|
+
Subcommands:
|
|
8
|
+
prune Prune old convoy artifact directories
|
|
9
|
+
|
|
10
|
+
Options:
|
|
11
|
+
--keep <N> Number of recent artifacts to keep (default: 10)
|
|
12
|
+
--dry-run Preview what would be pruned without deleting
|
|
13
|
+
--help, -h Show this help
|
|
14
|
+
`;
|
|
15
|
+
export default function artifactsCli({ args }) {
|
|
16
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
17
|
+
console.log(HELP);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const dryRun = args.includes('--dry-run') || args.includes('--dryRun');
|
|
21
|
+
const subcommand = args.find(a => !a.startsWith('--'));
|
|
22
|
+
if (subcommand === 'prune') {
|
|
23
|
+
const keepIdx = args.indexOf('--keep');
|
|
24
|
+
const keepCount = keepIdx >= 0 && args[keepIdx + 1] ? parseInt(args[keepIdx + 1], 10) : 10;
|
|
25
|
+
if (dryRun) {
|
|
26
|
+
console.log(` [dry-run] Would prune convoy artifacts, keeping ${keepCount} most recent`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const result = pruneArtifacts(keepCount);
|
|
30
|
+
console.log(`Pruned ${result.removed} convoy artifact directories, freed ${(result.freed_bytes / 1024).toFixed(1)} KB`);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
console.log(HELP);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=artifacts-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts-cli.js","sourceRoot":"","sources":["../../src/cli/artifacts-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAGtD,MAAM,IAAI,GAAG;;;;;;;;;;;;CAYZ,CAAA;AAED,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EAAE,IAAI,EAAc;IACvD,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACjB,OAAM;IACR,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;IACtE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAA;IAEtD,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACtC,MAAM,SAAS,GAAG,OAAO,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAE1F,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,qDAAqD,SAAS,cAAc,CAAC,CAAA;YACzF,OAAM;QACR,CAAC;QAED,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;QACxC,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,OAAO,uCAAuC,CAAC,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IACzH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baselines.d.ts","sourceRoot":"","sources":["../../src/cli/baselines.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"baselines.d.ts","sourceRoot":"","sources":["../../src/cli/baselines.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAoF5C,wBAA8B,SAAS,CAAC,EAAE,IAAI,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAoE3E"}
|
package/dist/cli/baselines.js
CHANGED
|
@@ -14,6 +14,7 @@ const HELP = `
|
|
|
14
14
|
--slug <name> Baseline name (used as filename)
|
|
15
15
|
--from <file> Source PNG file path
|
|
16
16
|
--dir <path> Baselines directory (default: .opencastle/baselines)
|
|
17
|
+
--dry-run Preview what would be updated without writing
|
|
17
18
|
--help, -h Show this help
|
|
18
19
|
`;
|
|
19
20
|
function parseBaselinesArgs(args) {
|
|
@@ -22,6 +23,7 @@ function parseBaselinesArgs(args) {
|
|
|
22
23
|
slug: null,
|
|
23
24
|
from: null,
|
|
24
25
|
dir: '.opencastle/baselines',
|
|
26
|
+
dryRun: false,
|
|
25
27
|
help: false,
|
|
26
28
|
};
|
|
27
29
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -52,6 +54,10 @@ function parseBaselinesArgs(args) {
|
|
|
52
54
|
}
|
|
53
55
|
opts.dir = args[++i];
|
|
54
56
|
break;
|
|
57
|
+
case '--dry-run':
|
|
58
|
+
case '--dryRun':
|
|
59
|
+
opts.dryRun = true;
|
|
60
|
+
break;
|
|
55
61
|
default:
|
|
56
62
|
if (arg.startsWith('--')) {
|
|
57
63
|
console.error(` \u2717 Unknown option: ${arg}`);
|
|
@@ -95,6 +101,11 @@ export default async function baselines({ args }) {
|
|
|
95
101
|
console.error(' \u2717 Source file contains potential secrets \u2014 baseline not updated');
|
|
96
102
|
process.exit(1);
|
|
97
103
|
}
|
|
104
|
+
if (opts.dryRun) {
|
|
105
|
+
const dest = join(opts.dir, `${opts.slug}.png`);
|
|
106
|
+
console.log(` [dry-run] Would update baseline: ${dest}`);
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
98
109
|
mkdirSync(opts.dir, { recursive: true });
|
|
99
110
|
const dest = join(opts.dir, `${opts.slug}.png`);
|
|
100
111
|
writeFileSync(dest, data);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baselines.js","sourceRoot":"","sources":["../../src/cli/baselines.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACnG,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAE1C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAElD,MAAM,IAAI,GAAG
|
|
1
|
+
{"version":3,"file":"baselines.js","sourceRoot":"","sources":["../../src/cli/baselines.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface Artifact {
|
|
2
|
+
task_id: string;
|
|
3
|
+
convoy_id: string;
|
|
4
|
+
filename: string;
|
|
5
|
+
type: 'report' | 'code' | 'data' | 'diff' | 'log' | 'other';
|
|
6
|
+
size_bytes: number;
|
|
7
|
+
summary: string;
|
|
8
|
+
path: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ArtifactRef {
|
|
11
|
+
task_id: string;
|
|
12
|
+
filename: string;
|
|
13
|
+
summary: string;
|
|
14
|
+
path: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function getArtifactDir(convoyId: string, taskId: string): string;
|
|
17
|
+
export declare function writeArtifact(convoyId: string, taskId: string, filename: string, content: string, type: Artifact['type']): Artifact;
|
|
18
|
+
export declare function listArtifacts(convoyId: string, taskId: string): ArtifactRef[];
|
|
19
|
+
export declare function readArtifact(ref: ArtifactRef): string;
|
|
20
|
+
export declare function extractArtifactRefs(taskId: string, convoyId: string, output: string): ArtifactRef[];
|
|
21
|
+
export declare function pruneArtifacts(keepCount: number): {
|
|
22
|
+
removed: number;
|
|
23
|
+
freed_bytes: number;
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=artifacts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts.d.ts","sourceRoot":"","sources":["../../../src/cli/convoy/artifacts.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAA;IAC3D,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;CACb;AAoBD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAIvE;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,GACrB,QAAQ,CAgBV;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,CA6B7E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAErD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,CA2BnG;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CA4B1F"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync, } from 'node:fs';
|
|
2
|
+
import { basename, join } from 'node:path';
|
|
3
|
+
// ── Sanitization ──────────────────────────────────────────────────────────────
|
|
4
|
+
function sanitizeSegment(input) {
|
|
5
|
+
if (input.includes('..') || input.includes('/') || input.includes('\\')) {
|
|
6
|
+
throw new Error(`Invalid path segment "${input}": path traversal characters not allowed`);
|
|
7
|
+
}
|
|
8
|
+
return input.replace(/[^a-zA-Z0-9\-_.]/g, '');
|
|
9
|
+
}
|
|
10
|
+
// ── Core ──────────────────────────────────────────────────────────────────────
|
|
11
|
+
export function getArtifactDir(convoyId, taskId) {
|
|
12
|
+
const safeConvoyId = sanitizeSegment(convoyId);
|
|
13
|
+
const safeTaskId = sanitizeSegment(taskId);
|
|
14
|
+
return join(process.cwd(), '.opencastle', 'artifacts', safeConvoyId, safeTaskId) + '/';
|
|
15
|
+
}
|
|
16
|
+
export function writeArtifact(convoyId, taskId, filename, content, type) {
|
|
17
|
+
const safeFilename = sanitizeSegment(filename);
|
|
18
|
+
const dir = getArtifactDir(convoyId, taskId);
|
|
19
|
+
mkdirSync(dir, { recursive: true });
|
|
20
|
+
const filePath = join(dir, safeFilename);
|
|
21
|
+
writeFileSync(filePath, content, 'utf8');
|
|
22
|
+
const size_bytes = Buffer.byteLength(content, 'utf8');
|
|
23
|
+
const firstLine = content.split('\n')[0] ?? '';
|
|
24
|
+
const summary = firstLine.slice(0, 120);
|
|
25
|
+
const meta = { type, summary, size_bytes, created_at: new Date().toISOString() };
|
|
26
|
+
writeFileSync(join(dir, safeFilename + '.meta.json'), JSON.stringify(meta, null, 2), 'utf8');
|
|
27
|
+
return { task_id: taskId, convoy_id: convoyId, filename: safeFilename, type, size_bytes, summary, path: filePath };
|
|
28
|
+
}
|
|
29
|
+
export function listArtifacts(convoyId, taskId) {
|
|
30
|
+
const dir = getArtifactDir(convoyId, taskId);
|
|
31
|
+
if (!existsSync(dir))
|
|
32
|
+
return [];
|
|
33
|
+
const refs = [];
|
|
34
|
+
for (const entry of readdirSync(dir)) {
|
|
35
|
+
if (entry.endsWith('.meta.json'))
|
|
36
|
+
continue;
|
|
37
|
+
const filePath = join(dir, entry);
|
|
38
|
+
const metaPath = join(dir, entry + '.meta.json');
|
|
39
|
+
let summary = '';
|
|
40
|
+
if (existsSync(metaPath)) {
|
|
41
|
+
try {
|
|
42
|
+
const meta = JSON.parse(readFileSync(metaPath, 'utf8'));
|
|
43
|
+
summary = meta.summary;
|
|
44
|
+
}
|
|
45
|
+
catch { /* fallback */ }
|
|
46
|
+
}
|
|
47
|
+
if (!summary) {
|
|
48
|
+
try {
|
|
49
|
+
const firstLine = readFileSync(filePath, 'utf8').split('\n')[0] ?? '';
|
|
50
|
+
summary = firstLine.slice(0, 120);
|
|
51
|
+
}
|
|
52
|
+
catch { /* non-critical */ }
|
|
53
|
+
}
|
|
54
|
+
refs.push({ task_id: taskId, filename: entry, summary, path: filePath });
|
|
55
|
+
}
|
|
56
|
+
return refs;
|
|
57
|
+
}
|
|
58
|
+
export function readArtifact(ref) {
|
|
59
|
+
return readFileSync(ref.path, 'utf8');
|
|
60
|
+
}
|
|
61
|
+
export function extractArtifactRefs(taskId, convoyId, output) {
|
|
62
|
+
const pattern = /\[ARTIFACT:\s*([^\]]+)\]\s*(.+)/g;
|
|
63
|
+
const refs = [];
|
|
64
|
+
let match;
|
|
65
|
+
while ((match = pattern.exec(output)) !== null) {
|
|
66
|
+
// Use basename to prevent path traversal from untrusted agent output
|
|
67
|
+
const filename = basename(match[1].trim());
|
|
68
|
+
const summary = match[2].trim();
|
|
69
|
+
if (!filename || filename === '..') {
|
|
70
|
+
process.stderr.write('[artifacts] Warning: invalid artifact filename from agent output\n');
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const dir = getArtifactDir(convoyId, taskId);
|
|
74
|
+
const filePath = join(dir, filename);
|
|
75
|
+
if (!existsSync(filePath)) {
|
|
76
|
+
process.stderr.write(`[artifacts] Warning: referenced artifact not found: ${filePath}\n`);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
refs.push({ task_id: taskId, filename, summary, path: filePath });
|
|
80
|
+
}
|
|
81
|
+
return refs;
|
|
82
|
+
}
|
|
83
|
+
export function pruneArtifacts(keepCount) {
|
|
84
|
+
const artifactsRoot = join(process.cwd(), '.opencastle', 'artifacts');
|
|
85
|
+
if (!existsSync(artifactsRoot))
|
|
86
|
+
return { removed: 0, freed_bytes: 0 };
|
|
87
|
+
const convoyDirs = readdirSync(artifactsRoot)
|
|
88
|
+
.map(name => {
|
|
89
|
+
const dirPath = join(artifactsRoot, name);
|
|
90
|
+
try {
|
|
91
|
+
return { name, path: dirPath, mtime: statSync(dirPath).mtime.getTime() };
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return { name, path: dirPath, mtime: 0 };
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
98
|
+
const toRemove = convoyDirs.slice(keepCount);
|
|
99
|
+
let removed = 0;
|
|
100
|
+
let freed_bytes = 0;
|
|
101
|
+
for (const dir of toRemove) {
|
|
102
|
+
try {
|
|
103
|
+
freed_bytes += calcDirSize(dir.path);
|
|
104
|
+
rmSync(dir.path, { recursive: true, force: true });
|
|
105
|
+
removed++;
|
|
106
|
+
}
|
|
107
|
+
catch { /* non-critical */ }
|
|
108
|
+
}
|
|
109
|
+
return { removed, freed_bytes };
|
|
110
|
+
}
|
|
111
|
+
function calcDirSize(dirPath) {
|
|
112
|
+
let total = 0;
|
|
113
|
+
try {
|
|
114
|
+
for (const entry of readdirSync(dirPath)) {
|
|
115
|
+
const p = join(dirPath, entry);
|
|
116
|
+
try {
|
|
117
|
+
const s = statSync(p);
|
|
118
|
+
if (s.isDirectory())
|
|
119
|
+
total += calcDirSize(p);
|
|
120
|
+
else
|
|
121
|
+
total += s.size;
|
|
122
|
+
}
|
|
123
|
+
catch { /* skip */ }
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch { /* skip */ }
|
|
127
|
+
return total;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../../src/cli/convoy/artifacts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts.test.d.ts","sourceRoot":"","sources":["../../../src/cli/convoy/artifacts.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { mkdtempSync, rmSync, existsSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { getArtifactDir, writeArtifact, listArtifacts, readArtifact, extractArtifactRefs, pruneArtifacts, } from './artifacts.js';
|
|
6
|
+
describe('artifacts', () => {
|
|
7
|
+
let tmpDir;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
tmpDir = mkdtempSync(join(tmpdir(), 'artifacts-test-'));
|
|
10
|
+
vi.spyOn(process, 'cwd').mockReturnValue(tmpDir);
|
|
11
|
+
});
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
vi.restoreAllMocks();
|
|
14
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
15
|
+
});
|
|
16
|
+
describe('writeArtifact', () => {
|
|
17
|
+
it('creates file in correct directory structure', () => {
|
|
18
|
+
const artifact = writeArtifact('convoy-1', 'task-1', 'report.md', '# Report\nContent here', 'report');
|
|
19
|
+
expect(artifact.path).toContain('convoy-1');
|
|
20
|
+
expect(artifact.path).toContain('task-1');
|
|
21
|
+
expect(artifact.path).toContain('report.md');
|
|
22
|
+
expect(existsSync(artifact.path)).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
it('creates .meta.json sidecar', () => {
|
|
25
|
+
const artifact = writeArtifact('convoy-1', 'task-1', 'report.md', '# Report\nContent here', 'report');
|
|
26
|
+
const metaPath = artifact.path + '.meta.json';
|
|
27
|
+
expect(existsSync(metaPath)).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
it('returns Artifact with correct metadata', () => {
|
|
30
|
+
const content = '# Report\nLine 2';
|
|
31
|
+
const artifact = writeArtifact('convoy-1', 'task-1', 'report.md', content, 'report');
|
|
32
|
+
expect(artifact.task_id).toBe('task-1');
|
|
33
|
+
expect(artifact.convoy_id).toBe('convoy-1');
|
|
34
|
+
expect(artifact.filename).toBe('report.md');
|
|
35
|
+
expect(artifact.type).toBe('report');
|
|
36
|
+
expect(artifact.size_bytes).toBe(Buffer.byteLength(content, 'utf8'));
|
|
37
|
+
expect(artifact.summary).toBe('# Report');
|
|
38
|
+
});
|
|
39
|
+
it('summary is truncated to 120 chars when first line is long', () => {
|
|
40
|
+
const longFirstLine = 'A'.repeat(200);
|
|
41
|
+
const content = longFirstLine + '\nSecond line';
|
|
42
|
+
const artifact = writeArtifact('convoy-1', 'task-1', 'long.md', content, 'report');
|
|
43
|
+
expect(artifact.summary.length).toBe(120);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
describe('listArtifacts', () => {
|
|
47
|
+
it('returns refs for all files in task dir excluding .meta.json', () => {
|
|
48
|
+
writeArtifact('convoy-1', 'task-1', 'report.md', '# Report', 'report');
|
|
49
|
+
writeArtifact('convoy-1', 'task-1', 'migration.sql', 'ALTER TABLE users', 'code');
|
|
50
|
+
const refs = listArtifacts('convoy-1', 'task-1');
|
|
51
|
+
expect(refs).toHaveLength(2);
|
|
52
|
+
const filenames = refs.map(r => r.filename);
|
|
53
|
+
expect(filenames).toContain('report.md');
|
|
54
|
+
expect(filenames).toContain('migration.sql');
|
|
55
|
+
});
|
|
56
|
+
it('returns empty array when dir does not exist', () => {
|
|
57
|
+
const refs = listArtifacts('nonexistent-convoy', 'nonexistent-task');
|
|
58
|
+
expect(refs).toHaveLength(0);
|
|
59
|
+
});
|
|
60
|
+
it('populates summary from .meta.json sidecar', () => {
|
|
61
|
+
writeArtifact('convoy-1', 'task-1', 'diff.patch', 'diff --git a/file.ts\nchanges here', 'diff');
|
|
62
|
+
const refs = listArtifacts('convoy-1', 'task-1');
|
|
63
|
+
expect(refs[0].summary).toBe('diff --git a/file.ts');
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('readArtifact', () => {
|
|
67
|
+
it('returns file content', () => {
|
|
68
|
+
const content = '# Report\nDetailed content here';
|
|
69
|
+
const artifact = writeArtifact('convoy-1', 'task-1', 'report.md', content, 'report');
|
|
70
|
+
const ref = { task_id: 'task-1', filename: 'report.md', summary: '# Report', path: artifact.path };
|
|
71
|
+
expect(readArtifact(ref)).toBe(content);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
describe('extractArtifactRefs', () => {
|
|
75
|
+
it('parses [ARTIFACT: filename] summary pattern correctly', () => {
|
|
76
|
+
writeArtifact('convoy-1', 'task-1', 'report.md', '# Report', 'report');
|
|
77
|
+
const output = 'I completed the work.\n[ARTIFACT: report.md] Full analysis report\nSee the artifact for details.';
|
|
78
|
+
const refs = extractArtifactRefs('task-1', 'convoy-1', output);
|
|
79
|
+
expect(refs).toHaveLength(1);
|
|
80
|
+
expect(refs[0].filename).toBe('report.md');
|
|
81
|
+
expect(refs[0].summary).toBe('Full analysis report');
|
|
82
|
+
});
|
|
83
|
+
it('parses multiple artifacts in one output', () => {
|
|
84
|
+
writeArtifact('convoy-1', 'task-1', 'report.md', '# Report', 'report');
|
|
85
|
+
writeArtifact('convoy-1', 'task-1', 'migration.sql', 'ALTER TABLE', 'code');
|
|
86
|
+
const output = '[ARTIFACT: report.md] Analysis report\n[ARTIFACT: migration.sql] Database migration script';
|
|
87
|
+
const refs = extractArtifactRefs('task-1', 'convoy-1', output);
|
|
88
|
+
expect(refs).toHaveLength(2);
|
|
89
|
+
});
|
|
90
|
+
it('logs warning to stderr for referenced but missing artifacts', () => {
|
|
91
|
+
const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
92
|
+
const output = '[ARTIFACT: missing.md] A report that does not exist on disk';
|
|
93
|
+
const refs = extractArtifactRefs('task-1', 'convoy-1', output);
|
|
94
|
+
expect(refs).toHaveLength(0);
|
|
95
|
+
expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining('[artifacts] Warning'));
|
|
96
|
+
});
|
|
97
|
+
it('returns empty array when no artifact patterns found', () => {
|
|
98
|
+
const refs = extractArtifactRefs('task-1', 'convoy-1', 'No artifacts here, just a normal response.');
|
|
99
|
+
expect(refs).toHaveLength(0);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
describe('pruneArtifacts', () => {
|
|
103
|
+
it('removes convoy dirs beyond keepCount', () => {
|
|
104
|
+
writeArtifact('convoy-a', 'task-1', 'file.md', 'content', 'report');
|
|
105
|
+
writeArtifact('convoy-b', 'task-1', 'file.md', 'content', 'report');
|
|
106
|
+
writeArtifact('convoy-c', 'task-1', 'file.md', 'content', 'report');
|
|
107
|
+
const result = pruneArtifacts(1);
|
|
108
|
+
expect(result.removed).toBe(2);
|
|
109
|
+
expect(result.freed_bytes).toBeGreaterThan(0);
|
|
110
|
+
});
|
|
111
|
+
it('returns zero removed when within keepCount', () => {
|
|
112
|
+
writeArtifact('convoy-1', 'task-1', 'file.md', 'content', 'report');
|
|
113
|
+
writeArtifact('convoy-2', 'task-1', 'file.md', 'content', 'report');
|
|
114
|
+
const result = pruneArtifacts(5);
|
|
115
|
+
expect(result.removed).toBe(0);
|
|
116
|
+
expect(result.freed_bytes).toBe(0);
|
|
117
|
+
});
|
|
118
|
+
it('returns zero when no artifacts directory exists', () => {
|
|
119
|
+
const result = pruneArtifacts(10);
|
|
120
|
+
expect(result.removed).toBe(0);
|
|
121
|
+
expect(result.freed_bytes).toBe(0);
|
|
122
|
+
});
|
|
123
|
+
it('returns correct freed bytes count', () => {
|
|
124
|
+
const content = 'A'.repeat(1000);
|
|
125
|
+
writeArtifact('convoy-old1', 'task-1', 'large.md', content, 'report');
|
|
126
|
+
writeArtifact('convoy-old2', 'task-1', 'large.md', content, 'report');
|
|
127
|
+
writeArtifact('convoy-new', 'task-1', 'large.md', content, 'report');
|
|
128
|
+
const result = pruneArtifacts(1);
|
|
129
|
+
expect(result.removed).toBe(2);
|
|
130
|
+
expect(result.freed_bytes).toBeGreaterThan(0);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
describe('round-trip', () => {
|
|
134
|
+
it('write → list → read produces identical content', () => {
|
|
135
|
+
const content = '# Report\nLine 2\nLine 3';
|
|
136
|
+
writeArtifact('convoy-1', 'task-1', 'report.md', content, 'report');
|
|
137
|
+
const refs = listArtifacts('convoy-1', 'task-1');
|
|
138
|
+
expect(refs).toHaveLength(1);
|
|
139
|
+
const retrieved = readArtifact(refs[0]);
|
|
140
|
+
expect(retrieved).toBe(content);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
describe('path sanitization', () => {
|
|
144
|
+
it('rejects filenames with ..', () => {
|
|
145
|
+
expect(() => writeArtifact('convoy-1', 'task-1', '../evil.ts', 'content', 'code')).toThrow();
|
|
146
|
+
});
|
|
147
|
+
it('rejects filenames with /', () => {
|
|
148
|
+
expect(() => writeArtifact('convoy-1', 'task-1', 'sub/evil.ts', 'content', 'code')).toThrow();
|
|
149
|
+
});
|
|
150
|
+
it('rejects convoy IDs with path traversal', () => {
|
|
151
|
+
expect(() => writeArtifact('../evil', 'task-1', 'file.md', 'content', 'report')).toThrow();
|
|
152
|
+
});
|
|
153
|
+
it('rejects task IDs with backslash', () => {
|
|
154
|
+
expect(() => writeArtifact('convoy-1', 'task\\evil', 'file.md', 'content', 'report')).toThrow();
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
describe('getArtifactDir', () => {
|
|
158
|
+
it('returns path ending with trailing slash', () => {
|
|
159
|
+
const dir = getArtifactDir('convoy-1', 'task-1');
|
|
160
|
+
expect(dir.endsWith('/')).toBe(true);
|
|
161
|
+
});
|
|
162
|
+
it('includes convoy-id and task-id in path', () => {
|
|
163
|
+
const dir = getArtifactDir('convoy-abc', 'task-xyz');
|
|
164
|
+
expect(dir).toContain('convoy-abc');
|
|
165
|
+
expect(dir).toContain('task-xyz');
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
//# sourceMappingURL=artifacts.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts.test.js","sourceRoot":"","sources":["../../../src/cli/convoy/artifacts.test.ts"],"names":[],"mappings":"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"}
|