@jterrats/open-orchestra 0.5.7 → 1.0.2
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/AGENTS.md +9 -8
- package/CLAUDE.md +13 -11
- package/README.md +78 -11
- package/dist/assets/web-console.js +169 -32
- package/dist/automation-evidence.d.ts +23 -0
- package/dist/automation-evidence.js +97 -0
- package/dist/automation-evidence.js.map +1 -0
- package/dist/autonomous-run-store.js +3 -3
- package/dist/autonomous-run-store.js.map +1 -1
- package/dist/benchmark.d.ts +4 -1
- package/dist/benchmark.js +93 -4
- package/dist/benchmark.js.map +1 -1
- package/dist/cli.js +73 -2
- package/dist/cli.js.map +1 -1
- package/dist/collaboration-flows.js +3 -5
- package/dist/collaboration-flows.js.map +1 -1
- package/dist/collection-utils.d.ts +3 -0
- package/dist/collection-utils.js +10 -0
- package/dist/collection-utils.js.map +1 -0
- package/dist/command-manifest.d.ts +12 -1
- package/dist/command-manifest.js +213 -10
- package/dist/command-manifest.js.map +1 -1
- package/dist/commands.d.ts +10 -5
- package/dist/commands.js +16 -6
- package/dist/commands.js.map +1 -1
- package/dist/config-migrations.d.ts +24 -0
- package/dist/config-migrations.js +102 -0
- package/dist/config-migrations.js.map +1 -0
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +23 -0
- package/dist/constants.js.map +1 -1
- package/dist/dashboard-commands.d.ts +2 -0
- package/dist/dashboard-commands.js +14 -0
- package/dist/dashboard-commands.js.map +1 -0
- package/dist/defaults.d.ts +13 -0
- package/dist/defaults.js +13 -0
- package/dist/defaults.js.map +1 -1
- package/dist/delegation-decision.js +23 -8
- package/dist/delegation-decision.js.map +1 -1
- package/dist/delivery-commands.js +5 -0
- package/dist/delivery-commands.js.map +1 -1
- package/dist/delivery-dashboard-charts.d.ts +4 -0
- package/dist/delivery-dashboard-charts.js +156 -0
- package/dist/delivery-dashboard-charts.js.map +1 -0
- package/dist/delivery-dashboard-html.d.ts +2 -0
- package/dist/delivery-dashboard-html.js +115 -0
- package/dist/delivery-dashboard-html.js.map +1 -0
- package/dist/delivery-dashboard-types.d.ts +78 -0
- package/dist/delivery-dashboard-types.js +2 -0
- package/dist/delivery-dashboard-types.js.map +1 -0
- package/dist/delivery-dashboard.d.ts +8 -0
- package/dist/delivery-dashboard.js +124 -0
- package/dist/delivery-dashboard.js.map +1 -0
- package/dist/effort-classification.d.ts +7 -0
- package/dist/effort-classification.js +72 -0
- package/dist/effort-classification.js.map +1 -0
- package/dist/extension-commands.d.ts +3 -0
- package/dist/extension-commands.js +40 -0
- package/dist/extension-commands.js.map +1 -0
- package/dist/extensions.d.ts +22 -0
- package/dist/extensions.js +126 -0
- package/dist/extensions.js.map +1 -0
- package/dist/github.d.ts +2 -0
- package/dist/github.js +15 -3
- package/dist/github.js.map +1 -1
- package/dist/health-checks.js +51 -0
- package/dist/health-checks.js.map +1 -1
- package/dist/lucid-story-map.d.ts +73 -0
- package/dist/lucid-story-map.js +112 -0
- package/dist/lucid-story-map.js.map +1 -0
- package/dist/mcp-integrations.d.ts +19 -0
- package/dist/mcp-integrations.js +58 -0
- package/dist/mcp-integrations.js.map +1 -0
- package/dist/mcp-tool-adapter.d.ts +21 -0
- package/dist/mcp-tool-adapter.js +56 -0
- package/dist/mcp-tool-adapter.js.map +1 -0
- package/dist/memory.js +18 -8
- package/dist/memory.js.map +1 -1
- package/dist/metrics-commands.js +47 -13
- package/dist/metrics-commands.js.map +1 -1
- package/dist/model-commands.d.ts +5 -0
- package/dist/model-commands.js +101 -3
- package/dist/model-commands.js.map +1 -1
- package/dist/model-providers.js +13 -1
- package/dist/model-providers.js.map +1 -1
- package/dist/package-update-check.d.ts +18 -0
- package/dist/package-update-check.js +20 -0
- package/dist/package-update-check.js.map +1 -1
- package/dist/phase-executor.d.ts +1 -0
- package/dist/phase-executor.js +118 -14
- package/dist/phase-executor.js.map +1 -1
- package/dist/phase-playbooks.d.ts +15 -0
- package/dist/phase-playbooks.js +82 -0
- package/dist/phase-playbooks.js.map +1 -1
- package/dist/planning-commands.d.ts +1 -0
- package/dist/planning-commands.js +24 -1
- package/dist/planning-commands.js.map +1 -1
- package/dist/project-detection.js +9 -7
- package/dist/project-detection.js.map +1 -1
- package/dist/prompt-registry-update.d.ts +2 -0
- package/dist/prompt-registry-update.js +25 -1
- package/dist/prompt-registry-update.js.map +1 -1
- package/dist/prompt-registry-validation.js +39 -2
- package/dist/prompt-registry-validation.js.map +1 -1
- package/dist/qa-commands.d.ts +2 -0
- package/dist/qa-commands.js +18 -0
- package/dist/qa-commands.js.map +1 -0
- package/dist/qa-coverage.d.ts +24 -0
- package/dist/qa-coverage.js +198 -0
- package/dist/qa-coverage.js.map +1 -0
- package/dist/qa-readiness.d.ts +5 -0
- package/dist/qa-readiness.js +26 -0
- package/dist/qa-readiness.js.map +1 -0
- package/dist/refresh-generated.d.ts +10 -1
- package/dist/refresh-generated.js +83 -6
- package/dist/refresh-generated.js.map +1 -1
- package/dist/release-candidate.d.ts +9 -1
- package/dist/release-candidate.js +52 -1
- package/dist/release-candidate.js.map +1 -1
- package/dist/release-commands.js +202 -12
- package/dist/release-commands.js.map +1 -1
- package/dist/release-readiness.d.ts +36 -1
- package/dist/release-readiness.js +217 -6
- package/dist/release-readiness.js.map +1 -1
- package/dist/runtime-bootstrap.js +1 -1
- package/dist/runtime-bootstrap.js.map +1 -1
- package/dist/runtime-commands.d.ts +2 -0
- package/dist/runtime-commands.js +77 -0
- package/dist/runtime-commands.js.map +1 -1
- package/dist/runtime-execution-renderer.d.ts +3 -2
- package/dist/runtime-execution-renderer.js +19 -1
- package/dist/runtime-execution-renderer.js.map +1 -1
- package/dist/runtime-execution.d.ts +2 -1
- package/dist/runtime-execution.js +71 -11
- package/dist/runtime-execution.js.map +1 -1
- package/dist/runtime-guardrails.d.ts +26 -0
- package/dist/runtime-guardrails.js +168 -0
- package/dist/runtime-guardrails.js.map +1 -0
- package/dist/setup-agents-import.js +5 -3
- package/dist/setup-agents-import.js.map +1 -1
- package/dist/skills-catalog.js +63 -0
- package/dist/skills-catalog.js.map +1 -1
- package/dist/skills-commands.d.ts +4 -0
- package/dist/skills-commands.js +55 -2
- package/dist/skills-commands.js.map +1 -1
- package/dist/skills-memory.d.ts +36 -2
- package/dist/skills-memory.js +165 -6
- package/dist/skills-memory.js.map +1 -1
- package/dist/skills-planning.js +2 -4
- package/dist/skills-planning.js.map +1 -1
- package/dist/skills-render.js +2 -4
- package/dist/skills-render.js.map +1 -1
- package/dist/skills.d.ts +1 -1
- package/dist/skills.js +1 -1
- package/dist/skills.js.map +1 -1
- package/dist/sprint-commands.js +2 -1
- package/dist/sprint-commands.js.map +1 -1
- package/dist/subagent-protocol.js +3 -5
- package/dist/subagent-protocol.js.map +1 -1
- package/dist/support-commands.d.ts +2 -0
- package/dist/support-commands.js +18 -0
- package/dist/support-commands.js.map +1 -0
- package/dist/support-diagnostics.d.ts +49 -0
- package/dist/support-diagnostics.js +86 -0
- package/dist/support-diagnostics.js.map +1 -0
- package/dist/task-graph-commands.js +5 -3
- package/dist/task-graph-commands.js.map +1 -1
- package/dist/telemetry-redaction.js +8 -1
- package/dist/telemetry-redaction.js.map +1 -1
- package/dist/tool-commands.d.ts +3 -0
- package/dist/tool-commands.js +62 -0
- package/dist/tool-commands.js.map +1 -1
- package/dist/tracker-adapters.d.ts +71 -0
- package/dist/tracker-adapters.js +186 -0
- package/dist/tracker-adapters.js.map +1 -0
- package/dist/tracker-commands.d.ts +2 -0
- package/dist/tracker-commands.js +119 -0
- package/dist/tracker-commands.js.map +1 -0
- package/dist/types/metrics.d.ts +24 -0
- package/dist/types/model-config.d.ts +39 -0
- package/dist/types/runtime.d.ts +56 -0
- package/dist/types/skills.d.ts +2 -0
- package/dist/types/tasks.d.ts +6 -0
- package/dist/types/workflow-run.d.ts +17 -0
- package/dist/types.d.ts +4 -4
- package/dist/types.js.map +1 -1
- package/dist/upgrade-commands.js +13 -4
- package/dist/upgrade-commands.js.map +1 -1
- package/dist/validation.js +2 -2
- package/dist/validation.js.map +1 -1
- package/dist/visual-validation.d.ts +81 -0
- package/dist/visual-validation.js +290 -0
- package/dist/visual-validation.js.map +1 -0
- package/dist/web-action-security.d.ts +11 -0
- package/dist/web-action-security.js +45 -0
- package/dist/web-action-security.js.map +1 -0
- package/dist/web-api-read-routes.js +101 -1
- package/dist/web-api-read-routes.js.map +1 -1
- package/dist/web-api.js +507 -5
- package/dist/web-api.js.map +1 -1
- package/dist/web-artifacts.d.ts +55 -0
- package/dist/web-artifacts.js +222 -0
- package/dist/web-artifacts.js.map +1 -0
- package/dist/web-console/assets/index-BNESIVvk.js +11 -0
- package/dist/web-console/assets/index-jxCY5eEc.css +1 -0
- package/dist/web-console/index.html +13 -0
- package/dist/web-console.js +9 -3
- package/dist/web-console.js.map +1 -1
- package/dist/web-recovery.d.ts +30 -0
- package/dist/web-recovery.js +163 -0
- package/dist/web-recovery.js.map +1 -0
- package/dist/web-workflow-progress.d.ts +41 -0
- package/dist/web-workflow-progress.js +114 -0
- package/dist/web-workflow-progress.js.map +1 -0
- package/dist/workflow-approval-service.d.ts +2 -1
- package/dist/workflow-approval-service.js +72 -0
- package/dist/workflow-approval-service.js.map +1 -1
- package/dist/workflow-evidence-service.js +8 -1
- package/dist/workflow-evidence-service.js.map +1 -1
- package/dist/workflow-gates.d.ts +2 -0
- package/dist/workflow-gates.js +221 -0
- package/dist/workflow-gates.js.map +1 -1
- package/dist/workflow-run-commands.js +13 -1
- package/dist/workflow-run-commands.js.map +1 -1
- package/dist/workflow-services.d.ts +16 -12
- package/dist/workflow-services.js +313 -253
- package/dist/workflow-services.js.map +1 -1
- package/dist/workflow-task-service.d.ts +11 -0
- package/dist/workflow-task-service.js +242 -0
- package/dist/workflow-task-service.js.map +1 -0
- package/dist/workspace-validator.js +109 -3
- package/dist/workspace-validator.js.map +1 -1
- package/dist/workspace.js +8 -2
- package/dist/workspace.js.map +1 -1
- package/docs/adoption-guide.md +147 -0
- package/docs/autonomous-workflow.md +118 -27
- package/docs/benchmark.md +15 -7
- package/docs/command-contracts.md +18 -1
- package/docs/core-command-surface.md +59 -13
- package/docs/end-to-end-demo.md +1 -0
- package/docs/extension-contracts.md +83 -0
- package/docs/orchestra-mvp.md +83 -3
- package/docs/persona-workflows.md +32 -0
- package/docs/release-test-matrix.md +42 -0
- package/docs/runtime-adapters.md +92 -0
- package/docs/runtime-llm-flow.md +13 -0
- package/docs/setup-agents-applicability-review.md +173 -0
- package/docs/skill-loading-strategy.md +1 -0
- package/docs/source-of-truth-and-agent-learning.md +14 -0
- package/docs/traceability-flow.md +16 -1
- package/docs/tracker-adapter-contract.md +10 -1
- package/docs/web-console-qa.md +35 -0
- package/package.json +12 -6
- package/rules/development-engineering.mdc +68 -0
- package/rules/devops-tooling.mdc +1 -0
- package/rules/dry-clean-code.mdc +1 -0
- package/rules/performance-reliability.mdc +1 -0
- package/rules/testing-discipline.mdc +4 -1
- package/skills/collection-standards/SKILL.md +63 -0
- package/skills/collection-standards/manifest.json +69 -0
|
@@ -4,14 +4,21 @@ import { DEFAULT_PHASE_PLAYBOOKS, DEFAULT_PLAYBOOKS_DIR, } from "./phase-playboo
|
|
|
4
4
|
import { exists, resolveWorkspaceWritePath } from "./fs-utils.js";
|
|
5
5
|
import { listRuntimeAdapters } from "./runtime-adapters.js";
|
|
6
6
|
import { renderRuntimeBootstrap, upsertRuntimeBootstrapBlock, } from "./runtime-bootstrap.js";
|
|
7
|
-
export async function refreshGeneratedFiles({ root = process.cwd(), check = false, dryRun = false, force = false, } = {}) {
|
|
7
|
+
export async function refreshGeneratedFiles({ root = process.cwd(), check = false, dryRun = false, force = false, targets, } = {}) {
|
|
8
8
|
const items = [
|
|
9
|
-
...(await refreshRuntimeBootstrapFiles({
|
|
9
|
+
...(await refreshRuntimeBootstrapFiles({
|
|
10
|
+
root,
|
|
11
|
+
check,
|
|
12
|
+
dryRun,
|
|
13
|
+
force,
|
|
14
|
+
targets: targets ?? [],
|
|
15
|
+
})),
|
|
10
16
|
...(await refreshPhasePlaybooks({ root, check, dryRun, force })),
|
|
11
17
|
];
|
|
12
18
|
return {
|
|
13
19
|
mode: check ? "check" : dryRun ? "dry-run" : "apply",
|
|
14
20
|
force,
|
|
21
|
+
driftStatus: driftStatus(items),
|
|
15
22
|
items,
|
|
16
23
|
totals: {
|
|
17
24
|
changed: items.filter((item) => item.status === "changed").length,
|
|
@@ -20,8 +27,8 @@ export async function refreshGeneratedFiles({ root = process.cwd(), check = fals
|
|
|
20
27
|
},
|
|
21
28
|
};
|
|
22
29
|
}
|
|
23
|
-
async function refreshRuntimeBootstrapFiles({ root, check, dryRun, force, }) {
|
|
24
|
-
const candidates = await existingRuntimeBootstrapTargets(root);
|
|
30
|
+
async function refreshRuntimeBootstrapFiles({ root, check, dryRun, force, targets, }) {
|
|
31
|
+
const candidates = await existingRuntimeBootstrapTargets(root, targets);
|
|
25
32
|
const items = [];
|
|
26
33
|
for (const candidate of candidates) {
|
|
27
34
|
const filePath = resolveWorkspaceWritePath(root, candidate.path);
|
|
@@ -31,8 +38,17 @@ async function refreshRuntimeBootstrapFiles({ root, check, dryRun, force, }) {
|
|
|
31
38
|
items.push({
|
|
32
39
|
kind: "runtime-bootstrap",
|
|
33
40
|
path: candidate.path,
|
|
41
|
+
target: candidate.target,
|
|
42
|
+
managedBlockId: `runtime-bootstrap:${candidate.target}`,
|
|
43
|
+
beforeStatus: "drifted",
|
|
44
|
+
afterStatus: "blocked",
|
|
34
45
|
status: "blocked",
|
|
35
46
|
reason: "managed block drift detected; rerun with --force to replace it",
|
|
47
|
+
plannedWrite: false,
|
|
48
|
+
recommendedCommand: recommendedRefreshCommand({
|
|
49
|
+
force: true,
|
|
50
|
+
target: candidate.target,
|
|
51
|
+
}),
|
|
36
52
|
});
|
|
37
53
|
continue;
|
|
38
54
|
}
|
|
@@ -40,22 +56,33 @@ async function refreshRuntimeBootstrapFiles({ root, check, dryRun, force, }) {
|
|
|
40
56
|
await ensureParent(filePath);
|
|
41
57
|
await writeFile(filePath, result.content, "utf8");
|
|
42
58
|
}
|
|
59
|
+
const beforeStatus = runtimeBeforeStatus(existing, result);
|
|
43
60
|
items.push({
|
|
44
61
|
kind: "runtime-bootstrap",
|
|
45
62
|
path: candidate.path,
|
|
63
|
+
target: candidate.target,
|
|
64
|
+
managedBlockId: `runtime-bootstrap:${candidate.target}`,
|
|
65
|
+
beforeStatus,
|
|
66
|
+
afterStatus: afterStatus(result.changed, check, dryRun),
|
|
46
67
|
status: result.changed ? "changed" : "unchanged",
|
|
47
68
|
reason: result.missing
|
|
48
69
|
? "managed block missing"
|
|
49
70
|
: result.changed
|
|
50
71
|
? "managed block refreshed"
|
|
51
72
|
: "managed block current",
|
|
73
|
+
plannedWrite: result.changed && !check,
|
|
74
|
+
recommendedCommand: result.changed
|
|
75
|
+
? recommendedRefreshCommand({ force, target: candidate.target })
|
|
76
|
+
: "none",
|
|
52
77
|
});
|
|
53
78
|
}
|
|
54
79
|
return items;
|
|
55
80
|
}
|
|
56
|
-
async function existingRuntimeBootstrapTargets(root) {
|
|
81
|
+
async function existingRuntimeBootstrapTargets(root, targets) {
|
|
57
82
|
const defaults = new Set(["ORCHESTRA.md", "AGENTS.md"]);
|
|
58
|
-
const
|
|
83
|
+
const targetSet = new Set(targets);
|
|
84
|
+
const adapters = listRuntimeAdapters().filter((adapter) => targetSet.size === 0 || targetSet.has(adapter.target));
|
|
85
|
+
const candidates = adapters.flatMap((adapter) => adapter.defaultInstructionFiles.map((file) => ({
|
|
59
86
|
path: file,
|
|
60
87
|
target: adapter.target,
|
|
61
88
|
})));
|
|
@@ -84,6 +111,14 @@ async function refreshPhasePlaybooks({ root, check, dryRun, force, }) {
|
|
|
84
111
|
items.push({
|
|
85
112
|
kind: "phase-playbook",
|
|
86
113
|
path: relativePath,
|
|
114
|
+
target: phase,
|
|
115
|
+
managedBlockId: `phase-playbook:${phase}`,
|
|
116
|
+
beforeStatus: missing
|
|
117
|
+
? "missing"
|
|
118
|
+
: existing === desired
|
|
119
|
+
? "current"
|
|
120
|
+
: "custom",
|
|
121
|
+
afterStatus: afterStatus(changed, check, dryRun),
|
|
87
122
|
status: changed ? "changed" : "unchanged",
|
|
88
123
|
reason: missing
|
|
89
124
|
? "default playbook missing"
|
|
@@ -92,10 +127,52 @@ async function refreshPhasePlaybooks({ root, check, dryRun, force, }) {
|
|
|
92
127
|
: force
|
|
93
128
|
? "default playbook current"
|
|
94
129
|
: "existing playbook preserved",
|
|
130
|
+
plannedWrite: changed && !check,
|
|
131
|
+
recommendedCommand: changed
|
|
132
|
+
? recommendedRefreshCommand({ force })
|
|
133
|
+
: missing
|
|
134
|
+
? recommendedRefreshCommand({ force: false })
|
|
135
|
+
: "none",
|
|
95
136
|
});
|
|
96
137
|
}
|
|
97
138
|
return items;
|
|
98
139
|
}
|
|
140
|
+
function runtimeBeforeStatus(existing, result) {
|
|
141
|
+
if (existing === "") {
|
|
142
|
+
return "missing";
|
|
143
|
+
}
|
|
144
|
+
if (result.missing) {
|
|
145
|
+
return "missing-block";
|
|
146
|
+
}
|
|
147
|
+
if (result.drift) {
|
|
148
|
+
return "drifted";
|
|
149
|
+
}
|
|
150
|
+
return result.changed ? "stale" : "current";
|
|
151
|
+
}
|
|
152
|
+
function afterStatus(changed, check, dryRun) {
|
|
153
|
+
if (!changed) {
|
|
154
|
+
return "unchanged";
|
|
155
|
+
}
|
|
156
|
+
return check || dryRun ? "would-change" : "changed";
|
|
157
|
+
}
|
|
158
|
+
function driftStatus(items) {
|
|
159
|
+
if (items.some((item) => item.status === "blocked")) {
|
|
160
|
+
return "blocked";
|
|
161
|
+
}
|
|
162
|
+
if (items.some((item) => item.status === "changed")) {
|
|
163
|
+
return "changes";
|
|
164
|
+
}
|
|
165
|
+
return "clean";
|
|
166
|
+
}
|
|
167
|
+
function recommendedRefreshCommand({ force, target, }) {
|
|
168
|
+
return [
|
|
169
|
+
"orchestra refresh",
|
|
170
|
+
force ? "--force" : "",
|
|
171
|
+
target ? `--target ${target}` : "",
|
|
172
|
+
]
|
|
173
|
+
.filter(Boolean)
|
|
174
|
+
.join(" ");
|
|
175
|
+
}
|
|
99
176
|
async function ensureParent(filePath) {
|
|
100
177
|
const { mkdir } = await import("node:fs/promises");
|
|
101
178
|
await mkdir(path.dirname(filePath), { recursive: true });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh-generated.js","sourceRoot":"","sources":["../src/refresh-generated.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EACL,sBAAsB,EACtB,2BAA2B,GAC5B,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"refresh-generated.js","sourceRoot":"","sources":["../src/refresh-generated.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,9 +15,17 @@ export interface CandidateReleasePlan {
|
|
|
15
15
|
stories: ReleaseStoryReadiness[];
|
|
16
16
|
approvedStories: ReleaseStoryReadiness[];
|
|
17
17
|
changelog: string;
|
|
18
|
+
operations: ReleaseOperationsPlan;
|
|
18
19
|
ready: boolean;
|
|
19
20
|
missing: string[];
|
|
20
21
|
}
|
|
22
|
+
export interface ReleaseOperationsPlan {
|
|
23
|
+
semverImpact: "patch" | "minor" | "major";
|
|
24
|
+
rolloutChecklist: string[];
|
|
25
|
+
rollbackChecklist: string[];
|
|
26
|
+
postReleaseChecklist: string[];
|
|
27
|
+
}
|
|
28
|
+
export type ReleaseEvidenceKind = "smoke" | "rollback" | "post-release" | "release-notes";
|
|
21
29
|
export declare function generateCandidateReleasePlan({ root, version, }?: {
|
|
22
30
|
root?: string;
|
|
23
31
|
version?: string | undefined;
|
|
@@ -37,7 +45,7 @@ export declare function recordReleaseTagApproval({ root, version, approver, appr
|
|
|
37
45
|
}): Promise<EventEntry>;
|
|
38
46
|
export declare function attachReleaseEvidence({ root, kind, summary, artifactPath, }: {
|
|
39
47
|
root?: string;
|
|
40
|
-
kind:
|
|
48
|
+
kind: ReleaseEvidenceKind;
|
|
41
49
|
summary: string;
|
|
42
50
|
artifactPath?: string | undefined;
|
|
43
51
|
}): Promise<EventEntry>;
|
|
@@ -11,6 +11,7 @@ export async function generateCandidateReleasePlan({ root = process.cwd(), versi
|
|
|
11
11
|
stories,
|
|
12
12
|
approvedStories,
|
|
13
13
|
changelog: renderReleaseChangelog(version, approvedStories),
|
|
14
|
+
operations: buildReleaseOperationsPlan(approvedStories),
|
|
14
15
|
ready: missing.length === 0,
|
|
15
16
|
missing,
|
|
16
17
|
};
|
|
@@ -150,12 +151,51 @@ function releasePlanMissingItems(stories, approvedStories) {
|
|
|
150
151
|
}
|
|
151
152
|
function renderReleaseChangelog(version, approvedStories) {
|
|
152
153
|
const title = version ? "# Changelog " + version : "# Changelog";
|
|
153
|
-
const lines = [title, ""];
|
|
154
|
+
const lines = [title, "", "## Changes"];
|
|
154
155
|
for (const story of approvedStories) {
|
|
155
156
|
lines.push("- " + story.taskId + ": " + story.title);
|
|
156
157
|
}
|
|
158
|
+
const breaking = approvedStories.filter((story) => isBreakingStory(story));
|
|
159
|
+
if (breaking.length > 0) {
|
|
160
|
+
lines.push("", "## Breaking Changes");
|
|
161
|
+
for (const story of breaking) {
|
|
162
|
+
lines.push("- " + story.taskId + ": " + story.title);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
157
165
|
return lines.join("\n");
|
|
158
166
|
}
|
|
167
|
+
function buildReleaseOperationsPlan(approvedStories) {
|
|
168
|
+
const semverImpact = approvedStories.some((story) => isBreakingStory(story))
|
|
169
|
+
? "major"
|
|
170
|
+
: approvedStories.length > 0
|
|
171
|
+
? "minor"
|
|
172
|
+
: "patch";
|
|
173
|
+
return {
|
|
174
|
+
semverImpact,
|
|
175
|
+
rolloutChecklist: [
|
|
176
|
+
"Confirm release candidate plan is reviewed.",
|
|
177
|
+
"Confirm release notes or changelog are attached.",
|
|
178
|
+
"Run release smoke validation in the target environment.",
|
|
179
|
+
],
|
|
180
|
+
rollbackChecklist: [
|
|
181
|
+
"Confirm rollback evidence is attached.",
|
|
182
|
+
"Confirm owner and communication path for rollback decision.",
|
|
183
|
+
"Confirm forward-fix path for non-rollbackable changes.",
|
|
184
|
+
],
|
|
185
|
+
postReleaseChecklist: [
|
|
186
|
+
"Attach post-release smoke evidence.",
|
|
187
|
+
"Monitor availability, errors, latency, and support channels.",
|
|
188
|
+
"Capture follow-up issues for accepted risks or known gaps.",
|
|
189
|
+
],
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function isBreakingStory(story) {
|
|
193
|
+
return /\b(breaking|major|incompatible|migration required)\b/i.test([
|
|
194
|
+
story.title,
|
|
195
|
+
story.backlogItem,
|
|
196
|
+
...story.acceptanceCoverage.map((item) => item.criterion),
|
|
197
|
+
].join(" "));
|
|
198
|
+
}
|
|
159
199
|
function renderCandidateReleasePlan(plan) {
|
|
160
200
|
return [
|
|
161
201
|
"# Candidate Release" + (plan.version ? " " + plan.version : ""),
|
|
@@ -163,10 +203,21 @@ function renderCandidateReleasePlan(plan) {
|
|
|
163
203
|
"- Ready: " + plan.ready,
|
|
164
204
|
"- Approved stories: " + plan.approvedStories.length,
|
|
165
205
|
"- Missing: " + (plan.missing.join(", ") || "none"),
|
|
206
|
+
"- Semver impact: " + plan.operations.semverImpact,
|
|
166
207
|
"",
|
|
167
208
|
"## Stories",
|
|
168
209
|
...plan.stories.map(renderStoryLine),
|
|
169
210
|
"",
|
|
211
|
+
"## Release Operations",
|
|
212
|
+
"### Rollout",
|
|
213
|
+
...plan.operations.rolloutChecklist.map((item) => "- " + item),
|
|
214
|
+
"",
|
|
215
|
+
"### Rollback",
|
|
216
|
+
...plan.operations.rollbackChecklist.map((item) => "- " + item),
|
|
217
|
+
"",
|
|
218
|
+
"### Post-release",
|
|
219
|
+
...plan.operations.postReleaseChecklist.map((item) => "- " + item),
|
|
220
|
+
"",
|
|
170
221
|
"## Changelog",
|
|
171
222
|
plan.changelog,
|
|
172
223
|
"",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release-candidate.js","sourceRoot":"","sources":["../src/release-candidate.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,aAAa,EACb,UAAU,EACV,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,0BAA0B,EAC1B,uBAAuB,GAExB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"release-candidate.js","sourceRoot":"","sources":["../src/release-candidate.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,aAAa,EACb,UAAU,EACV,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,0BAA0B,EAC1B,uBAAuB,GAExB,MAAM,wBAAwB,CAAC;AAqChC,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,EACjD,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,EACpB,OAAO,MAIL,EAAE;IACJ,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAC3C,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,CACpD,CAAC;IACF,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,uBAAuB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAClE,OAAO;QACL,OAAO;QACP,OAAO;QACP,eAAe;QACf,SAAS,EAAE,sBAAsB,CAAC,OAAO,EAAE,eAAe,CAAC;QAC3D,UAAU,EAAE,0BAA0B,CAAC,eAAe,CAAC;QACvD,KAAK,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC;QAC3B,OAAO;KACR,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,EAC9C,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,EACpB,OAAO,MAIL,EAAE;IACJ,MAAM,IAAI,GAAG,MAAM,4BAA4B,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,oBAAoB,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;IAC3D,MAAM,OAAO,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC1E,MAAM,WAAW,CAAC,IAAI,EAAE;QACtB,IAAI,EAAE,2BAA2B;QACjC,KAAK,EAAE,iBAAiB;QACxB,OAAO,EAAE,kCAAkC;QAC3C,SAAS,EAAE,CAAC,QAAQ,CAAC;QACrB,QAAQ,EAAE;YACR,OAAO;YACP,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,gBAAgB,EAAE,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC;YACnE,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB;KACF,CAAC,CAAC;IACH,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,EAC7C,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,EACpB,OAAO,EACP,QAAQ,EACR,QAAQ,GAMT;IACC,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,WAAW,CAAC,IAAI,EAAE;QACvB,IAAI,EAAE,sBAAsB;QAC5B,KAAK,EAAE,QAAQ;QACf,OAAO,EAAE,2BAA2B,GAAG,OAAO;QAC9C,QAAQ,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,EAAE;KAC1C,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,EAC1C,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,EACpB,IAAI,EACJ,OAAO,EACP,YAAY,GAMb;IACC,OAAO,WAAW,CAAC,IAAI,EAAE;QACvB,IAAI,EAAE,2BAA2B;QACjC,KAAK,EAAE,iBAAiB;QACxB,OAAO;QACP,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE;QAC7C,QAAQ,EAAE,EAAE,IAAI,EAAE;KACnB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,oBAAoB,CAC3B,IAAU,EACV,MAAoB,EACpB,QAAqB,EAAE;IAEvB,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;IACtE,MAAM,kBAAkB,GAAG,0BAA0B,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG;QACd,GAAG,iBAAiB,CAAC,IAAI,CAAC;QAC1B,GAAG,oBAAoB,CAAC,IAAI,EAAE,UAAU,CAAC;QACzC,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;YAC1D,CAAC,CAAC,CAAC,oBAAoB,CAAC;YACxB,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1E,CAAC;IACF,MAAM,QAAQ,GAAG,uBAAuB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC3D,OAAO;QACL,MAAM,EAAE,IAAI,CAAC,EAAE;QACf,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,WAAW,EAAE,oBAAoB,CAAC,IAAI,CAAC,WAAW,CAAC;QACnD,QAAQ,EACN,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC;YAC7B,OAAO,CAAC,MAAM,KAAK,CAAC;YACpB,QAAQ,CAAC,MAAM,KAAK,CAAC;QACvB,OAAO;QACP,QAAQ;QACR,kBAAkB;KACnB,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAU;IACnC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrE,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAU,EAAE,MAAoB;IAC5D,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACjC,CAAC;IACD,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACxC,CAAC;IACD,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACpC,CAAC;IACD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,WAAW,CAAC,IAAU,EAAE,MAAoB;IACnD,OAAO,CACL,IAAI,CAAC,MAAM,EAAE,eAAe,KAAK,QAAQ;QACzC,MAAM,CAAC,IAAI,CACT,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,gBAAgB,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,CACnE,CACF,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAoB;IAC9C,OAAO,MAAM,CAAC,IAAI,CAChB,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,IAAI,KAAK,iBAAiB,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,SAAS,CAC1E,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAAC,MAAoB;IACpD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAC3B,2BAA2B,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,CACpE,CAAC;AACJ,CAAC;AAED,SAAS,2BAA2B,CAAC,IAAU;IAC7C,OAAO,CACL,IAAI,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC;QAC9B,IAAI,CAAC,MAAM,KAAK,MAAM;QACtB,IAAI,CAAC,MAAM,KAAK,UAAU,CAC3B,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,MAAoB;IAC3C,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAsB;IAC9C,OAAO,MAAM,KAAK,UAAU,IAAI,MAAM,KAAK,MAAM,CAAC;AACpD,CAAC;AAED,SAAS,oBAAoB,CAAC,WAAoB;IAChD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,WAAW,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtE,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,uBAAuB,CAC9B,OAAgC,EAChC,eAAwC;IAExC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;QACvD,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,sBAAsB,CAC7B,OAA2B,EAC3B,eAAwC;IAExC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC;IACjE,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,EAAE,EAAE,YAAY,CAAC,CAAC;IACxC,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IACvD,CAAC;IACD,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3E,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,qBAAqB,CAAC,CAAC;QACtC,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,0BAA0B,CACjC,eAAwC;IAExC,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAC1E,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC;YAC1B,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,OAAO,CAAC;IACd,OAAO;QACL,YAAY;QACZ,gBAAgB,EAAE;YAChB,6CAA6C;YAC7C,kDAAkD;YAClD,yDAAyD;SAC1D;QACD,iBAAiB,EAAE;YACjB,wCAAwC;YACxC,6DAA6D;YAC7D,wDAAwD;SACzD;QACD,oBAAoB,EAAE;YACpB,qCAAqC;YACrC,8DAA8D;YAC9D,4DAA4D;SAC7D;KACF,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,KAA4B;IACnD,OAAO,uDAAuD,CAAC,IAAI,CACjE;QACE,KAAK,CAAC,KAAK;QACX,KAAK,CAAC,WAAW;QACjB,GAAG,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;KAC1D,CAAC,IAAI,CAAC,GAAG,CAAC,CACZ,CAAC;AACJ,CAAC;AAED,SAAS,0BAA0B,CAAC,IAA0B;IAC5D,OAAO;QACL,qBAAqB,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,EAAE;QACF,WAAW,GAAG,IAAI,CAAC,KAAK;QACxB,sBAAsB,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM;QACpD,aAAa,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;QACnD,mBAAmB,GAAG,IAAI,CAAC,UAAU,CAAC,YAAY;QAClD,EAAE;QACF,YAAY;QACZ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;QACpC,EAAE;QACF,uBAAuB;QACvB,aAAa;QACb,GAAG,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,IAAI,CAAC;QAC9D,EAAE;QACF,cAAc;QACd,GAAG,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,IAAI,CAAC;QAC/D,EAAE;QACF,kBAAkB;QAClB,GAAG,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,IAAI,CAAC;QAClE,EAAE;QACF,cAAc;QACd,IAAI,CAAC,SAAS;QACd,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,SAAS,eAAe,CAAC,KAA4B;IACnD,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IACtD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;IACnD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;IACrD,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IACrE,OAAO,CACL,IAAI;QACJ,KAAK,CAAC,MAAM;QACZ,IAAI;QACJ,KAAK;QACL,GAAG;QACH,KAAK;QACL,WAAW;QACX,OAAO;QACP,YAAY;QACZ,QAAQ,CACT,CAAC;AACJ,CAAC"}
|
package/dist/release-commands.js
CHANGED
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
import { execFile, spawn } from "node:child_process";
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
3
5
|
import { promisify } from "node:util";
|
|
4
6
|
import { requireArg } from "./args.js";
|
|
5
7
|
import { attachReleaseEvidence, generateCandidateReleasePlan, recordReleaseTagApproval, writeCandidateReleasePlan, } from "./release-candidate.js";
|
|
6
8
|
import { generateReleaseReadinessReport, } from "./release-readiness.js";
|
|
7
9
|
const execFileAsync = promisify(execFile);
|
|
10
|
+
const REQUIRED_PACKAGE_FILES = [
|
|
11
|
+
"package.json",
|
|
12
|
+
"README.md",
|
|
13
|
+
"bin/orchestra.js",
|
|
14
|
+
];
|
|
15
|
+
const FORBIDDEN_PACKAGE_PATHS = [
|
|
16
|
+
/^\.agent-workflow(?:\/|$)/,
|
|
17
|
+
/^\.generated-prompts(?:\/|$)/,
|
|
18
|
+
/^\.env(?:\.|$)/,
|
|
19
|
+
/(?:^|\/)\.env(?:\.|$)/,
|
|
20
|
+
/(?:^|\/)node_modules(?:\/|$)/,
|
|
21
|
+
];
|
|
22
|
+
const PROCESS_OUTPUT_TAIL_LIMIT = 1200;
|
|
8
23
|
export async function releaseCheckCommand(options, io) {
|
|
9
24
|
const root = typeof options.root === "string" ? options.root : process.cwd();
|
|
10
25
|
const result = await runReleaseChecks(root);
|
|
@@ -31,7 +46,9 @@ async function runReleaseChecks(root) {
|
|
|
31
46
|
checks.push(await runScript(root, "lint", "npm run lint"));
|
|
32
47
|
checks.push(await runScript(root, "typecheck", "npm run typecheck"));
|
|
33
48
|
checks.push(await runScript(root, "secret-scan", "npm run secret-scan"));
|
|
49
|
+
checks.push(await runScript(root, "security-audit", "npm run security:audit"));
|
|
34
50
|
checks.push(await runScript(root, "tests", "npm test"));
|
|
51
|
+
checks.push(await checkPackageProvenance(root));
|
|
35
52
|
checks.push(await checkVersionMatchesTag(root));
|
|
36
53
|
checks.push(await checkCleanWorkingTree(root));
|
|
37
54
|
const releaseReadiness = await checkReleaseReadiness(root);
|
|
@@ -54,12 +71,21 @@ async function runScript(root, name, cmd) {
|
|
|
54
71
|
const msg = err instanceof Error
|
|
55
72
|
? (err.message.split("\n")[0] ?? err.message)
|
|
56
73
|
: String(err);
|
|
57
|
-
return { name, passed: false, detail: msg };
|
|
74
|
+
return { name, passed: false, detail: normalizeFailedScriptDetail(msg) };
|
|
58
75
|
}
|
|
59
76
|
}
|
|
60
77
|
function runProcess(command, args, cwd) {
|
|
61
78
|
return new Promise((resolve, reject) => {
|
|
62
|
-
const child = spawn(command, args, {
|
|
79
|
+
const child = spawn(command, args, {
|
|
80
|
+
cwd,
|
|
81
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
82
|
+
});
|
|
83
|
+
let outputTail = "";
|
|
84
|
+
const appendOutput = (chunk) => {
|
|
85
|
+
outputTail = (outputTail + chunk.toString("utf8")).slice(-PROCESS_OUTPUT_TAIL_LIMIT);
|
|
86
|
+
};
|
|
87
|
+
child.stdout?.on("data", appendOutput);
|
|
88
|
+
child.stderr?.on("data", appendOutput);
|
|
63
89
|
child.on("error", reject);
|
|
64
90
|
child.on("close", (code, signal) => {
|
|
65
91
|
if (code === 0) {
|
|
@@ -67,12 +93,29 @@ function runProcess(command, args, cwd) {
|
|
|
67
93
|
return;
|
|
68
94
|
}
|
|
69
95
|
const reason = signal !== null ? `signal ${signal}` : `exit code ${code ?? "unknown"}`;
|
|
70
|
-
|
|
96
|
+
const tail = compactProcessOutput(outputTail);
|
|
97
|
+
const detail = tail ? `; output: ${tail}` : "";
|
|
98
|
+
reject(new Error(`Command failed: ${command} ${args.join(" ")} (${reason})${detail}`));
|
|
71
99
|
});
|
|
72
100
|
});
|
|
73
101
|
}
|
|
102
|
+
function compactProcessOutput(output) {
|
|
103
|
+
return output
|
|
104
|
+
.split(/\r?\n/)
|
|
105
|
+
.map((line) => line.trim())
|
|
106
|
+
.filter(Boolean)
|
|
107
|
+
.slice(-8)
|
|
108
|
+
.join(" | ");
|
|
109
|
+
}
|
|
110
|
+
function normalizeFailedScriptDetail(detail) {
|
|
111
|
+
if (detail.includes("listen EPERM")) {
|
|
112
|
+
return (detail +
|
|
113
|
+
"; local web-server tests were blocked by the environment while running inside release check. Run npm test directly or rerun in CI/a shell that permits 127.0.0.1 listeners.");
|
|
114
|
+
}
|
|
115
|
+
return detail;
|
|
116
|
+
}
|
|
74
117
|
async function checkVersionMatchesTag(root) {
|
|
75
|
-
const name = "version
|
|
118
|
+
const name = "version is releasable against latest tag";
|
|
76
119
|
try {
|
|
77
120
|
const pkg = JSON.parse(await readFile(`${root}/package.json`, "utf8"));
|
|
78
121
|
const version = pkg.version;
|
|
@@ -84,18 +127,45 @@ async function checkVersionMatchesTag(root) {
|
|
|
84
127
|
if (!latest)
|
|
85
128
|
return { name, passed: false, detail: "no semver tags found" };
|
|
86
129
|
const tagVersion = latest.slice(1);
|
|
87
|
-
|
|
130
|
+
const comparison = compareSemver(version, tagVersion);
|
|
131
|
+
if (comparison === 0)
|
|
88
132
|
return { name, passed: true };
|
|
133
|
+
if (comparison > 0) {
|
|
134
|
+
return {
|
|
135
|
+
name,
|
|
136
|
+
passed: true,
|
|
137
|
+
detail: `package.json=${version} is ahead of latest tag ${latest}; release should create v${version}`,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
89
140
|
return {
|
|
90
141
|
name,
|
|
91
142
|
passed: false,
|
|
92
|
-
detail: `package.json=${version} latest tag
|
|
143
|
+
detail: `package.json=${version} is behind latest tag ${latest}`,
|
|
93
144
|
};
|
|
94
145
|
}
|
|
95
146
|
catch (err) {
|
|
96
147
|
return { name, passed: false, detail: String(err) };
|
|
97
148
|
}
|
|
98
149
|
}
|
|
150
|
+
function compareSemver(left, right) {
|
|
151
|
+
const leftParts = parseSemver(left);
|
|
152
|
+
const rightParts = parseSemver(right);
|
|
153
|
+
if (!leftParts || !rightParts) {
|
|
154
|
+
return left.localeCompare(right);
|
|
155
|
+
}
|
|
156
|
+
for (let index = 0; index < leftParts.length; index += 1) {
|
|
157
|
+
const delta = leftParts[index] - rightParts[index];
|
|
158
|
+
if (delta !== 0)
|
|
159
|
+
return delta;
|
|
160
|
+
}
|
|
161
|
+
return 0;
|
|
162
|
+
}
|
|
163
|
+
function parseSemver(value) {
|
|
164
|
+
const match = value.match(/^(\d+)\.(\d+)\.(\d+)$/);
|
|
165
|
+
if (!match)
|
|
166
|
+
return undefined;
|
|
167
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
168
|
+
}
|
|
99
169
|
async function checkCleanWorkingTree(root) {
|
|
100
170
|
const name = "clean working tree";
|
|
101
171
|
try {
|
|
@@ -116,9 +186,112 @@ async function checkCleanWorkingTree(root) {
|
|
|
116
186
|
return { name, passed: false, detail: String(err) };
|
|
117
187
|
}
|
|
118
188
|
}
|
|
189
|
+
async function checkPackageProvenance(root) {
|
|
190
|
+
const name = "package provenance";
|
|
191
|
+
try {
|
|
192
|
+
const { stdout } = await execFileAsync("npm", ["pack", "--dry-run", "--json"], {
|
|
193
|
+
cwd: root,
|
|
194
|
+
env: {
|
|
195
|
+
...process.env,
|
|
196
|
+
npm_config_cache: join(tmpdir(), "open-orchestra-npm-cache"),
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
const artifact = parseNpmPackArtifact(stdout);
|
|
200
|
+
const files = new Set((artifact.files ?? [])
|
|
201
|
+
.map((file) => (typeof file.path === "string" ? file.path : ""))
|
|
202
|
+
.filter(Boolean));
|
|
203
|
+
const missing = REQUIRED_PACKAGE_FILES.filter((file) => !files.has(file));
|
|
204
|
+
const forbidden = [...files].filter((file) => FORBIDDEN_PACKAGE_PATHS.some((pattern) => pattern.test(file)));
|
|
205
|
+
if (missing.length > 0 || forbidden.length > 0) {
|
|
206
|
+
const details = [];
|
|
207
|
+
if (missing.length > 0) {
|
|
208
|
+
details.push(`missing ${missing.join(", ")}`);
|
|
209
|
+
}
|
|
210
|
+
if (forbidden.length > 0) {
|
|
211
|
+
details.push(`forbidden ${forbidden.join(", ")}`);
|
|
212
|
+
}
|
|
213
|
+
return { name, passed: false, detail: details.join("; ") };
|
|
214
|
+
}
|
|
215
|
+
return {
|
|
216
|
+
name,
|
|
217
|
+
passed: true,
|
|
218
|
+
detail: `${files.size} files in ${String(artifact.filename ?? "pack output")}`,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
catch (err) {
|
|
222
|
+
return { name, passed: false, detail: String(err) };
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
function parseNpmPackArtifact(stdout) {
|
|
226
|
+
const parsed = JSON.parse(extractJsonArray(stdout));
|
|
227
|
+
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
228
|
+
throw new Error("npm pack did not return package metadata");
|
|
229
|
+
}
|
|
230
|
+
const artifact = parsed[0];
|
|
231
|
+
if (!Array.isArray(artifact.files)) {
|
|
232
|
+
throw new Error("npm pack metadata does not include files");
|
|
233
|
+
}
|
|
234
|
+
return artifact;
|
|
235
|
+
}
|
|
236
|
+
function extractJsonArray(output) {
|
|
237
|
+
let lastParseError;
|
|
238
|
+
for (let start = output.indexOf("["); start !== -1; start = output.indexOf("[", start + 1)) {
|
|
239
|
+
const end = findJsonArrayEnd(output, start);
|
|
240
|
+
if (end === -1) {
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
const candidate = output.slice(start, end + 1);
|
|
244
|
+
try {
|
|
245
|
+
if (Array.isArray(JSON.parse(candidate))) {
|
|
246
|
+
return candidate;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
catch (err) {
|
|
250
|
+
lastParseError = err;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
const suffix = lastParseError instanceof Error ? `: ${lastParseError.message}` : "";
|
|
254
|
+
throw new Error(`npm pack output did not include JSON package metadata${suffix}`);
|
|
255
|
+
}
|
|
256
|
+
function findJsonArrayEnd(output, start) {
|
|
257
|
+
let depth = 0;
|
|
258
|
+
let inString = false;
|
|
259
|
+
let escaped = false;
|
|
260
|
+
for (let index = start; index < output.length; index += 1) {
|
|
261
|
+
const char = output[index];
|
|
262
|
+
if (inString) {
|
|
263
|
+
if (escaped) {
|
|
264
|
+
escaped = false;
|
|
265
|
+
}
|
|
266
|
+
else if (char === "\\") {
|
|
267
|
+
escaped = true;
|
|
268
|
+
}
|
|
269
|
+
else if (char === '"') {
|
|
270
|
+
inString = false;
|
|
271
|
+
}
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
if (char === '"') {
|
|
275
|
+
inString = true;
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
if (char === "[") {
|
|
279
|
+
depth += 1;
|
|
280
|
+
}
|
|
281
|
+
else if (char === "]") {
|
|
282
|
+
depth -= 1;
|
|
283
|
+
if (depth === 0) {
|
|
284
|
+
return index;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return -1;
|
|
289
|
+
}
|
|
119
290
|
async function checkReleaseReadiness(root) {
|
|
120
291
|
try {
|
|
121
|
-
const report = await generateReleaseReadinessReport(root
|
|
292
|
+
const report = await generateReleaseReadinessReport(root, {
|
|
293
|
+
scope: "release",
|
|
294
|
+
});
|
|
122
295
|
const missing = releaseReadinessMissingSummary(report);
|
|
123
296
|
return {
|
|
124
297
|
check: {
|
|
@@ -152,7 +325,12 @@ async function checkReleaseReadiness(root) {
|
|
|
152
325
|
function releaseReadinessMissingSummary(report) {
|
|
153
326
|
const missing = [];
|
|
154
327
|
if (report.uncoveredAcceptanceCriteria.length > 0) {
|
|
155
|
-
|
|
328
|
+
const taskIds = [
|
|
329
|
+
...new Set(report.uncoveredAcceptanceCriteria.map((item) => item.taskId)),
|
|
330
|
+
];
|
|
331
|
+
const examples = taskIds.slice(0, 3).join(", ");
|
|
332
|
+
const suffix = taskIds.length > 3 ? `, +${taskIds.length - 3} more` : "";
|
|
333
|
+
missing.push(`${report.uncoveredAcceptanceCriteria.length} uncovered AC across ${taskIds.length} task(s) (${examples}${suffix}); scope a release candidate or attach AC evidence`);
|
|
156
334
|
}
|
|
157
335
|
if (report.blockerReviews.length > 0) {
|
|
158
336
|
missing.push(`${report.blockerReviews.length} blocker review(s)`);
|
|
@@ -161,10 +339,19 @@ function releaseReadinessMissingSummary(report) {
|
|
|
161
339
|
missing.push(`${report.activeLocks.length} active lock(s)`);
|
|
162
340
|
}
|
|
163
341
|
if (report.missingSmokeEvidence) {
|
|
164
|
-
missing.push("smoke evidence");
|
|
342
|
+
missing.push("smoke evidence (orchestra release evidence --kind smoke)");
|
|
165
343
|
}
|
|
166
344
|
if (report.missingRollbackEvidence) {
|
|
167
|
-
missing.push("rollback evidence");
|
|
345
|
+
missing.push("rollback evidence (orchestra release evidence --kind rollback)");
|
|
346
|
+
}
|
|
347
|
+
if (report.missingDocumentationEvidence) {
|
|
348
|
+
missing.push("documentation evidence");
|
|
349
|
+
}
|
|
350
|
+
if (report.missingObservabilityEvidence) {
|
|
351
|
+
missing.push("observability evidence");
|
|
352
|
+
}
|
|
353
|
+
if (!report.gaReadiness.passed) {
|
|
354
|
+
missing.push(`${report.gaReadiness.blockers.length} GA blocker(s)`);
|
|
168
355
|
}
|
|
169
356
|
return missing.join("; ");
|
|
170
357
|
}
|
|
@@ -207,10 +394,13 @@ export async function releaseEvidenceCommand(options, io) {
|
|
|
207
394
|
io.log("Release evidence attached: " + event.summary);
|
|
208
395
|
}
|
|
209
396
|
function parseReleaseEvidenceKind(value) {
|
|
210
|
-
if (value === "smoke" ||
|
|
397
|
+
if (value === "smoke" ||
|
|
398
|
+
value === "rollback" ||
|
|
399
|
+
value === "post-release" ||
|
|
400
|
+
value === "release-notes") {
|
|
211
401
|
return value;
|
|
212
402
|
}
|
|
213
|
-
throw new Error("release evidence kind must be smoke or
|
|
403
|
+
throw new Error("release evidence kind must be smoke, rollback, post-release, or release-notes");
|
|
214
404
|
}
|
|
215
405
|
function stringOption(value) {
|
|
216
406
|
return typeof value === "string" ? value : undefined;
|