@dzhechkov/harness-core 0.2.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.
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Dynamic workflow templates for Opus 4.8+ orchestration.
3
+ *
4
+ * Per ADR-005: workflows live in the orchestration layer only.
5
+ * They generate JS scripts that Claude Code's dynamic workflow engine executes.
6
+ * Core schema, adapters, and skill content remain model-agnostic.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+
11
+ /** A workflow template — generates a JS orchestration script from parameters. */
12
+ export interface WorkflowTemplate {
13
+ readonly name: string;
14
+ readonly description: string;
15
+ readonly generate: (options: WorkflowOptions) => string;
16
+ }
17
+
18
+ /** Options passed to workflow generation. */
19
+ export interface WorkflowOptions {
20
+ readonly projectRoot: string;
21
+ readonly dryRun?: boolean;
22
+ readonly packages?: readonly string[];
23
+ }
24
+
25
+ const coverageLift: WorkflowTemplate = {
26
+ name: 'coverage-lift',
27
+ description: 'Lift Tier-A package coverage to ≥95% using parallel agents per package.',
28
+ generate: (opts) => `
29
+ // Dynamic Workflow: Coverage Lift
30
+ // Generated for: ${opts.projectRoot}
31
+ // Per ADR-005: orchestration only — no adapter/core changes
32
+
33
+ const tierA = ${JSON.stringify(opts.packages ?? [
34
+ 'core', 'memory', 'harness-core', 'harness-cli',
35
+ 'harness-presets', 'mcp-server-tools',
36
+ 'adapter-claude', 'adapter-codex', 'adapter-opencode', 'adapter-hermes',
37
+ 'skills-qe',
38
+ ])};
39
+
40
+ const tasks = tierA.map(pkg => ({
41
+ name: \`coverage-\${pkg}\`,
42
+ description: \`Lift @dzhechkov/\${pkg} to ≥95% line coverage. Run: pnpm --filter @dzhechkov/\${pkg} test -- --coverage. Add tests for uncovered lines.\`,
43
+ }));
44
+
45
+ // Claude Code dynamic workflow engine will:
46
+ // 1. Spawn one agent per task (up to 16 concurrent)
47
+ // 2. Each agent reads coverage, writes tests, re-runs coverage
48
+ // 3. Results aggregated when all agents complete
49
+ export default { tasks, maxConcurrency: 4${opts.dryRun ? ', dryRun: true' : ''} };
50
+ `.trim(),
51
+ };
52
+
53
+ const mutationKill: WorkflowTemplate = {
54
+ name: 'mutation-kill',
55
+ description: 'Kill surviving mutants across core packages using parallel Stryker runs.',
56
+ generate: (opts) => `
57
+ // Dynamic Workflow: Mutation Kill
58
+ // Generated for: ${opts.projectRoot}
59
+
60
+ const packages = ${JSON.stringify(opts.packages ?? ['core', 'memory', 'harness-core'])};
61
+
62
+ const tasks = packages.map(pkg => ({
63
+ name: \`mutate-\${pkg}\`,
64
+ description: \`Run Stryker on @dzhechkov/\${pkg}, analyze survivors, write tests to kill them. Target: ≥80% mutation score.\`,
65
+ }));
66
+
67
+ export default { tasks, maxConcurrency: 3${opts.dryRun ? ', dryRun: true' : ''} };
68
+ `.trim(),
69
+ };
70
+
71
+ const canonicalize: WorkflowTemplate = {
72
+ name: 'canonicalize',
73
+ description: 'Canonicalize packages from vendored directories into @dzhechkov/* namespace.',
74
+ generate: (opts) => `
75
+ // Dynamic Workflow: Canonicalize
76
+ // Generated for: ${opts.projectRoot}
77
+
78
+ const tasks = [
79
+ { name: 'discover', description: 'Scan vendored directories for un-canonicalized packages.' },
80
+ { name: 'copy', description: 'Copy discovered packages to packages/@dzhechkov/. Exclude node_modules, .git, runtime state.' },
81
+ { name: 'metadata', description: 'Add publishConfig, repository, homepage to each package.json.' },
82
+ { name: 'verify', description: 'Run byte-level diff between source and canonical. 0 missing, 0 changed.' },
83
+ { name: 'test', description: 'Run canonical-packages structural tests. All must pass.' },
84
+ ];
85
+
86
+ export default { tasks, maxConcurrency: 2${opts.dryRun ? ', dryRun: true' : ''} };
87
+ `.trim(),
88
+ };
89
+
90
+ const securityAudit: WorkflowTemplate = {
91
+ name: 'security-audit',
92
+ description: 'Run adversarial security audit with parallel boundary scanning.',
93
+ generate: (opts) => `
94
+ // Dynamic Workflow: Security Audit
95
+ // Generated for: ${opts.projectRoot}
96
+
97
+ const tasks = [
98
+ { name: 'npm-audit', description: 'Run pnpm audit, capture baseline.' },
99
+ { name: 'gitleaks', description: 'Run gitleaks detect, document findings.' },
100
+ { name: 'boundaries', description: 'Verify all 8 input boundaries have runtime guards.' },
101
+ { name: 'payloads', description: 'Test aidefence payloads against boundaries.' },
102
+ { name: 'report', description: 'Generate security-audit.md with 6 H2 sections.' },
103
+ ];
104
+
105
+ export default { tasks, maxConcurrency: 3${opts.dryRun ? ', dryRun: true' : ''} };
106
+ `.trim(),
107
+ };
108
+
109
+ /** All registered workflow templates. */
110
+ export const WORKFLOWS: Record<string, WorkflowTemplate> = {
111
+ 'coverage-lift': coverageLift,
112
+ 'mutation-kill': mutationKill,
113
+ 'canonicalize': canonicalize,
114
+ 'security-audit': securityAudit,
115
+ };
116
+
117
+ /** Valid workflow names. */
118
+ export const WORKFLOW_NAMES = Object.keys(WORKFLOWS);
119
+
120
+ /** Look up a workflow by name. */
121
+ export function getWorkflow(name: string): WorkflowTemplate | undefined {
122
+ return WORKFLOWS[name];
123
+ }