@helmiq/crew 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/defaults/personas/architect.persona.yaml +72 -0
  2. package/defaults/personas/engineer.persona.yaml +137 -0
  3. package/defaults/personas/persona-spec.schema.yaml +149 -0
  4. package/defaults/personas/reviewer.persona.yaml +47 -0
  5. package/defaults/rubrics/adr.rubric.yaml +48 -0
  6. package/defaults/rubrics/code-review.rubric.yaml +39 -0
  7. package/defaults/rubrics/pull-request.rubric.yaml +40 -0
  8. package/dist/actions/actions.test.d.ts +2 -0
  9. package/dist/actions/actions.test.d.ts.map +1 -0
  10. package/dist/actions/actions.test.js +158 -0
  11. package/dist/actions/direct-dispatcher.d.ts +10 -0
  12. package/dist/actions/direct-dispatcher.d.ts.map +1 -0
  13. package/dist/actions/direct-dispatcher.js +27 -0
  14. package/dist/actions/dispatcher.d.ts +11 -0
  15. package/dist/actions/dispatcher.d.ts.map +1 -0
  16. package/dist/actions/dispatcher.js +1 -0
  17. package/dist/actions/index.d.ts +7 -0
  18. package/dist/actions/index.d.ts.map +1 -0
  19. package/dist/actions/index.js +3 -0
  20. package/dist/actions/registry.d.ts +13 -0
  21. package/dist/actions/registry.d.ts.map +1 -0
  22. package/dist/actions/registry.js +40 -0
  23. package/dist/actions/resolver.d.ts +47 -0
  24. package/dist/actions/resolver.d.ts.map +1 -0
  25. package/dist/actions/resolver.js +43 -0
  26. package/dist/cli/cli.test.d.ts +2 -0
  27. package/dist/cli/cli.test.d.ts.map +1 -0
  28. package/dist/cli/cli.test.js +392 -0
  29. package/dist/cli/run.d.ts +45 -0
  30. package/dist/cli/run.d.ts.map +1 -0
  31. package/dist/cli/run.js +236 -0
  32. package/dist/common/errors.d.ts +76 -0
  33. package/dist/common/errors.d.ts.map +1 -0
  34. package/dist/common/errors.js +74 -0
  35. package/dist/config/config.test.d.ts +2 -0
  36. package/dist/config/config.test.d.ts.map +1 -0
  37. package/dist/config/config.test.js +691 -0
  38. package/dist/config/index.d.ts +7 -0
  39. package/dist/config/index.d.ts.map +1 -0
  40. package/dist/config/index.js +4 -0
  41. package/dist/config/loader.d.ts +16 -0
  42. package/dist/config/loader.d.ts.map +1 -0
  43. package/dist/config/loader.js +56 -0
  44. package/dist/config/model-resolver.d.ts +24 -0
  45. package/dist/config/model-resolver.d.ts.map +1 -0
  46. package/dist/config/model-resolver.js +39 -0
  47. package/dist/config/resolver.d.ts +22 -0
  48. package/dist/config/resolver.d.ts.map +1 -0
  49. package/dist/config/resolver.js +115 -0
  50. package/dist/config/schemas.d.ts +266 -0
  51. package/dist/config/schemas.d.ts.map +1 -0
  52. package/dist/config/schemas.js +115 -0
  53. package/dist/context/artifact-reader.d.ts +12 -0
  54. package/dist/context/artifact-reader.d.ts.map +1 -0
  55. package/dist/context/artifact-reader.js +92 -0
  56. package/dist/context/assembler.d.ts +22 -0
  57. package/dist/context/assembler.d.ts.map +1 -0
  58. package/dist/context/assembler.js +126 -0
  59. package/dist/context/code-reader.d.ts +14 -0
  60. package/dist/context/code-reader.d.ts.map +1 -0
  61. package/dist/context/code-reader.js +56 -0
  62. package/dist/context/context.test.d.ts +2 -0
  63. package/dist/context/context.test.d.ts.map +1 -0
  64. package/dist/context/context.test.js +260 -0
  65. package/dist/context/index.d.ts +9 -0
  66. package/dist/context/index.d.ts.map +1 -0
  67. package/dist/context/index.js +5 -0
  68. package/dist/context/section-extractor.d.ts +9 -0
  69. package/dist/context/section-extractor.d.ts.map +1 -0
  70. package/dist/context/section-extractor.js +32 -0
  71. package/dist/context/token-budget.d.ts +11 -0
  72. package/dist/context/token-budget.d.ts.map +1 -0
  73. package/dist/context/token-budget.js +22 -0
  74. package/dist/control/control.test.d.ts +2 -0
  75. package/dist/control/control.test.d.ts.map +1 -0
  76. package/dist/control/control.test.js +137 -0
  77. package/dist/control/id-generator.d.ts +12 -0
  78. package/dist/control/id-generator.d.ts.map +1 -0
  79. package/dist/control/id-generator.js +20 -0
  80. package/dist/control/index.d.ts +5 -0
  81. package/dist/control/index.d.ts.map +1 -0
  82. package/dist/control/index.js +3 -0
  83. package/dist/control/lock-manager.d.ts +13 -0
  84. package/dist/control/lock-manager.d.ts.map +1 -0
  85. package/dist/control/lock-manager.js +72 -0
  86. package/dist/control/run-state.d.ts +16 -0
  87. package/dist/control/run-state.d.ts.map +1 -0
  88. package/dist/control/run-state.js +55 -0
  89. package/dist/engine/composite.d.ts +34 -0
  90. package/dist/engine/composite.d.ts.map +1 -0
  91. package/dist/engine/composite.js +192 -0
  92. package/dist/engine/composite.test.d.ts +2 -0
  93. package/dist/engine/composite.test.d.ts.map +1 -0
  94. package/dist/engine/composite.test.js +1947 -0
  95. package/dist/engine/engine.test.d.ts +2 -0
  96. package/dist/engine/engine.test.d.ts.map +1 -0
  97. package/dist/engine/engine.test.js +334 -0
  98. package/dist/engine/index.d.ts +10 -0
  99. package/dist/engine/index.d.ts.map +1 -0
  100. package/dist/engine/index.js +5 -0
  101. package/dist/engine/llm-client.d.ts +27 -0
  102. package/dist/engine/llm-client.d.ts.map +1 -0
  103. package/dist/engine/llm-client.js +46 -0
  104. package/dist/engine/simple.d.ts +21 -0
  105. package/dist/engine/simple.d.ts.map +1 -0
  106. package/dist/engine/simple.js +59 -0
  107. package/dist/engine/tool-dispatch.d.ts +37 -0
  108. package/dist/engine/tool-dispatch.d.ts.map +1 -0
  109. package/dist/engine/tool-dispatch.js +146 -0
  110. package/dist/engine/tool-dispatch.test.d.ts +2 -0
  111. package/dist/engine/tool-dispatch.test.d.ts.map +1 -0
  112. package/dist/engine/tool-dispatch.test.js +348 -0
  113. package/dist/engine/tool-filter.d.ts +13 -0
  114. package/dist/engine/tool-filter.d.ts.map +1 -0
  115. package/dist/engine/tool-filter.js +25 -0
  116. package/dist/evaluation/evaluation.test.d.ts +2 -0
  117. package/dist/evaluation/evaluation.test.d.ts.map +1 -0
  118. package/dist/evaluation/evaluation.test.js +490 -0
  119. package/dist/evaluation/evaluator.d.ts +19 -0
  120. package/dist/evaluation/evaluator.d.ts.map +1 -0
  121. package/dist/evaluation/evaluator.js +78 -0
  122. package/dist/evaluation/index.d.ts +4 -0
  123. package/dist/evaluation/index.d.ts.map +1 -0
  124. package/dist/evaluation/index.js +2 -0
  125. package/dist/evaluation/scorer.d.ts +38 -0
  126. package/dist/evaluation/scorer.d.ts.map +1 -0
  127. package/dist/evaluation/scorer.js +94 -0
  128. package/dist/index.d.ts +47 -0
  129. package/dist/index.d.ts.map +1 -0
  130. package/dist/index.js +28 -0
  131. package/dist/providers/index.d.ts +2 -0
  132. package/dist/providers/index.d.ts.map +1 -0
  133. package/dist/providers/index.js +1 -0
  134. package/dist/providers/provider-factory.d.ts +11 -0
  135. package/dist/providers/provider-factory.d.ts.map +1 -0
  136. package/dist/providers/provider-factory.js +30 -0
  137. package/dist/publication/frontmatter.d.ts +21 -0
  138. package/dist/publication/frontmatter.d.ts.map +1 -0
  139. package/dist/publication/frontmatter.js +15 -0
  140. package/dist/publication/git-ops.d.ts +18 -0
  141. package/dist/publication/git-ops.d.ts.map +1 -0
  142. package/dist/publication/git-ops.js +74 -0
  143. package/dist/publication/index.d.ts +9 -0
  144. package/dist/publication/index.d.ts.map +1 -0
  145. package/dist/publication/index.js +5 -0
  146. package/dist/publication/provenance-writer.d.ts +27 -0
  147. package/dist/publication/provenance-writer.d.ts.map +1 -0
  148. package/dist/publication/provenance-writer.js +21 -0
  149. package/dist/publication/publication.test.d.ts +2 -0
  150. package/dist/publication/publication.test.d.ts.map +1 -0
  151. package/dist/publication/publication.test.js +235 -0
  152. package/dist/publication/publisher.d.ts +32 -0
  153. package/dist/publication/publisher.d.ts.map +1 -0
  154. package/dist/publication/publisher.js +113 -0
  155. package/dist/publication/secret-scanner.d.ts +6 -0
  156. package/dist/publication/secret-scanner.d.ts.map +1 -0
  157. package/dist/publication/secret-scanner.js +19 -0
  158. package/dist/tools/index.d.ts +4 -0
  159. package/dist/tools/index.d.ts.map +1 -0
  160. package/dist/tools/index.js +2 -0
  161. package/dist/tools/registry.d.ts +15 -0
  162. package/dist/tools/registry.d.ts.map +1 -0
  163. package/dist/tools/registry.js +288 -0
  164. package/dist/tools/registry.test.d.ts +2 -0
  165. package/dist/tools/registry.test.d.ts.map +1 -0
  166. package/dist/tools/registry.test.js +131 -0
  167. package/dist/tools/tool-groups.d.ts +20 -0
  168. package/dist/tools/tool-groups.d.ts.map +1 -0
  169. package/dist/tools/tool-groups.js +48 -0
  170. package/dist/tools/tool-groups.test.d.ts +2 -0
  171. package/dist/tools/tool-groups.test.d.ts.map +1 -0
  172. package/dist/tools/tool-groups.test.js +127 -0
  173. package/dist/types/artifact-store.d.ts +33 -0
  174. package/dist/types/artifact-store.d.ts.map +1 -0
  175. package/dist/types/artifact-store.js +9 -0
  176. package/dist/types/evaluation-rubric.d.ts +18 -0
  177. package/dist/types/evaluation-rubric.d.ts.map +1 -0
  178. package/dist/types/evaluation-rubric.js +1 -0
  179. package/dist/types/index.d.ts +10 -0
  180. package/dist/types/index.d.ts.map +1 -0
  181. package/dist/types/index.js +1 -0
  182. package/dist/types/llm-provider.d.ts +47 -0
  183. package/dist/types/llm-provider.d.ts.map +1 -0
  184. package/dist/types/llm-provider.js +8 -0
  185. package/dist/types/persona-spec.d.ts +79 -0
  186. package/dist/types/persona-spec.d.ts.map +1 -0
  187. package/dist/types/persona-spec.js +1 -0
  188. package/dist/types/project-config.d.ts +28 -0
  189. package/dist/types/project-config.d.ts.map +1 -0
  190. package/dist/types/project-config.js +1 -0
  191. package/dist/types/provenance.d.ts +67 -0
  192. package/dist/types/provenance.d.ts.map +1 -0
  193. package/dist/types/provenance.js +1 -0
  194. package/dist/types/run-state.d.ts +11 -0
  195. package/dist/types/run-state.d.ts.map +1 -0
  196. package/dist/types/run-state.js +1 -0
  197. package/dist/types/tool-runtime.d.ts +43 -0
  198. package/dist/types/tool-runtime.d.ts.map +1 -0
  199. package/dist/types/tool-runtime.js +30 -0
  200. package/dist/workspace/detect.d.ts +11 -0
  201. package/dist/workspace/detect.d.ts.map +1 -0
  202. package/dist/workspace/detect.js +28 -0
  203. package/dist/workspace/detect.test.d.ts +2 -0
  204. package/dist/workspace/detect.test.d.ts.map +1 -0
  205. package/dist/workspace/detect.test.js +53 -0
  206. package/dist/workspace/index.d.ts +2 -0
  207. package/dist/workspace/index.d.ts.map +1 -0
  208. package/dist/workspace/index.js +1 -0
  209. package/package.json +51 -0
@@ -0,0 +1,235 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { mkdtemp, readFile, mkdir } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+ import { execSync } from 'node:child_process';
6
+ import { parse as yamlParse } from 'yaml';
7
+ import { addFrontmatter, parseFrontmatter } from './frontmatter.js';
8
+ import { writeProvenance, writeManifest } from './provenance-writer.js';
9
+ import { scanForSecrets } from './secret-scanner.js';
10
+ import { SecretDetectedError } from '../common/errors.js';
11
+ import { publish } from './publisher.js';
12
+ function makeProvenance() {
13
+ return {
14
+ run_id: 'run-test-001',
15
+ persona: 'engineer',
16
+ task: 'implement-story',
17
+ versions: {
18
+ persona_spec_hash: 'sha256:abc',
19
+ prompt_hashes: { planner: 'sha256:def' },
20
+ model: 'claude-sonnet-4',
21
+ rubric_hash: 'sha256:ghi',
22
+ runtime_version: '0.0.0',
23
+ },
24
+ timestamp: new Date().toISOString(),
25
+ duration_ms: 5000,
26
+ trigger: 'manual',
27
+ inputs: {
28
+ artifacts_read: [{ type: 'requirements', path: 'work/TEST-01/requirements.md' }],
29
+ context_tokens: 1000,
30
+ },
31
+ outputs: { artifact_produced: { type: 'review', id: 'review-001' } },
32
+ evaluation: { self_eval_score: 8.5, self_eval_pass: true },
33
+ cost: { llm_calls: 3, total_tokens: 5000, estimated_cost_usd: 0.05 },
34
+ run_state: 'published',
35
+ };
36
+ }
37
+ function makeRunRecord() {
38
+ return {
39
+ run_id: 'run-test-001',
40
+ persona: 'engineer',
41
+ task: 'implement-story',
42
+ scope: 'TEST-01-001',
43
+ status: 'publishing',
44
+ started_at: new Date().toISOString(),
45
+ };
46
+ }
47
+ describe('T-01-006a: markdown artifact with frontmatter', () => {
48
+ it('adds YAML frontmatter to content', () => {
49
+ const result = addFrontmatter('# My Artifact\n\nContent here.', {
50
+ author: 'engineer',
51
+ run_id: 'run-test-001',
52
+ status: 'published',
53
+ timestamp: '2026-03-22T09:00:00Z',
54
+ eval_score: 8.5,
55
+ eval_pass: true,
56
+ });
57
+ expect(result).toContain('---');
58
+ expect(result).toContain('author: engineer');
59
+ expect(result).toContain('run_id: run-test-001');
60
+ expect(result).toContain('status: published');
61
+ expect(result).toContain('eval_score: 8.5');
62
+ expect(result).toContain('# My Artifact');
63
+ });
64
+ it('roundtrips through parse', () => {
65
+ const original = addFrontmatter('Body content', {
66
+ author: 'reviewer',
67
+ run_id: 'run-002',
68
+ status: 'awaiting_review',
69
+ timestamp: '2026-03-22T10:00:00Z',
70
+ });
71
+ const { content, data } = parseFrontmatter(original);
72
+ expect(content.trim()).toBe('Body content');
73
+ expect(data['author']).toBe('reviewer');
74
+ expect(data['status']).toBe('awaiting_review');
75
+ });
76
+ });
77
+ describe('T-01-006c: provenance record completeness', () => {
78
+ let runDir;
79
+ beforeEach(async () => {
80
+ runDir = await mkdtemp(join(tmpdir(), 'crew-prov-test-'));
81
+ });
82
+ it('writes provenance.yaml with all required fields', async () => {
83
+ const provenance = makeProvenance();
84
+ const path = await writeProvenance(runDir, provenance);
85
+ const raw = await readFile(path, 'utf-8');
86
+ const parsed = yamlParse(raw);
87
+ expect(parsed['run_id']).toBe('run-test-001');
88
+ expect(parsed['persona']).toBe('engineer');
89
+ expect(parsed['task']).toBe('implement-story');
90
+ expect(parsed['versions']).toBeDefined();
91
+ expect(parsed['inputs']).toBeDefined();
92
+ expect(parsed['outputs']).toBeDefined();
93
+ expect(parsed['evaluation']).toBeDefined();
94
+ expect(parsed['cost']).toBeDefined();
95
+ expect(parsed['run_state']).toBe('published');
96
+ });
97
+ });
98
+ describe('T-01-006d: run manifest cross-repo linkage', () => {
99
+ let runDir;
100
+ beforeEach(async () => {
101
+ runDir = await mkdtemp(join(tmpdir(), 'crew-manifest-test-'));
102
+ });
103
+ it('writes manifest.yaml linking workspace and target repos', async () => {
104
+ const path = await writeManifest(runDir, {
105
+ run_id: 'run-test-001',
106
+ artifacts_repo: {
107
+ commit_sha: 'abc123',
108
+ artifacts_referenced: [
109
+ { type: 'requirements', path: 'work/TEST-01/requirements.md', status: 'approved' },
110
+ ],
111
+ },
112
+ target_repo: {
113
+ branch: 'feat/TEST-01-001-implement',
114
+ commit_sha: 'def456',
115
+ },
116
+ story_id: 'TEST-01-001',
117
+ });
118
+ const raw = await readFile(path, 'utf-8');
119
+ const parsed = yamlParse(raw);
120
+ expect(parsed.manifest['run_id']).toBe('run-test-001');
121
+ expect(parsed.manifest['artifacts_repo']).toBeDefined();
122
+ expect(parsed.manifest['target_repo']).toBeDefined();
123
+ expect(parsed.manifest['story_id']).toBe('TEST-01-001');
124
+ });
125
+ });
126
+ describe('T-01-006e: rollback on publication failure', () => {
127
+ it('blocks publication when secrets are detected', () => {
128
+ expect(() => scanForSecrets('API key: sk-ant-abc123456789012345678901234567890', 'test.md')).toThrow(SecretDetectedError);
129
+ });
130
+ it('does not throw for clean content', () => {
131
+ expect(() => scanForSecrets('# Normal artifact\n\nNo secrets here.', 'test.md')).not.toThrow();
132
+ });
133
+ it('blocks publish when artifact contains secrets', async () => {
134
+ const tmpBase = await mkdtemp(join(tmpdir(), 'crew-secret-test-'));
135
+ const ws = join(tmpBase, 'ws');
136
+ await mkdir(ws, { recursive: true });
137
+ await expect(publish({
138
+ artifact: 'secret: sk-ant-abc123456789012345678901234567890',
139
+ artifactPath: 'bad.md',
140
+ metadata: {
141
+ author: 'engineer',
142
+ run_id: 'run-test-001',
143
+ status: 'published',
144
+ timestamp: new Date().toISOString(),
145
+ },
146
+ provenance: makeProvenance(),
147
+ config: {
148
+ project: { name: 'T', key: 'T' },
149
+ workspace: { path: ws, work: 'work/', runs: 'runs/' },
150
+ source: { repo: 'github:test/repo', path: ws },
151
+ llm: {
152
+ default_model: 'x',
153
+ providers: { a: { api_key_env: 'X', models: { x: 'x' } } },
154
+ },
155
+ },
156
+ runRecord: makeRunRecord(),
157
+ runDir: join(tmpBase, 'run'),
158
+ push: false,
159
+ })).rejects.toThrow(SecretDetectedError);
160
+ });
161
+ });
162
+ describe('T-01-006b: code artifact on branch (git integration)', () => {
163
+ let tmpBase;
164
+ let workspacePath;
165
+ let runDir;
166
+ function canRunGit() {
167
+ try {
168
+ execSync('git --version', { stdio: 'ignore' });
169
+ const testDir = join(tmpdir(), `crew-git-check-${Date.now()}`);
170
+ execSync(`mkdir -p ${testDir} && cd ${testDir} && git init`, { stdio: 'ignore' });
171
+ execSync(`rm -rf ${testDir}`, { stdio: 'ignore' });
172
+ return true;
173
+ }
174
+ catch {
175
+ return false;
176
+ }
177
+ }
178
+ beforeEach(async () => {
179
+ tmpBase = await mkdtemp(join(tmpdir(), 'crew-git-pub-'));
180
+ workspacePath = join(tmpBase, 'workspace');
181
+ runDir = join(tmpBase, 'runs', 'run-test-001');
182
+ await mkdir(workspacePath, { recursive: true });
183
+ await mkdir(runDir, { recursive: true });
184
+ if (canRunGit()) {
185
+ execSync('git init', { cwd: workspacePath, stdio: 'ignore' });
186
+ execSync('git config user.email "test@test.com"', { cwd: workspacePath, stdio: 'ignore' });
187
+ execSync('git config user.name "Test"', { cwd: workspacePath, stdio: 'ignore' });
188
+ execSync('git commit --allow-empty -m "init"', { cwd: workspacePath, stdio: 'ignore' });
189
+ }
190
+ });
191
+ it('publishes a workspace artifact and commits', async () => {
192
+ if (!canRunGit())
193
+ return;
194
+ const artifactDir = join(workspacePath, 'work', 'TEST-01');
195
+ await mkdir(artifactDir, { recursive: true });
196
+ const config = {
197
+ project: {
198
+ name: 'Test',
199
+ key: 'TEST',
200
+ },
201
+ workspace: { path: workspacePath, work: 'work/', runs: 'runs/' },
202
+ source: { repo: 'github:test/repo', path: workspacePath },
203
+ llm: {
204
+ default_model: 'claude-sonnet',
205
+ providers: {
206
+ anthropic: {
207
+ api_key_env: 'ANTHROPIC_API_KEY',
208
+ models: { 'claude-sonnet': 'claude-sonnet-4' },
209
+ },
210
+ },
211
+ },
212
+ };
213
+ const result = await publish({
214
+ artifact: '# Review\n\nLooks good.',
215
+ artifactPath: 'work/TEST-01/review.md',
216
+ metadata: {
217
+ author: 'engineer',
218
+ run_id: 'run-test-001',
219
+ status: 'published',
220
+ timestamp: new Date().toISOString(),
221
+ },
222
+ provenance: makeProvenance(),
223
+ config,
224
+ runRecord: makeRunRecord(),
225
+ runDir,
226
+ push: false,
227
+ });
228
+ expect(result.artifactPath).toContain('review.md');
229
+ expect(result.commitSha).toBeTruthy();
230
+ expect(result.provenancePath).toContain('provenance.yaml');
231
+ const written = await readFile(result.artifactPath, 'utf-8');
232
+ expect(written).toContain('author: engineer');
233
+ expect(written).toContain('# Review');
234
+ });
235
+ });
@@ -0,0 +1,32 @@
1
+ import type { Provenance, ProjectConfig, RunRecord } from '../types/index.js';
2
+ import type { ArtifactMetadata } from './frontmatter.js';
3
+ export interface PublicationOptions {
4
+ artifact: string;
5
+ artifactPath: string;
6
+ metadata: ArtifactMetadata;
7
+ provenance: Provenance;
8
+ config: ProjectConfig;
9
+ runRecord: RunRecord;
10
+ runDir: string;
11
+ push?: boolean;
12
+ targetRepoBranch?: string;
13
+ targetRepoFiles?: {
14
+ path: string;
15
+ content: string;
16
+ }[];
17
+ }
18
+ export interface PublicationResult {
19
+ artifactPath: string;
20
+ commitSha: string;
21
+ provenancePath: string;
22
+ manifestPath?: string;
23
+ }
24
+ /**
25
+ * Publish an artifact to the workspace repo (and optionally code to the target repo),
26
+ * record provenance, and produce a cross-repo manifest.
27
+ *
28
+ * Follows the ordered publication sequence with compensating rollback
29
+ * for local, unpushed state per ADR-0007.
30
+ */
31
+ export declare function publish(options: PublicationOptions): Promise<PublicationResult>;
32
+ //# sourceMappingURL=publisher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publisher.d.ts","sourceRoot":"","sources":["../../src/publication/publisher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAG9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAMzD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACvD;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID;;;;;;GAMG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAuIrF"}
@@ -0,0 +1,113 @@
1
+ import { writeFile, unlink, mkdir } from 'node:fs/promises';
2
+ import { join, relative } from 'node:path';
3
+ import { PublicationError } from '../common/errors.js';
4
+ import { addFrontmatter } from './frontmatter.js';
5
+ import { commitAndPush, resetLastCommit, createBranch } from './git-ops.js';
6
+ import { writeProvenance, writeManifest } from './provenance-writer.js';
7
+ import { scanForSecrets } from './secret-scanner.js';
8
+ /**
9
+ * Publish an artifact to the workspace repo (and optionally code to the target repo),
10
+ * record provenance, and produce a cross-repo manifest.
11
+ *
12
+ * Follows the ordered publication sequence with compensating rollback
13
+ * for local, unpushed state per ADR-0007.
14
+ */
15
+ export async function publish(options) {
16
+ const { artifact, artifactPath, metadata, provenance, config, runRecord, runDir, push = false, targetRepoBranch, targetRepoFiles, } = options;
17
+ const workspacePath = config.workspace.path;
18
+ const compensations = [];
19
+ scanForSecrets(artifact, artifactPath);
20
+ const fullArtifactPath = join(workspacePath, artifactPath);
21
+ try {
22
+ // Step 1: Write artifact with frontmatter
23
+ const artifactWithFrontmatter = addFrontmatter(artifact, metadata);
24
+ const dir = join(fullArtifactPath, '..');
25
+ await mkdir(dir, { recursive: true });
26
+ await writeFile(fullArtifactPath, artifactWithFrontmatter, 'utf-8');
27
+ compensations.push(async () => {
28
+ try {
29
+ await unlink(fullArtifactPath);
30
+ }
31
+ catch {
32
+ /* best-effort */
33
+ }
34
+ });
35
+ // Step 2: Commit to workspace repo
36
+ const relPath = relative(workspacePath, fullArtifactPath);
37
+ const workspaceCommitSha = await commitAndPush(workspacePath, [relPath], `publish: ${runRecord.persona}/${runRecord.task} [${runRecord.run_id}]`, false);
38
+ compensations.push(async () => {
39
+ await resetLastCommit(workspacePath);
40
+ });
41
+ // Step 3: Push workspace repo (if enabled)
42
+ if (push) {
43
+ await commitAndPush(workspacePath, [], '', true);
44
+ // After push: no automatic rollback for remote state
45
+ }
46
+ // Step 4-5: Target repo operations (code artifacts)
47
+ let targetCommitSha;
48
+ if (targetRepoBranch && targetRepoFiles && targetRepoFiles.length > 0) {
49
+ const targetPath = config.source.path;
50
+ for (const file of targetRepoFiles) {
51
+ scanForSecrets(file.content, file.path);
52
+ }
53
+ await createBranch(targetPath, targetRepoBranch);
54
+ for (const file of targetRepoFiles) {
55
+ const fullPath = join(targetPath, file.path);
56
+ const fileDir = join(fullPath, '..');
57
+ await mkdir(fileDir, { recursive: true });
58
+ await writeFile(fullPath, file.content, 'utf-8');
59
+ }
60
+ const filePaths = targetRepoFiles.map((f) => f.path);
61
+ targetCommitSha = await commitAndPush(targetPath, filePaths, `feat: ${runRecord.task} [${runRecord.run_id}]`, false);
62
+ compensations.push(async () => {
63
+ await resetLastCommit(targetPath);
64
+ });
65
+ if (push) {
66
+ await commitAndPush(targetPath, [], '', true, targetRepoBranch);
67
+ }
68
+ }
69
+ // Step 6: Write provenance
70
+ const provenancePath = await writeProvenance(runDir, provenance);
71
+ // Step 7: Write manifest (cross-repo linkage)
72
+ let manifestPath;
73
+ if (targetCommitSha) {
74
+ const manifestData = {
75
+ run_id: runRecord.run_id,
76
+ artifacts_repo: {
77
+ commit_sha: workspaceCommitSha,
78
+ artifacts_referenced: provenance.inputs.artifacts_read.map((a) => ({
79
+ type: a.type,
80
+ path: a.path,
81
+ status: a.status ?? 'unknown',
82
+ })),
83
+ },
84
+ target_repo: {
85
+ branch: targetRepoBranch,
86
+ commit_sha: targetCommitSha,
87
+ },
88
+ story_id: runRecord.scope,
89
+ };
90
+ manifestPath = await writeManifest(runDir, manifestData);
91
+ }
92
+ return {
93
+ artifactPath: fullArtifactPath,
94
+ commitSha: workspaceCommitSha,
95
+ provenancePath,
96
+ manifestPath,
97
+ };
98
+ }
99
+ catch (err) {
100
+ // Execute compensations in reverse order
101
+ for (let i = compensations.length - 1; i >= 0; i--) {
102
+ try {
103
+ await compensations[i]();
104
+ }
105
+ catch {
106
+ /* compensation best-effort */
107
+ }
108
+ }
109
+ if (err instanceof PublicationError)
110
+ throw err;
111
+ throw new PublicationError(`Publication failed: ${err instanceof Error ? err.message : String(err)}`, { cause: err, runId: runRecord.run_id, stage: 'publish' });
112
+ }
113
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Scan content for patterns that look like secrets.
3
+ * Throws SecretDetectedError if any match is found.
4
+ */
5
+ export declare function scanForSecrets(content: string, context: string): void;
6
+ //# sourceMappingURL=secret-scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-scanner.d.ts","sourceRoot":"","sources":["../../src/publication/secret-scanner.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAQrE"}
@@ -0,0 +1,19 @@
1
+ import { SecretDetectedError } from '../common/errors.js';
2
+ const SECRET_PATTERNS = [
3
+ /(?:sk-|sk_)[a-zA-Z0-9_-]{20,}/,
4
+ /(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{30,}/,
5
+ /(?:AKIA|ABIA|ACCA|ASIA)[A-Z0-9]{16}/,
6
+ /-----BEGIN (?:RSA |EC |DSA )?PRIVATE KEY-----/,
7
+ /(?:bearer|token|api[_-]?key|secret|password)\s*[:=]\s*['"]?[A-Za-z0-9_/+=-]{20,}/i,
8
+ ];
9
+ /**
10
+ * Scan content for patterns that look like secrets.
11
+ * Throws SecretDetectedError if any match is found.
12
+ */
13
+ export function scanForSecrets(content, context) {
14
+ for (const pattern of SECRET_PATTERNS) {
15
+ if (pattern.test(content)) {
16
+ throw new SecretDetectedError(`Potential secret detected in ${context}. Publication blocked. Pattern: ${pattern.source.slice(0, 30)}...`);
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,4 @@
1
+ export { createToolRegistry } from './registry.js';
2
+ export type { ToolRegistryOptions } from './registry.js';
3
+ export { TOOL_GROUPS, expandToolNames } from './tool-groups.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,YAAY,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { createToolRegistry } from './registry.js';
2
+ export { TOOL_GROUPS, expandToolNames } from './tool-groups.js';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * CrewTool registry -- maps logical tool names used in persona specs
3
+ * to executable CrewTool implementations backed by the tool packages.
4
+ *
5
+ * Each tool's `execute` function adapts the tool package's API,
6
+ * injecting ToolExecutionContext values (repo paths, protected paths, etc.)
7
+ * so the LLM only needs to provide the operation-specific parameters.
8
+ */
9
+ import type { CrewToolSet } from '../types/tool-runtime.js';
10
+ import type { ArtifactStore } from '../types/artifact-store.js';
11
+ export interface ToolRegistryOptions {
12
+ artifactStore?: ArtifactStore;
13
+ }
14
+ export declare function createToolRegistry(options?: ToolRegistryOptions): CrewToolSet;
15
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE,MAAM,WAAW,mBAAmB;IAClC,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,WAAW,CA0T7E"}