mandrel 1.81.0 → 1.83.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/.agents/README.md +46 -5
- package/.agents/docs/SDLC.md +97 -82
- package/.agents/docs/agentrc-reference.json +10 -2
- package/.agents/docs/configuration.md +4 -1
- package/.agents/docs/execution-reference.md +52 -0
- package/.agents/docs/workflows.md +1 -1
- package/.agents/instructions.md +85 -45
- package/.agents/personas/architect.md +8 -5
- package/.agents/personas/engineer-mobile.md +3 -2
- package/.agents/personas/engineer-web.md +3 -2
- package/.agents/personas/engineer.md +6 -5
- package/.agents/personas/product.md +19 -13
- package/.agents/personas/project-manager.md +9 -8
- package/.agents/personas/qa-engineer.md +10 -6
- package/.agents/personas/refactorer.md +3 -2
- package/.agents/personas/technical-writer.md +2 -1
- package/.agents/personas/ux-designer.md +2 -2
- package/.agents/schemas/agentrc.schema.json +41 -3
- package/.agents/schemas/qa-ledger.schema.json +2 -2
- package/.agents/scripts/acceptance-spec-reconciler.js +143 -59
- package/.agents/scripts/epic-deliver-prepare.js +40 -31
- package/.agents/scripts/epic-plan-decompose.js +2 -5
- package/.agents/scripts/epic-plan-spec.js +16 -19
- package/.agents/scripts/hierarchy-gate.js +11 -11
- package/.agents/scripts/lib/ITicketingProvider.js +4 -3
- package/.agents/scripts/lib/bdd-runner-detect.js +1 -1
- package/.agents/scripts/lib/bdd-scenario-scanner.js +1 -1
- package/.agents/scripts/lib/cli-args.js +1 -5
- package/.agents/scripts/lib/codebase-snapshot.js +1 -1
- package/.agents/scripts/lib/config/explain.js +4 -1
- package/.agents/scripts/lib/config/temp-paths.js +1 -4
- package/.agents/scripts/lib/config-settings-schema.js +30 -1
- package/.agents/scripts/lib/epic-body-sections.js +310 -0
- package/.agents/scripts/lib/epic-plan-clarity.js +38 -1
- package/.agents/scripts/lib/epic-plan-ideation.js +15 -3
- package/.agents/scripts/lib/findings/promote-finding.js +3 -3
- package/.agents/scripts/lib/findings/severity.js +5 -6
- package/.agents/scripts/lib/label-constants.js +7 -17
- package/.agents/scripts/lib/label-taxonomy.js +4 -21
- package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +65 -2
- package/.agents/scripts/lib/orchestration/context-hydration-engine.js +105 -9
- package/.agents/scripts/lib/orchestration/doc-reader.js +29 -0
- package/.agents/scripts/lib/orchestration/docs-digest.js +134 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +23 -22
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +7 -10
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +4 -38
- package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +8 -9
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/authoring-context.js +11 -5
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/cli-args.js +26 -5
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +102 -304
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +32 -29
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +19 -20
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-authoring-grounding.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +6 -9
- package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +3 -4
- package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +20 -27
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +11 -5
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +22 -59
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +1 -1
- package/.agents/scripts/lib/orchestration/planning-context-budget.js +1 -1
- package/.agents/scripts/lib/orchestration/preflight-cache.js +1 -1
- package/.agents/scripts/lib/orchestration/spec-freshness.js +3 -3
- package/.agents/scripts/lib/orchestration/spec-section-validator.js +1 -1
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +15 -1
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +122 -1
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +5 -8
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +2 -2
- package/.agents/scripts/lib/plan-phase-cleanup.js +1 -2
- package/.agents/scripts/lib/qa/console-allowlist.js +5 -4
- package/.agents/scripts/lib/qa/qa-context-hydrator.js +6 -85
- package/.agents/scripts/lib/qa/resolve-qa-contract.js +144 -8
- package/.agents/scripts/lib/templates/decomposer-prompts.js +14 -8
- package/.agents/scripts/lifecycle-emit.js +1 -1
- package/.agents/scripts/lint-label-vocabulary.js +2 -3
- package/.agents/scripts/providers/github/mappers.js +0 -3
- package/.agents/scripts/providers/github/tickets.js +7 -18
- package/.agents/scripts/single-story-init.js +0 -1
- package/.agents/scripts/story-init.js +1 -29
- package/.agents/skills/core/epic-plan-consolidate/SKILL.md +43 -22
- package/.agents/skills/core/epic-plan-consolidate/examples.md +51 -0
- package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +27 -40
- package/.agents/skills/core/epic-plan-decompose-author/examples.md +47 -0
- package/.agents/skills/core/epic-plan-premortem/SKILL.md +15 -13
- package/.agents/skills/core/epic-plan-premortem/examples.md +53 -0
- package/.agents/skills/core/epic-plan-spec-author/SKILL.md +143 -151
- package/.agents/skills/core/epic-plan-spec-author/examples.md +91 -0
- package/.agents/skills/core/hydrate-context/SKILL.md +10 -5
- package/.agents/skills/core/knowledge-transfer/SKILL.md +3 -2
- package/.agents/skills/core/scope-triage/SKILL.md +2 -1
- package/.agents/skills/skills.index.json +8 -8
- package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +52 -38
- package/.agents/templates/epic-from-idea.md +4 -0
- package/.agents/workflows/audit-to-stories.md +2 -2
- package/.agents/workflows/helpers/code-review.md +11 -9
- package/.agents/workflows/helpers/deliver-epic-reference.md +514 -0
- package/.agents/workflows/helpers/deliver-epic.md +173 -490
- package/.agents/workflows/helpers/epic-audit.md +11 -8
- package/.agents/workflows/helpers/epic-deliver-story.md +45 -27
- package/.agents/workflows/helpers/epic-plan-decompose.md +17 -12
- package/.agents/workflows/helpers/epic-plan-spec.md +68 -68
- package/.agents/workflows/helpers/parallel-tooling.md +2 -1
- package/.agents/workflows/helpers/plan-epic-reference.md +136 -0
- package/.agents/workflows/helpers/plan-epic.md +141 -256
- package/.agents/workflows/helpers/plan-story.md +31 -61
- package/.agents/workflows/helpers/qa-run-scenario.md +194 -0
- package/.agents/workflows/helpers/scope-triage-gate.md +97 -0
- package/.agents/workflows/helpers/single-story-deliver-reference.md +423 -0
- package/.agents/workflows/helpers/single-story-deliver.md +129 -393
- package/.agents/workflows/helpers/worktree-lifecycle.md +1 -1
- package/.agents/workflows/plan.md +8 -8
- package/.agents/workflows/qa-assist.md +2 -1
- package/.agents/workflows/qa-explore.md +63 -32
- package/.agents/workflows/qa-run.md +293 -130
- package/docs/CHANGELOG.md +35 -0
- package/package.json +1 -1
- package/.agents/schemas/qa-finding.schema.json +0 -133
- package/.agents/scripts/lib/issue-link-parser.js +0 -74
- package/.agents/scripts/lib/orchestration/finalize/close-planning-tickets.js +0 -116
- package/.agents/scripts/lib/orchestration/planning-state-manager.js +0 -318
- package/.agents/scripts/lib/story-init/hierarchy-tracer.js +0 -57
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Exports:
|
|
6
6
|
* - `assertDecomposeInputs(epic, epicId, tickets)` — entry guards.
|
|
7
7
|
* - `buildEpicSpecInput(epic, epicId)` — projection used by
|
|
8
|
-
* `renderSpec`;
|
|
8
|
+
* `renderSpec`; the Epic body already carries the folded planning
|
|
9
9
|
* spec body carries the `## Planning Artifacts` section the
|
|
10
10
|
* cascade-close path depends on.
|
|
11
11
|
* - `validateTickets(tickets, config)` — runs the cross-link / freshness
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* @module lib/orchestration/epic-plan-decompose/phases/persist-helpers
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
+
import { hasTechSpecContent } from '../../../epic-body-sections.js';
|
|
22
23
|
import { gitSpawn } from '../../../git-utils.js';
|
|
23
24
|
import { Logger } from '../../../Logger.js';
|
|
24
25
|
import { TYPE_LABELS } from '../../../label-constants.js';
|
|
@@ -29,10 +30,7 @@ import {
|
|
|
29
30
|
} from '../../epic-plan-state-store.js';
|
|
30
31
|
import { validateTaskBodies } from '../../task-body-validator.js';
|
|
31
32
|
import { validateAndNormalizeTickets } from '../../ticket-validator.js';
|
|
32
|
-
import {
|
|
33
|
-
ensurePlanningArtifacts,
|
|
34
|
-
resolveConflictPolicy,
|
|
35
|
-
} from './planning-artifacts.js';
|
|
33
|
+
import { resolveConflictPolicy } from './planning-artifacts.js';
|
|
36
34
|
|
|
37
35
|
export function assertDecomposeInputs(epic, epicId, tickets) {
|
|
38
36
|
if (!epic) {
|
|
@@ -43,9 +41,9 @@ export function assertDecomposeInputs(epic, epicId, tickets) {
|
|
|
43
41
|
`[epic-plan-decompose] Ticket #${epicId} is not a ${TYPE_LABELS.EPIC}.`,
|
|
44
42
|
);
|
|
45
43
|
}
|
|
46
|
-
if (!epic.
|
|
44
|
+
if (!hasTechSpecContent(epic.body ?? '')) {
|
|
47
45
|
throw new Error(
|
|
48
|
-
`[epic-plan-decompose] Epic #${epicId}
|
|
46
|
+
`[epic-plan-decompose] Epic #${epicId} body carries no Tech Spec sections (no ## Delivery Slicing). Run /plan Phase 7 first.`,
|
|
49
47
|
);
|
|
50
48
|
}
|
|
51
49
|
if (!Array.isArray(tickets)) {
|
|
@@ -56,7 +54,7 @@ export function assertDecomposeInputs(epic, epicId, tickets) {
|
|
|
56
54
|
}
|
|
57
55
|
|
|
58
56
|
export function buildEpicSpecInput(epic, epicId) {
|
|
59
|
-
const epicBody =
|
|
57
|
+
const epicBody = epic.body ?? '';
|
|
60
58
|
const epicSpecInput = { id: epicId, title: epic.title };
|
|
61
59
|
if (epicBody.length > 0) epicSpecInput.body = epicBody;
|
|
62
60
|
return epicSpecInput;
|
|
@@ -117,8 +115,7 @@ export async function seedPlanState(provider, epicId, epic) {
|
|
|
117
115
|
epicId,
|
|
118
116
|
seed: {
|
|
119
117
|
spec: {
|
|
120
|
-
|
|
121
|
-
techSpecId: epic.linkedIssues.techSpec,
|
|
118
|
+
techSpecPersisted: hasTechSpecContent(epic.body ?? ''),
|
|
122
119
|
completedAt: null,
|
|
123
120
|
},
|
|
124
121
|
},
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* planning-artifacts.js — Phase 1 of the epic-plan-decompose pipeline
|
|
3
|
-
* (Story #2466). Owns the
|
|
4
|
-
* cross-Story conflict-policy resolver.
|
|
3
|
+
* (Story #2466). Owns the cross-Story conflict-policy resolver.
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* Story #4324 retired the `## Planning Artifacts` body shim
|
|
6
|
+
* (`ensurePlanningArtifacts`) with the context-ticket classes — the Epic
|
|
7
|
+
* body now carries the planning content itself as managed sections.
|
|
9
8
|
*
|
|
10
9
|
* @module lib/orchestration/epic-plan-decompose/phases/planning-artifacts
|
|
11
10
|
*/
|
|
@@ -13,39 +12,6 @@
|
|
|
13
12
|
import { resolveListValue } from '../../../config/shared.js';
|
|
14
13
|
import { DEFAULT_REGISTRY_PATTERNS } from '../../ticket-validator-conflicts.js';
|
|
15
14
|
|
|
16
|
-
/**
|
|
17
|
-
* Ensure the supplied Epic body carries a `## Planning Artifacts` section.
|
|
18
|
-
* Idempotent — when the section already exists the body is returned
|
|
19
|
-
* verbatim; when it's missing and `linkedIssues` carries resolved ids
|
|
20
|
-
* the section is appended exactly once using the canonical
|
|
21
|
-
* `- [ ] PRD: #N` / `Tech Spec: #N` / `Acceptance Spec: #N` lines that
|
|
22
|
-
* `issue-link-parser.js` recognises (so cascade-close still resolves the
|
|
23
|
-
* linked tickets).
|
|
24
|
-
*
|
|
25
|
-
* Story #2283.
|
|
26
|
-
*
|
|
27
|
-
* @param {string} body
|
|
28
|
-
* @param {{ prd: number|null, techSpec: number|null, acceptanceSpec: number|null } | undefined | null} linkedIssues
|
|
29
|
-
* @returns {string}
|
|
30
|
-
*/
|
|
31
|
-
export function ensurePlanningArtifacts(body, linkedIssues) {
|
|
32
|
-
const safeBody = typeof body === 'string' ? body : '';
|
|
33
|
-
if (safeBody.includes('## Planning Artifacts')) return safeBody;
|
|
34
|
-
if (!linkedIssues) return safeBody;
|
|
35
|
-
const lines = [];
|
|
36
|
-
if (Number.isInteger(linkedIssues.prd)) {
|
|
37
|
-
lines.push(`- [ ] PRD: #${linkedIssues.prd}`);
|
|
38
|
-
}
|
|
39
|
-
if (Number.isInteger(linkedIssues.techSpec)) {
|
|
40
|
-
lines.push(`- [ ] Tech Spec: #${linkedIssues.techSpec}`);
|
|
41
|
-
}
|
|
42
|
-
if (Number.isInteger(linkedIssues.acceptanceSpec)) {
|
|
43
|
-
lines.push(`- [ ] Acceptance Spec: #${linkedIssues.acceptanceSpec}`);
|
|
44
|
-
}
|
|
45
|
-
if (lines.length === 0) return safeBody;
|
|
46
|
-
return `${safeBody}\n\n## Planning Artifacts\n${lines.join('\n')}\n`;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
15
|
/**
|
|
50
16
|
* Resolve the cross-Story conflict-finding policy from `_config.planning`.
|
|
51
17
|
* Both flags default to `false` so existing repos keep the advisory-only
|
|
@@ -28,9 +28,10 @@
|
|
|
28
28
|
* operator passed `--force` (a deliberate
|
|
29
29
|
* re-decompose that closes the old tree).
|
|
30
30
|
*
|
|
31
|
-
* The
|
|
32
|
-
*
|
|
33
|
-
* cross-run mutual exclusion and the child-duplication refusal
|
|
31
|
+
* The spec-persist idempotency already lives in `phases/plan-epic.js`
|
|
32
|
+
* (keyed on the Epic body's managed planning sections); these guards add
|
|
33
|
+
* the cross-run mutual exclusion and the child-duplication refusal
|
|
34
|
+
* around it.
|
|
34
35
|
*/
|
|
35
36
|
|
|
36
37
|
import { getGitHub } from '../config/github.js';
|
|
@@ -341,12 +342,10 @@ export async function assertNoOpenPlanChildren({
|
|
|
341
342
|
const openChildren = (children ?? []).filter((t) => {
|
|
342
343
|
const labels = Array.isArray(t.labels) ? t.labels : [];
|
|
343
344
|
const isOpen = t.state === undefined || t.state === 'open';
|
|
344
|
-
//
|
|
345
|
-
// `context::*` label
|
|
346
|
-
//
|
|
347
|
-
//
|
|
348
|
-
// MUST be excluded here: counting them would make every first decompose
|
|
349
|
-
// (where the three context tickets are the only open children) refuse.
|
|
345
|
+
// Legacy context spec tickets (the pre-#4324 Tech Spec / Acceptance
|
|
346
|
+
// Spec artifacts) carry a `context::*` label. Historical Epics keep
|
|
347
|
+
// them (forward-only cutover, no backfill), so they are still
|
|
348
|
+
// excluded here: they are reference artifacts, not plan children.
|
|
350
349
|
const isContext = labels.some(
|
|
351
350
|
(l) => typeof l === 'string' && l.startsWith('context::'),
|
|
352
351
|
);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* phases/authoring-context.js — emit-context phase.
|
|
3
3
|
*
|
|
4
4
|
* Builds the authoring context the host LLM (or the
|
|
5
|
-
* `epic-plan-spec-author` Skill) needs to write the
|
|
5
|
+
* `epic-plan-spec-author` Skill) needs to write the Tech Spec.
|
|
6
6
|
* Returns a plain JSON-serialisable object; never hits the network beyond
|
|
7
7
|
* the provider call needed to load the Epic.
|
|
8
8
|
*/
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
import { scanBddScenarios } from '../../../bdd-scenario-scanner.js';
|
|
17
17
|
import { buildCodebaseSnapshot } from '../../../codebase-snapshot.js';
|
|
18
18
|
import { getLimits, PROJECT_ROOT } from '../../../config-resolver.js';
|
|
19
|
+
import { hasEpicSection } from '../../../epic-body-sections.js';
|
|
19
20
|
import { scanMemoryFreshness } from '../../../feedback-loop/memory-freshness.js';
|
|
20
21
|
import { fetchPriorFeedback } from '../../../feedback-loop/prior-feedback-fetcher.js';
|
|
21
22
|
import { Logger } from '../../../Logger.js';
|
|
@@ -24,7 +25,6 @@ import { applyBudget } from '../../planning-context-budget.js';
|
|
|
24
25
|
import { collectReferences, hasNewFileCue } from '../../spec-freshness.js';
|
|
25
26
|
import {
|
|
26
27
|
ACCEPTANCE_SPEC_SYSTEM_PROMPT,
|
|
27
|
-
PRD_SYSTEM_PROMPT,
|
|
28
28
|
TECH_SPEC_SYSTEM_PROMPT,
|
|
29
29
|
} from './prompts.js';
|
|
30
30
|
import { buildAuthoringGrounding } from './spec-authoring-grounding.js';
|
|
@@ -59,7 +59,7 @@ export function resolveMemoryDir({ github } = {}) {
|
|
|
59
59
|
|
|
60
60
|
/**
|
|
61
61
|
* Build the authoring context the host LLM (or the
|
|
62
|
-
* `epic-plan-spec-author` Skill) needs to write the
|
|
62
|
+
* `epic-plan-spec-author` Skill) needs to write the Tech Spec.
|
|
63
63
|
*
|
|
64
64
|
* `docsContext` is bounded by the planning-context budget (Epic #817 Story 9):
|
|
65
65
|
* over-budget payloads downgrade to a summary representation with headings +
|
|
@@ -205,12 +205,18 @@ export async function buildAuthoringContext(
|
|
|
205
205
|
title: epic.title,
|
|
206
206
|
body: epicBody.mode === 'full' ? epic.body : null,
|
|
207
207
|
bodySummary: epicBody.mode === 'summary' ? epicBody.items[0] : null,
|
|
208
|
-
|
|
208
|
+
// Story #4324: the context-ticket classes are retired. A re-planned
|
|
209
|
+
// Epic's previous Tech Spec / Acceptance Table content rides along
|
|
210
|
+
// inside `body` (managed sections), which is how the author keeps
|
|
211
|
+
// AC IDs stable across re-plans.
|
|
212
|
+
planningSections: {
|
|
213
|
+
techSpec: hasEpicSection(epic.body ?? '', 'techSpec'),
|
|
214
|
+
acceptanceTable: hasEpicSection(epic.body ?? '', 'acceptanceTable'),
|
|
215
|
+
},
|
|
209
216
|
},
|
|
210
217
|
docsContext,
|
|
211
218
|
codebaseSnapshot,
|
|
212
219
|
systemPrompts: {
|
|
213
|
-
prd: PRD_SYSTEM_PROMPT,
|
|
214
220
|
techSpec: TECH_SPEC_SYSTEM_PROMPT,
|
|
215
221
|
acceptanceSpec: ACCEPTANCE_SPEC_SYSTEM_PROMPT,
|
|
216
222
|
},
|
|
@@ -4,25 +4,46 @@
|
|
|
4
4
|
* Extracted from `epic-plan-spec.js` (refs #3685) so the top-level entry
|
|
5
5
|
* stays a thin wire-up that scores at or above the maintainability floor;
|
|
6
6
|
* the option schema and the epic-id guards live here.
|
|
7
|
+
*
|
|
8
|
+
* Story #4324: the separate-ticket persist flags `--techspec` /
|
|
9
|
+
* `--acceptance-spec` are retired with the context-ticket classes. The
|
|
10
|
+
* authored content now lands as sections of the Epic body; pass it via
|
|
11
|
+
* `--tech-spec <file>` and `--acceptance-table <file>`. The old flags fail
|
|
12
|
+
* with a usage error naming the removal.
|
|
7
13
|
*/
|
|
8
14
|
|
|
9
15
|
import { parseArgs } from 'node:util';
|
|
10
16
|
|
|
17
|
+
/** Retired flags → the replacement guidance surfaced in the usage error. */
|
|
18
|
+
const RETIRED_FLAGS = Object.freeze({
|
|
19
|
+
'--techspec':
|
|
20
|
+
'--techspec was retired by the context-ticket fold (Story #4324): the Tech Spec is no longer a separate context::tech-spec ticket. Pass --tech-spec <file> — the content lands as a managed section of the Epic body.',
|
|
21
|
+
'--acceptance-spec':
|
|
22
|
+
'--acceptance-spec was retired by the context-ticket fold (Story #4324): the Acceptance Spec is no longer a separate context::acceptance-spec ticket. Pass --acceptance-table <file> — the AC-ID table lands as the ## Acceptance Table section of the Epic body.',
|
|
23
|
+
});
|
|
24
|
+
|
|
11
25
|
/**
|
|
12
26
|
* Parse and validate the `epic-plan-spec` CLI arguments.
|
|
13
27
|
*
|
|
14
28
|
* @param {string[]} [argv] Defaults to `process.argv.slice(2)`.
|
|
15
29
|
* @returns {{ values: Record<string, unknown>, epicId: number }}
|
|
16
|
-
* @throws {Error} when `--epic` is missing or not a number
|
|
30
|
+
* @throws {Error} when `--epic` is missing or not a number, or when a
|
|
31
|
+
* retired separate-ticket persist flag is supplied.
|
|
17
32
|
*/
|
|
18
33
|
export function parseEpicPlanSpecArgs(argv = process.argv.slice(2)) {
|
|
34
|
+
for (const arg of argv) {
|
|
35
|
+
const flag = arg.split('=')[0];
|
|
36
|
+
if (RETIRED_FLAGS[flag]) {
|
|
37
|
+
throw new Error(`[epic-plan-spec] ${RETIRED_FLAGS[flag]}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
19
41
|
const { values } = parseArgs({
|
|
20
42
|
args: argv,
|
|
21
43
|
options: {
|
|
22
44
|
epic: { type: 'string' },
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
'acceptance-spec': { type: 'string' },
|
|
45
|
+
'tech-spec': { type: 'string' },
|
|
46
|
+
'acceptance-table': { type: 'string' },
|
|
26
47
|
'risk-verdict': { type: 'string' },
|
|
27
48
|
force: { type: 'boolean', default: false },
|
|
28
49
|
'force-review': { type: 'boolean', default: false },
|
|
@@ -35,7 +56,7 @@ export function parseEpicPlanSpecArgs(argv = process.argv.slice(2)) {
|
|
|
35
56
|
|
|
36
57
|
if (!values.epic) {
|
|
37
58
|
throw new Error(
|
|
38
|
-
'Usage: epic-plan-spec.js --epic <EpicId> (--emit-context [--pretty] [--full-context] | --
|
|
59
|
+
'Usage: epic-plan-spec.js --epic <EpicId> (--emit-context [--pretty] [--full-context] | --tech-spec <file> --risk-verdict <file> [--acceptance-table <file>]) [--force]',
|
|
39
60
|
);
|
|
40
61
|
}
|
|
41
62
|
|