cc-devflow 4.5.4 → 4.5.5
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/.claude/skills/cc-act/CHANGELOG.md +6 -0
- package/.claude/skills/cc-act/PLAYBOOK.md +21 -5
- package/.claude/skills/cc-act/SKILL.md +21 -11
- package/.claude/skills/cc-act/assets/PR_BRIEF_TEMPLATE.md +10 -0
- package/.claude/skills/cc-act/assets/RELEASE_NOTE_TEMPLATE.md +8 -0
- package/.claude/skills/cc-act/references/closure-contract.md +3 -0
- package/.claude/skills/cc-act/scripts/cc-act-common.sh +48 -0
- package/.claude/skills/cc-act/scripts/generate-status-report.sh +3 -0
- package/.claude/skills/cc-act/scripts/render-pr-brief.sh +6 -0
- package/.claude/skills/cc-act/scripts/sync-act-docs.sh +13 -0
- package/.claude/skills/cc-do/CHANGELOG.md +6 -0
- package/.claude/skills/cc-do/PLAYBOOK.md +7 -6
- package/.claude/skills/cc-do/SKILL.md +27 -12
- package/.claude/skills/cc-do/references/execution-recovery.md +9 -0
- package/.claude/skills/cc-investigate/CHANGELOG.md +6 -0
- package/.claude/skills/cc-investigate/PLAYBOOK.md +5 -1
- package/.claude/skills/cc-investigate/SKILL.md +22 -5
- package/.claude/skills/cc-investigate/assets/ANALYSIS_TEMPLATE.md +14 -0
- package/.claude/skills/cc-investigate/assets/TASKS_TEMPLATE.md +1 -0
- package/.claude/skills/cc-investigate/assets/TASK_MANIFEST_TEMPLATE.json +9 -1
- package/.claude/skills/cc-investigate/references/investigation-contract.md +2 -0
- package/.claude/skills/cc-plan/CHANGELOG.md +23 -0
- package/.claude/skills/cc-plan/PLAYBOOK.md +38 -18
- package/.claude/skills/cc-plan/SKILL.md +81 -47
- package/.claude/skills/cc-plan/assets/DESIGN_TEMPLATE.md +68 -3
- package/.claude/skills/cc-plan/assets/TASKS_TEMPLATE.md +28 -5
- package/.claude/skills/cc-plan/assets/TASK_MANIFEST_TEMPLATE.json +54 -2
- package/.claude/skills/cc-plan/assets/TINY_DESIGN_TEMPLATE.md +44 -0
- package/.claude/skills/cc-plan/references/planning-contract.md +29 -15
- package/.claude/skills/cc-roadmap/CHANGELOG.md +12 -0
- package/.claude/skills/cc-roadmap/PLAYBOOK.md +15 -9
- package/.claude/skills/cc-roadmap/SKILL.md +22 -16
- package/.claude/skills/cc-roadmap/assets/BACKLOG_TEMPLATE.md +3 -1
- package/.claude/skills/cc-roadmap/assets/ROADMAP_TEMPLATE.md +11 -1
- package/.claude/skills/cc-roadmap/assets/TRACKING_TEMPLATE.json +57 -10
- package/.claude/skills/cc-roadmap/scripts/lib/roadmap-tracking/markdown.js +68 -3
- package/.claude/skills/cc-roadmap/scripts/lib/roadmap-tracking/schema.js +120 -0
- package/.claude/skills/cc-roadmap/scripts/lib/roadmap-tracking/store.js +25 -1
- package/.claude/skills/cc-roadmap/scripts/locate-roadmap-item.sh +13 -5
- package/.claude/skills/cc-roadmap/scripts/roadmap-tracking.js +3 -3
- package/.claude/skills/cc-roadmap/scripts/sync-roadmap-progress.sh +3 -3
- package/CHANGELOG.md +7 -0
- package/README.md +5 -5
- package/README.zh-CN.md +5 -5
- package/docs/CLAUDE.md +1 -1
- package/docs/examples/START-HERE.md +3 -3
- package/docs/examples/example-bindings.json +26 -9
- package/docs/examples/full-design-blocked/BACKLOG.md +4 -2
- package/docs/examples/full-design-blocked/README.md +4 -4
- package/docs/examples/full-design-blocked/ROADMAP.md +16 -2
- package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/design.md +39 -1
- package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/task-manifest.json +41 -0
- package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/tasks.md +8 -1
- package/docs/examples/full-design-blocked/roadmap.json +123 -0
- package/docs/examples/local-handoff/BACKLOG.md +4 -2
- package/docs/examples/local-handoff/README.md +4 -4
- package/docs/examples/local-handoff/ROADMAP.md +16 -2
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/design.md +19 -1
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/task-manifest.json +26 -0
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/tasks.md +8 -1
- package/docs/examples/local-handoff/roadmap.json +121 -0
- package/docs/examples/pdca-loop/BACKLOG.md +4 -2
- package/docs/examples/pdca-loop/README.md +4 -4
- package/docs/examples/pdca-loop/ROADMAP.md +16 -2
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/design.md +19 -1
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/task-manifest.json +22 -3
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/tasks.md +8 -1
- package/docs/examples/pdca-loop/roadmap.json +191 -0
- package/docs/examples/scripts/check-example-bindings.sh +7 -4
- package/docs/guides/getting-started.md +2 -2
- package/docs/guides/getting-started.zh-CN.md +2 -2
- package/lib/compiler/__tests__/skills-registry.test.js +17 -3
- package/lib/skill-runtime/__tests__/cli-bootstrap.integration.test.js +9 -1
- package/package.json +1 -1
|
@@ -65,6 +65,47 @@ const DEFAULT_TRACKING = {
|
|
|
65
65
|
items: []
|
|
66
66
|
};
|
|
67
67
|
|
|
68
|
+
const DEFAULT_ROADMAP_STATE = {
|
|
69
|
+
version: 3,
|
|
70
|
+
outputPolicy: {
|
|
71
|
+
documentLanguage: 'en'
|
|
72
|
+
},
|
|
73
|
+
meta: {
|
|
74
|
+
roadmapVersion: '',
|
|
75
|
+
skillVersion: '',
|
|
76
|
+
status: 'active',
|
|
77
|
+
lastUpdated: '',
|
|
78
|
+
currentFocusStage: ''
|
|
79
|
+
},
|
|
80
|
+
context: {
|
|
81
|
+
planningPosture: '',
|
|
82
|
+
evidenceMaturity: '',
|
|
83
|
+
canonicalTerms: [],
|
|
84
|
+
durableDecisionSources: []
|
|
85
|
+
},
|
|
86
|
+
evidence: [],
|
|
87
|
+
route: {
|
|
88
|
+
recommended: '',
|
|
89
|
+
whyThisWinsNow: '',
|
|
90
|
+
rejectedRoutes: [],
|
|
91
|
+
firstSignal: '',
|
|
92
|
+
killSignal: ''
|
|
93
|
+
},
|
|
94
|
+
stages: [],
|
|
95
|
+
items: [],
|
|
96
|
+
handoff: {
|
|
97
|
+
readyForCcPlan: [],
|
|
98
|
+
parked: [],
|
|
99
|
+
serialSpine: [],
|
|
100
|
+
parallelWaves: []
|
|
101
|
+
},
|
|
102
|
+
architecture: {
|
|
103
|
+
diagramType: 'flowchart',
|
|
104
|
+
nodes: [],
|
|
105
|
+
edges: []
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
68
109
|
function normalizeHeader(value) {
|
|
69
110
|
return String(value || '')
|
|
70
111
|
.trim()
|
|
@@ -188,6 +229,83 @@ function normalizeTracking(raw) {
|
|
|
188
229
|
};
|
|
189
230
|
}
|
|
190
231
|
|
|
232
|
+
function normalizeStringList(value) {
|
|
233
|
+
if (Array.isArray(value)) {
|
|
234
|
+
return value.map((entry) => String(entry).trim()).filter(Boolean);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return parseList(value);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function buildRoadmapHandoff(tracking, handoff = {}) {
|
|
241
|
+
const items = Array.isArray(tracking.items) ? tracking.items : [];
|
|
242
|
+
const dependencyHandoff = tracking.dependencyHandoff || {};
|
|
243
|
+
const readyForCcPlan = normalizeStringList(handoff.readyForCcPlan);
|
|
244
|
+
const parked = normalizeStringList(handoff.parked);
|
|
245
|
+
|
|
246
|
+
return {
|
|
247
|
+
readyForCcPlan: readyForCcPlan.length
|
|
248
|
+
? readyForCcPlan
|
|
249
|
+
: items.filter((item) => item.backlog.ready && !item.backlog.parked).map((item) => item.rmId),
|
|
250
|
+
parked: parked.length
|
|
251
|
+
? parked
|
|
252
|
+
: items.filter((item) => item.backlog.parked).map((item) => item.rmId),
|
|
253
|
+
serialSpine: normalizeStringList(handoff.serialSpine || dependencyHandoff.serialSpine),
|
|
254
|
+
parallelWaves: normalizeStringList(
|
|
255
|
+
handoff.parallelWaves || dependencyHandoff.parallelReadyNextWave
|
|
256
|
+
)
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function normalizeRoadmapState(raw = {}) {
|
|
261
|
+
const tracking = normalizeTracking(raw);
|
|
262
|
+
const meta = raw.meta || {};
|
|
263
|
+
const context = raw.context || {};
|
|
264
|
+
const route = raw.route || {};
|
|
265
|
+
const architecture = raw.architecture || {};
|
|
266
|
+
|
|
267
|
+
return {
|
|
268
|
+
...DEFAULT_ROADMAP_STATE,
|
|
269
|
+
version: 3,
|
|
270
|
+
outputPolicy: {
|
|
271
|
+
...DEFAULT_ROADMAP_STATE.outputPolicy,
|
|
272
|
+
...(raw.outputPolicy || {})
|
|
273
|
+
},
|
|
274
|
+
meta: {
|
|
275
|
+
...DEFAULT_ROADMAP_STATE.meta,
|
|
276
|
+
roadmapVersion: String(meta.roadmapVersion || tracking.backlogMeta.roadmapVersion).trim(),
|
|
277
|
+
skillVersion: String(meta.skillVersion || tracking.backlogMeta.skillVersion).trim(),
|
|
278
|
+
status: String(meta.status || DEFAULT_ROADMAP_STATE.meta.status).trim(),
|
|
279
|
+
lastUpdated: String(meta.lastUpdated || tracking.lastSyncedAt).trim(),
|
|
280
|
+
currentFocusStage: String(meta.currentFocusStage || tracking.backlogMeta.currentFocusStage).trim()
|
|
281
|
+
},
|
|
282
|
+
context: {
|
|
283
|
+
...DEFAULT_ROADMAP_STATE.context,
|
|
284
|
+
...context,
|
|
285
|
+
canonicalTerms: normalizeStringList(context.canonicalTerms),
|
|
286
|
+
durableDecisionSources: normalizeStringList(context.durableDecisionSources)
|
|
287
|
+
},
|
|
288
|
+
evidence: Array.isArray(raw.evidence) ? raw.evidence : [],
|
|
289
|
+
route: {
|
|
290
|
+
...DEFAULT_ROADMAP_STATE.route,
|
|
291
|
+
...route,
|
|
292
|
+
rejectedRoutes: Array.isArray(route.rejectedRoutes) ? route.rejectedRoutes : []
|
|
293
|
+
},
|
|
294
|
+
stages: Array.isArray(raw.stages) ? raw.stages : [],
|
|
295
|
+
items: tracking.items,
|
|
296
|
+
backlogMeta: tracking.backlogMeta,
|
|
297
|
+
dependencyHandoff: tracking.dependencyHandoff,
|
|
298
|
+
lastSyncedAt: tracking.lastSyncedAt,
|
|
299
|
+
handoff: buildRoadmapHandoff(tracking, raw.handoff || {}),
|
|
300
|
+
architecture: {
|
|
301
|
+
...DEFAULT_ROADMAP_STATE.architecture,
|
|
302
|
+
...architecture,
|
|
303
|
+
nodes: Array.isArray(architecture.nodes) ? architecture.nodes : [],
|
|
304
|
+
edges: Array.isArray(architecture.edges) ? architecture.edges : []
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
191
309
|
const ROADMAP_HEADER_TO_KEY = new Map(
|
|
192
310
|
ROADMAP_COLUMNS.map(([header, key]) => [normalizeHeader(header), key])
|
|
193
311
|
);
|
|
@@ -225,6 +343,7 @@ const PARKED_FIELD_MAP = new Map(
|
|
|
225
343
|
module.exports = {
|
|
226
344
|
BACKLOG_QUEUE_COLUMNS,
|
|
227
345
|
BACKLOG_QUEUE_HEADER_TO_KEY,
|
|
346
|
+
DEFAULT_ROADMAP_STATE,
|
|
228
347
|
DEFAULT_TRACKING,
|
|
229
348
|
PARKED_FIELD_MAP,
|
|
230
349
|
READY_FIELD_MAP,
|
|
@@ -240,6 +359,7 @@ module.exports = {
|
|
|
240
359
|
normalizeCell,
|
|
241
360
|
normalizeHeader,
|
|
242
361
|
normalizeItem,
|
|
362
|
+
normalizeRoadmapState,
|
|
243
363
|
normalizeTracking,
|
|
244
364
|
parseList
|
|
245
365
|
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
2
3
|
|
|
3
4
|
const {
|
|
4
5
|
emptyBacklog,
|
|
5
6
|
normalizeItem,
|
|
7
|
+
normalizeRoadmapState,
|
|
6
8
|
normalizeTracking,
|
|
7
9
|
parseList
|
|
8
10
|
} = require('./schema');
|
|
@@ -63,7 +65,26 @@ function upgradeLegacyTracking(parsed) {
|
|
|
63
65
|
});
|
|
64
66
|
}
|
|
65
67
|
|
|
68
|
+
function isRoadmapStateFile(filePath) {
|
|
69
|
+
return path.basename(filePath || '') === 'roadmap.json';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function legacyTrackingFileFor(filePath) {
|
|
73
|
+
return path.join(path.dirname(filePath), 'roadmap-tracking.json');
|
|
74
|
+
}
|
|
75
|
+
|
|
66
76
|
function loadTracking({ trackingFile, roadmapFile = '', backlogFile = '' }) {
|
|
77
|
+
if (isRoadmapStateFile(trackingFile)) {
|
|
78
|
+
if (fs.existsSync(trackingFile)) {
|
|
79
|
+
return normalizeRoadmapState(readJson(trackingFile));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const legacyTrackingFile = legacyTrackingFileFor(trackingFile);
|
|
83
|
+
if (fs.existsSync(legacyTrackingFile)) {
|
|
84
|
+
return normalizeRoadmapState(readJson(legacyTrackingFile));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
67
88
|
if (trackingFile && fs.existsSync(trackingFile)) {
|
|
68
89
|
return upgradeLegacyTracking(readJson(trackingFile));
|
|
69
90
|
}
|
|
@@ -112,7 +133,10 @@ function applySyncArgs(tracking, args) {
|
|
|
112
133
|
}
|
|
113
134
|
|
|
114
135
|
function persistTrackingFiles({ trackingFile, roadmapFile, backlogFile, tracking }) {
|
|
115
|
-
writeJson(
|
|
136
|
+
writeJson(
|
|
137
|
+
trackingFile,
|
|
138
|
+
isRoadmapStateFile(trackingFile) ? normalizeRoadmapState(tracking) : tracking
|
|
139
|
+
);
|
|
116
140
|
|
|
117
141
|
const roadmapOutput = renderRoadmapDocument({
|
|
118
142
|
original: readFileIfExists(roadmapFile) || '# ROADMAP\n',
|
|
@@ -8,7 +8,7 @@ set -euo pipefail
|
|
|
8
8
|
|
|
9
9
|
usage() {
|
|
10
10
|
cat <<'EOF'
|
|
11
|
-
Usage: locate-roadmap-item.sh <ID> [--roadmap devflow/ROADMAP.md] [--backlog devflow/BACKLOG.md] [--tracking-file devflow/roadmap
|
|
11
|
+
Usage: locate-roadmap-item.sh <ID> [--roadmap devflow/ROADMAP.md] [--backlog devflow/BACKLOG.md] [--tracking-file devflow/roadmap.json]
|
|
12
12
|
|
|
13
13
|
ID can be RM-xxx or REQ-xxx.
|
|
14
14
|
EOF
|
|
@@ -22,8 +22,10 @@ LEGACY_ROADMAP_FILE="$REPO_ROOT/devflow/roadmap/roadmap.md"
|
|
|
22
22
|
DEFAULT_BACKLOG_FILE="$REPO_ROOT/devflow/BACKLOG.md"
|
|
23
23
|
ROOT_BACKLOG_FILE="$REPO_ROOT/BACKLOG.md"
|
|
24
24
|
LEGACY_BACKLOG_FILE="$REPO_ROOT/devflow/roadmap/backlog.md"
|
|
25
|
-
DEFAULT_TRACKING_FILE="$REPO_ROOT/devflow/roadmap
|
|
26
|
-
ROOT_TRACKING_FILE="$REPO_ROOT/roadmap
|
|
25
|
+
DEFAULT_TRACKING_FILE="$REPO_ROOT/devflow/roadmap.json"
|
|
26
|
+
ROOT_TRACKING_FILE="$REPO_ROOT/roadmap.json"
|
|
27
|
+
LEGACY_DEFAULT_TRACKING_FILE="$REPO_ROOT/devflow/roadmap-tracking.json"
|
|
28
|
+
LEGACY_ROOT_TRACKING_FILE="$REPO_ROOT/roadmap-tracking.json"
|
|
27
29
|
LEGACY_TRACKING_FILE="$REPO_ROOT/devflow/roadmap/roadmap-tracking.json"
|
|
28
30
|
ROADMAP_FILE="$DEFAULT_ROADMAP_FILE"
|
|
29
31
|
BACKLOG_FILE="$DEFAULT_BACKLOG_FILE"
|
|
@@ -40,7 +42,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
40
42
|
case "$1" in
|
|
41
43
|
--roadmap) ROADMAP_FILE="$2"; shift 2 ;;
|
|
42
44
|
--backlog) BACKLOG_FILE="$2"; shift 2 ;;
|
|
43
|
-
--tracking-file) TRACKING_FILE="$2"; shift 2 ;;
|
|
45
|
+
--tracking|--tracking-file) TRACKING_FILE="$2"; shift 2 ;;
|
|
44
46
|
-h|--help) usage; exit 0 ;;
|
|
45
47
|
*) echo "Unknown arg: $1" >&2; usage; exit 1 ;;
|
|
46
48
|
esac
|
|
@@ -64,10 +66,16 @@ fi
|
|
|
64
66
|
|
|
65
67
|
if [[ "$TRACKING_FILE" == "$DEFAULT_TRACKING_FILE" && ! -f "$TRACKING_FILE" ]]; then
|
|
66
68
|
roadmap_dir="$(cd "$(dirname "$ROADMAP_FILE")" 2>/dev/null && pwd || true)"
|
|
67
|
-
if [[ -n "$roadmap_dir" && -f "$roadmap_dir/roadmap
|
|
69
|
+
if [[ -n "$roadmap_dir" && -f "$roadmap_dir/roadmap.json" ]]; then
|
|
70
|
+
TRACKING_FILE="$roadmap_dir/roadmap.json"
|
|
71
|
+
elif [[ -n "$roadmap_dir" && -f "$roadmap_dir/roadmap-tracking.json" ]]; then
|
|
68
72
|
TRACKING_FILE="$roadmap_dir/roadmap-tracking.json"
|
|
69
73
|
elif [[ -f "$ROOT_TRACKING_FILE" ]]; then
|
|
70
74
|
TRACKING_FILE="$ROOT_TRACKING_FILE"
|
|
75
|
+
elif [[ -f "$LEGACY_DEFAULT_TRACKING_FILE" ]]; then
|
|
76
|
+
TRACKING_FILE="$LEGACY_DEFAULT_TRACKING_FILE"
|
|
77
|
+
elif [[ -f "$LEGACY_ROOT_TRACKING_FILE" ]]; then
|
|
78
|
+
TRACKING_FILE="$LEGACY_ROOT_TRACKING_FILE"
|
|
71
79
|
elif [[ -f "$LEGACY_TRACKING_FILE" ]]; then
|
|
72
80
|
TRACKING_FILE="$LEGACY_TRACKING_FILE"
|
|
73
81
|
fi
|
|
@@ -9,9 +9,9 @@ function usage() {
|
|
|
9
9
|
process.stderr.write(
|
|
10
10
|
[
|
|
11
11
|
'Usage:',
|
|
12
|
-
' roadmap-tracking.js sync --roadmap <ROADMAP.md> --backlog <BACKLOG.md> --tracking <roadmap
|
|
13
|
-
' roadmap-tracking.js render --roadmap <ROADMAP.md> --backlog <BACKLOG.md> --tracking <roadmap
|
|
14
|
-
' roadmap-tracking.js find --tracking <roadmap
|
|
12
|
+
' roadmap-tracking.js sync --roadmap <ROADMAP.md> --backlog <BACKLOG.md> --tracking <roadmap.json> --rm <RM-ID> [field updates]',
|
|
13
|
+
' roadmap-tracking.js render --roadmap <ROADMAP.md> --backlog <BACKLOG.md> --tracking <roadmap.json>',
|
|
14
|
+
' roadmap-tracking.js find --tracking <roadmap.json> --id <RM-ID|REQ-ID>',
|
|
15
15
|
'',
|
|
16
16
|
'Fields:',
|
|
17
17
|
' --item <title>',
|
|
@@ -11,7 +11,7 @@ usage() {
|
|
|
11
11
|
Usage: sync-roadmap-progress.sh --rm RM-001 [--status Planned] [--req REQ-001] [--progress 50%] [--file devflow/ROADMAP.md]
|
|
12
12
|
[--item "Add copy action"] [--stage "Stage 1"] [--priority P1] [--depends-on "RM-000"]
|
|
13
13
|
[--primary-capability cap-example] [--secondary-capabilities "cap-a,cap-b"] [--spec-delta "tighten truth"]
|
|
14
|
-
[--tracking-file devflow/roadmap
|
|
14
|
+
[--tracking-file devflow/roadmap.json] [--backlog-file devflow/BACKLOG.md]
|
|
15
15
|
EOF
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -49,7 +49,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
49
49
|
--secondary-capabilities) SECONDARY_CAPABILITIES="$2"; shift 2 ;;
|
|
50
50
|
--spec-delta) SPEC_DELTA="$2"; shift 2 ;;
|
|
51
51
|
--file) FILE="$2"; shift 2 ;;
|
|
52
|
-
--tracking-file) TRACKING_FILE="$2"; shift 2 ;;
|
|
52
|
+
--tracking|--tracking-file) TRACKING_FILE="$2"; shift 2 ;;
|
|
53
53
|
--backlog-file) BACKLOG_FILE="$2"; shift 2 ;;
|
|
54
54
|
-h|--help) usage; exit 0 ;;
|
|
55
55
|
*) echo "Unknown arg: $1" >&2; usage; exit 1 ;;
|
|
@@ -70,7 +70,7 @@ if [[ -z "$RM_ID" || ! -f "$FILE" ]]; then
|
|
|
70
70
|
fi
|
|
71
71
|
|
|
72
72
|
if [[ -z "$TRACKING_FILE" ]]; then
|
|
73
|
-
TRACKING_FILE="$(cd "$(dirname "$FILE")" && pwd)/roadmap
|
|
73
|
+
TRACKING_FILE="$(cd "$(dirname "$FILE")" && pwd)/roadmap.json"
|
|
74
74
|
fi
|
|
75
75
|
|
|
76
76
|
if [[ -z "$BACKLOG_FILE" ]]; then
|
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [4.5.5] - 2026-05-06
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Updated `cc-plan` and `cc-investigate` with Roadmap Sync Gates so frozen planning and root-cause handoffs reconcile source RM progress before moving to `cc-do`.
|
|
17
|
+
- Updated `cc-act` to check roadmap progress during closeout and to write source RM status through `devflow/roadmap.json` with regenerated `ROADMAP.md` / `BACKLOG.md` projections.
|
|
18
|
+
|
|
12
19
|
## [4.5.4] - 2026-04-29
|
|
13
20
|
|
|
14
21
|
### Fixed
|
package/README.md
CHANGED
|
@@ -62,7 +62,7 @@ After installation, ask your agent to use the workflow skills directly. Start wi
|
|
|
62
62
|
|
|
63
63
|
| Skill | Use it when | Main output |
|
|
64
64
|
| --- | --- | --- |
|
|
65
|
-
| `cc-roadmap` | You need product direction, staged scope, or backlog order | `devflow/ROADMAP.md`, `devflow/BACKLOG.md` |
|
|
65
|
+
| `cc-roadmap` | You need product direction, staged scope, or backlog order | `devflow/roadmap.json`, `devflow/ROADMAP.md`, deprecated `devflow/BACKLOG.md` |
|
|
66
66
|
| `cc-plan` | A feature or change needs scope, design, and task freezing | `planning/design.md`, `planning/tasks.md`, `task-manifest.json` |
|
|
67
67
|
| `cc-investigate` | A bug needs symptom, reproduction, root cause, and repair boundary | `planning/analysis.md`, `planning/tasks.md`, `task-manifest.json` |
|
|
68
68
|
| `cc-do` | Planned or investigated work needs implementation | code, tests, checkpoints, scratch runtime |
|
|
@@ -78,15 +78,15 @@ Maintenance skills are shipped with the pack:
|
|
|
78
78
|
|
|
79
79
|
`cc-roadmap` now records planning posture, evidence maturity, canonical project language, and durable decision context before recommending a route. That keeps idea-stage, active-user, paying-customer, infrastructure, and recovery work from being forced through the same questions, and prevents roadmap items from inventing a second vocabulary. Developer-facing or operator-facing roadmap items also carry target user, time to first value, magic moment, adoption bottleneck, and domain handoff into `cc-plan`.
|
|
80
80
|
|
|
81
|
-
Canonical language and durable decisions stay inside cc-devflow-native sources: `devflow/specs/`, `devflow/
|
|
81
|
+
Canonical language and durable decisions stay inside cc-devflow-native sources: `devflow/specs/`, `devflow/roadmap.json`, `devflow/ROADMAP.md`, `planning/design.md`, `planning/analysis.md`, and `change-meta.json`.
|
|
82
82
|
|
|
83
|
-
`cc-plan` freezes more implementation decisions before `cc-do` starts. Non-trivial plans compare minimal viable and ideal architecture options, full designs include decision horizon plus error/rescue mapping, and test-first plans record test framework evidence, public test seams, behavior assertions, mock boundaries, coverage quality, mandatory regression tests, interface depth, and vertical tracer-bullet slices when existing behavior changes.
|
|
83
|
+
`cc-plan` freezes more implementation decisions before `cc-do` starts. Non-trivial plans compare minimal viable and ideal architecture options, full designs include decision horizon plus error/rescue mapping, and test-first plans record test framework evidence, public test seams, spec-style test names, public verification paths, behavior assertions, mock boundaries, coverage quality, mandatory regression tests, interface depth, Green minimality guards, refactor candidates, and vertical tracer-bullet slices when existing behavior changes. Before handoff, `cc-plan` and `cc-investigate` also reconcile the source roadmap item so RM status, REQ/FIX binding, progress, and spec diagnosis do not drift from the frozen change artifacts.
|
|
84
84
|
|
|
85
85
|
## Verification And Ship Gates
|
|
86
86
|
|
|
87
87
|
`cc-check` now treats QA as a feedback-loop problem, not only a green-test problem. Bugfix and behavior work records the loop used to prove reality, expected versus actual behavior, reproduction steps, test boundary quality, and architecture follow-ups when no clean public test seam exists.
|
|
88
88
|
|
|
89
|
-
`cc-act` carries that evidence into PR briefs, handoffs, and release notes. Follow-ups must be durable behavior briefs with current behavior, desired behavior, key interfaces, acceptance criteria, and explicit out-of-scope notes before they are written back to roadmap or backlog.
|
|
89
|
+
`cc-act` carries that evidence into PR briefs, handoffs, and release notes. It checks source roadmap progress during closeout, updates `devflow/roadmap.json`, and regenerates `devflow/ROADMAP.md` / `devflow/BACKLOG.md` when verified reality changes. Follow-ups must be durable behavior briefs with current behavior, desired behavior, key interfaces, acceptance criteria, and explicit out-of-scope notes before they are written back to roadmap or backlog.
|
|
90
90
|
|
|
91
91
|
## Installation Modes
|
|
92
92
|
|
|
@@ -193,7 +193,7 @@ The currently distributed skill folders are:
|
|
|
193
193
|
## Durable vs Ephemeral
|
|
194
194
|
|
|
195
195
|
- `devflow/specs/` stores durable capability truth: `INDEX.md` plus `capabilities/*.md`.
|
|
196
|
-
- New change directories use `REQ-<number>-<description>` for requirements or `FIX-<number>-<description>` for bug fixes.
|
|
196
|
+
- New change directories use `REQ-<number>-<description>` for requirements or `FIX-<number>-<description>` for bug fixes. `REQ` and `FIX` numbers advance independently, so the same number may exist in both prefixes.
|
|
197
197
|
- `devflow/changes/<change>/` stores durable change truth: `change-state.json`, `change-meta.json`, planning docs, `task-manifest.json`, `team-state.json`, task `checkpoint.json`, `report-card.json`, and one final handoff file.
|
|
198
198
|
- `devflow/workspaces/<change>/` stores ephemeral runtime scratch such as worker assignment, journals, prompts, and session logs.
|
|
199
199
|
- Regenerable files should not be persisted under `devflow/changes/`.
|
package/README.zh-CN.md
CHANGED
|
@@ -62,7 +62,7 @@ npx cc-devflow@latest adapt --cwd /path/to/your/project --all
|
|
|
62
62
|
|
|
63
63
|
| Skill | 什么时候用 | 主要产物 |
|
|
64
64
|
| --- | --- | --- |
|
|
65
|
-
| `cc-roadmap` | 需要产品方向、阶段范围或 backlog 顺序 | `devflow/ROADMAP.md
|
|
65
|
+
| `cc-roadmap` | 需要产品方向、阶段范围或 backlog 顺序 | `devflow/roadmap.json`、`devflow/ROADMAP.md`、deprecated `devflow/BACKLOG.md` |
|
|
66
66
|
| `cc-plan` | 新功能或变更需要澄清范围、设计方案、冻结任务 | `planning/design.md`、`planning/tasks.md`、`task-manifest.json` |
|
|
67
67
|
| `cc-investigate` | Bug 需要症状、复现、根因和修复边界 | `planning/analysis.md`、`planning/tasks.md`、`task-manifest.json` |
|
|
68
68
|
| `cc-do` | 已计划或已调查的任务需要实现 | 代码、测试、checkpoint、scratch runtime |
|
|
@@ -78,15 +78,15 @@ npx cc-devflow@latest adapt --cwd /path/to/your/project --all
|
|
|
78
78
|
|
|
79
79
|
`cc-roadmap` 现在会先记录 planning posture、evidence maturity、项目 canonical language 和持久决策上下文,再推荐路线。idea、已有用户、付费客户、infra、recovery 场景不会被套进同一组问题,也不会让 roadmap item 发明第二套词汇。面向开发者或操作者的 roadmap item 还会把目标用户、time to first value、magic moment、adoption bottleneck 和 domain handoff 交给 `cc-plan`。
|
|
80
80
|
|
|
81
|
-
Canonical language 和 durable decisions 只收敛到 cc-devflow 原生真相源:`devflow/specs/`、`devflow/
|
|
81
|
+
Canonical language 和 durable decisions 只收敛到 cc-devflow 原生真相源:`devflow/specs/`、`devflow/roadmap.json`、`devflow/ROADMAP.md`、`planning/design.md`、`planning/analysis.md` 和 `change-meta.json`。
|
|
82
82
|
|
|
83
|
-
`cc-plan` 会在 `cc-do` 开始前冻结更多实现决策。非 trivial 计划需要比较 minimal viable 和 ideal architecture,full-design 需要包含 implementation decision horizon 和 error/rescue map;测试计划要记录测试框架证据、public test seam、behavior assertion、mock boundary、覆盖质量、强制 regression test、interface depth 和 vertical tracer-bullet slices
|
|
83
|
+
`cc-plan` 会在 `cc-do` 开始前冻结更多实现决策。非 trivial 计划需要比较 minimal viable 和 ideal architecture,full-design 需要包含 implementation decision horizon 和 error/rescue map;测试计划要记录测试框架证据、public test seam、spec-style test name、public verification path、behavior assertion、mock boundary、覆盖质量、强制 regression test、interface depth、Green minimality guard、refactor candidates 和 vertical tracer-bullet slices。交接前,`cc-plan` 和 `cc-investigate` 还会校准 source roadmap item,让 RM 状态、REQ/FIX 绑定、progress 和 spec diagnosis 不再漂移。
|
|
84
84
|
|
|
85
85
|
## 验证与交付门禁
|
|
86
86
|
|
|
87
87
|
`cc-check` 现在把 QA 当成反馈环问题,而不是只看测试是否绿。Bugfix 和行为变更需要记录证明现实的 loop、expected / actual、复现步骤、测试边界质量;如果没有干净的 public test seam,要留下架构 follow-up。
|
|
88
88
|
|
|
89
|
-
`cc-act` 会把这些证据带进 PR brief、handoff 和 release note
|
|
89
|
+
`cc-act` 会把这些证据带进 PR brief、handoff 和 release note。它会在 closeout 检查 source roadmap progress,必要时更新 `devflow/roadmap.json` 并重新生成 `devflow/ROADMAP.md` / `devflow/BACKLOG.md`。Follow-up 必须写成 durable behavior brief,包含 current behavior、desired behavior、key interfaces、acceptance criteria 和 out-of-scope,再回写 roadmap 或 backlog。
|
|
90
90
|
|
|
91
91
|
## 安装方式
|
|
92
92
|
|
|
@@ -193,7 +193,7 @@ npx cc-devflow config doctor --cwd /path/to/your/project
|
|
|
193
193
|
## Durable 与 Ephemeral
|
|
194
194
|
|
|
195
195
|
- `devflow/specs/` 保存 durable capability truth:`INDEX.md` 和 `capabilities/*.md`。
|
|
196
|
-
- 新 change 目录使用 `REQ-<number>-<description>` 表示需求,使用 `FIX-<number>-<description>` 表示 Bug
|
|
196
|
+
- 新 change 目录使用 `REQ-<number>-<description>` 表示需求,使用 `FIX-<number>-<description>` 表示 Bug 修复。`REQ` 和 `FIX` 各自递增自己的编号,跨前缀同号允许共存。
|
|
197
197
|
- `devflow/changes/<change>/` 保存 durable change truth:`change-state.json`、`change-meta.json`、planning 文档、`task-manifest.json`、`team-state.json`、任务级 `checkpoint.json`、`report-card.json` 和唯一最终 handoff 文件。
|
|
198
198
|
- `devflow/workspaces/<change>/` 保存 ephemeral runtime scratch,例如 worker assignment、journal、prompt 和 session log。
|
|
199
199
|
- 能从 durable truth 再生成的文件,不应该持久化到 `devflow/changes/`。
|
package/docs/CLAUDE.md
CHANGED
|
@@ -27,4 +27,4 @@ docs/
|
|
|
27
27
|
- 面向使用者:优先写“怎么用/怎么做”,其次再写“为什么”。
|
|
28
28
|
- 可检索:标题清晰、关键词统一(`/flow-*`、`/core-*`、`/speckit.*`)。
|
|
29
29
|
- 可落地:结论必须能映射到具体命令、脚本或模板文件路径。
|
|
30
|
-
- change 目录命名必须保留大写逻辑 ID 前缀:`REQ-123-...` 表示需求变更,`FIX-123-...`
|
|
30
|
+
- change 目录命名必须保留大写逻辑 ID 前缀:`REQ-123-...` 表示需求变更,`FIX-123-...` 表示缺陷修复;`REQ` 和 `FIX` 是独立编号空间;描述部分使用 kebab-case。
|
|
@@ -64,9 +64,9 @@ Use this when the only thing you know is the file in front of you.
|
|
|
64
64
|
|
|
65
65
|
| If the main file you have is... | You are probably here | Read this first |
|
|
66
66
|
| --- | --- | --- |
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
69
|
-
| `BACKLOG.md` | `cc-roadmap` -> `cc-plan`
|
|
67
|
+
| `roadmap.json` | `cc-roadmap` editable machine truth source | [pdca-loop/roadmap.json](./pdca-loop/roadmap.json) |
|
|
68
|
+
| `ROADMAP.md` | `cc-roadmap` generated human view | [pdca-loop/ROADMAP.md](./pdca-loop/ROADMAP.md) |
|
|
69
|
+
| `BACKLOG.md` | deprecated `cc-roadmap` -> `cc-plan` projection | [pdca-loop/BACKLOG.md](./pdca-loop/BACKLOG.md) |
|
|
70
70
|
| `design.md` | `cc-plan` | [pdca-loop/design.md](./pdca-loop/changes/REQ-001-copy-invite-link/planning/design.md) or [full-design-blocked/design.md](./full-design-blocked/changes/REQ-002-bulk-invite-import/planning/design.md) |
|
|
71
71
|
| `tasks.md` | `cc-plan` or `cc-do` | [pdca-loop/tasks.md](./pdca-loop/changes/REQ-001-copy-invite-link/planning/tasks.md) |
|
|
72
72
|
| `task-manifest.json` | `cc-do` | [pdca-loop/task-manifest.json](./pdca-loop/changes/REQ-001-copy-invite-link/planning/task-manifest.json) |
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
"updatedAt": "2026-
|
|
2
|
+
"updatedAt": "2026-05-06",
|
|
3
3
|
"skills": {
|
|
4
|
-
"cc-roadmap": "
|
|
5
|
-
"cc-plan": "3.7.
|
|
6
|
-
"cc-investigate": "1.2.
|
|
7
|
-
"cc-do": "1.6.
|
|
4
|
+
"cc-roadmap": "5.0.0",
|
|
5
|
+
"cc-plan": "3.7.5",
|
|
6
|
+
"cc-investigate": "1.2.2",
|
|
7
|
+
"cc-do": "1.6.2",
|
|
8
8
|
"cc-check": "1.10.1",
|
|
9
|
-
"cc-act": "1.8.
|
|
9
|
+
"cc-act": "1.8.2",
|
|
10
10
|
"cc-spec-init": "1.1.0"
|
|
11
11
|
},
|
|
12
12
|
"examples": [
|
|
@@ -15,7 +15,13 @@
|
|
|
15
15
|
"readme": "docs/examples/pdca-loop/README.md",
|
|
16
16
|
"root": "docs/examples/pdca-loop",
|
|
17
17
|
"changeDir": "docs/examples/pdca-loop/changes/REQ-001-copy-invite-link",
|
|
18
|
-
"covers": [
|
|
18
|
+
"covers": [
|
|
19
|
+
"cc-roadmap",
|
|
20
|
+
"cc-plan",
|
|
21
|
+
"cc-do",
|
|
22
|
+
"cc-check",
|
|
23
|
+
"cc-act"
|
|
24
|
+
],
|
|
19
25
|
"expectedShipMode": "create-pr"
|
|
20
26
|
},
|
|
21
27
|
{
|
|
@@ -23,7 +29,12 @@
|
|
|
23
29
|
"readme": "docs/examples/full-design-blocked/README.md",
|
|
24
30
|
"root": "docs/examples/full-design-blocked",
|
|
25
31
|
"changeDir": "docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import",
|
|
26
|
-
"covers": [
|
|
32
|
+
"covers": [
|
|
33
|
+
"cc-roadmap",
|
|
34
|
+
"cc-plan",
|
|
35
|
+
"cc-do",
|
|
36
|
+
"cc-check"
|
|
37
|
+
],
|
|
27
38
|
"expectedShipMode": "none"
|
|
28
39
|
},
|
|
29
40
|
{
|
|
@@ -31,7 +42,13 @@
|
|
|
31
42
|
"readme": "docs/examples/local-handoff/README.md",
|
|
32
43
|
"root": "docs/examples/local-handoff",
|
|
33
44
|
"changeDir": "docs/examples/local-handoff/changes/REQ-003-audit-log-export",
|
|
34
|
-
"covers": [
|
|
45
|
+
"covers": [
|
|
46
|
+
"cc-roadmap",
|
|
47
|
+
"cc-plan",
|
|
48
|
+
"cc-do",
|
|
49
|
+
"cc-check",
|
|
50
|
+
"cc-act"
|
|
51
|
+
],
|
|
35
52
|
"expectedShipMode": "local-handoff"
|
|
36
53
|
}
|
|
37
54
|
]
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# BACKLOG
|
|
2
2
|
|
|
3
|
+
> Deprecated projection. Edit `roadmap.json` instead.
|
|
4
|
+
|
|
3
5
|
## Backlog Meta
|
|
4
6
|
|
|
5
7
|
- Roadmap version: `roadmap.v2`
|
|
6
|
-
- Skill version: `
|
|
8
|
+
- Skill version: `5.0.0`
|
|
7
9
|
- Last synced: `2026-04-19`
|
|
8
10
|
- Current focus stage: `Stage 2`
|
|
9
|
-
-
|
|
11
|
+
- Roadmap state source: `roadmap.json`
|
|
10
12
|
|
|
11
13
|
## Queue
|
|
12
14
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
- Example version: `1.0.0`
|
|
6
6
|
- Last reviewed: `2026-04-17`
|
|
7
|
-
- Bound skills: `cc-roadmap@
|
|
7
|
+
- Bound skills: `cc-roadmap@5.0.0`, `cc-plan@3.7.5`, `cc-do@1.6.2`, `cc-check@1.10.1`
|
|
8
8
|
|
|
9
9
|
This example shows a requirement that **looked executable**, but `cc-check` correctly stopped it and sent it back to `cc-plan`.
|
|
10
10
|
|
|
@@ -40,9 +40,9 @@ The sample shows what happens when implementation moved before the integration d
|
|
|
40
40
|
|
|
41
41
|
## Artifact Map
|
|
42
42
|
|
|
43
|
-
- `
|
|
44
|
-
- `
|
|
45
|
-
- `BACKLOG.md`
|
|
43
|
+
- `roadmap.json` (editable roadmap truth)
|
|
44
|
+
- `ROADMAP.md` (generated view)
|
|
45
|
+
- `BACKLOG.md` (deprecated projection)
|
|
46
46
|
- `changes/REQ-002-bulk-invite-import/planning/design.md`
|
|
47
47
|
- `changes/REQ-002-bulk-invite-import/planning/tasks.md`
|
|
48
48
|
- `changes/REQ-002-bulk-invite-import/planning/task-manifest.json`
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
## Roadmap Meta
|
|
4
4
|
|
|
5
5
|
- Roadmap version: `roadmap.v2`
|
|
6
|
-
- Skill version: `
|
|
6
|
+
- Skill version: `5.0.0`
|
|
7
7
|
- Status: `active`
|
|
8
8
|
- Last updated: `2026-04-16`
|
|
9
9
|
- Owner / decider: `product-owner`
|
|
@@ -44,10 +44,24 @@
|
|
|
44
44
|
- Kill signal / stop condition: if the team cannot specify bulk invite semantics before implementation starts
|
|
45
45
|
|
|
46
46
|
## Implementation Tracking
|
|
47
|
-
-
|
|
47
|
+
- Roadmap state source: `roadmap.json`
|
|
48
48
|
|
|
49
49
|
<!-- roadmap-tracking:start -->
|
|
50
50
|
| RM-ID | Item | Stage | Priority | Primary Capability | Secondary Capabilities | Expected Spec Delta | Depends On | Status | REQ | Progress |
|
|
51
51
|
|------|------|------|------|------|------|------|------|------|------|------|
|
|
52
52
|
| RM-010 | Add CSV bulk invite import for admins | Stage 2 | P1 | cap-bulk-invite-import | cap-workspace-membership | define import semantics before widening current truth | - | Verification blocked | REQ-002 | 80% |
|
|
53
53
|
<!-- roadmap-tracking:end -->
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
## Technical Architecture
|
|
57
|
+
|
|
58
|
+
```mermaid
|
|
59
|
+
flowchart TD
|
|
60
|
+
roadmap_json["roadmap.json"]
|
|
61
|
+
roadmap_md["ROADMAP.md"]
|
|
62
|
+
backlog_md["BACKLOG.md (deprecated)"]
|
|
63
|
+
cc_plan["cc-plan"]
|
|
64
|
+
roadmap_json -->|renders| roadmap_md
|
|
65
|
+
roadmap_json -->|projects| backlog_md
|
|
66
|
+
roadmap_md -->|hands off| cc_plan
|
|
67
|
+
```
|
package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/design.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
- Requirement version: `REQ-002.v2`
|
|
6
6
|
- Design version: `design.v2`
|
|
7
|
-
- CC-Plan skill version: `3.7.
|
|
7
|
+
- CC-Plan skill version: `3.7.5`
|
|
8
8
|
- Requirement ID: `REQ-002`
|
|
9
9
|
- Design mode: `full-design`
|
|
10
10
|
- Why not `tiny-design`: the feature crosses import parsing, invite rules, billing limits, duplicate handling, and audit logging
|
|
@@ -42,6 +42,43 @@
|
|
|
42
42
|
- enterprise SCIM provisioning
|
|
43
43
|
- background retry orchestration
|
|
44
44
|
|
|
45
|
+
## PRD-Grade Requirement Brief
|
|
46
|
+
|
|
47
|
+
- Problem statement: admins onboarding larger teams spend too much time sending individual invites, and they cannot predict how duplicates, invalid rows, and seat limits will resolve in bulk.
|
|
48
|
+
- Solution summary: admins upload a CSV and receive deterministic row outcomes before the invite flow can be trusted for execution.
|
|
49
|
+
- Actors / personas:
|
|
50
|
+
- workspace admin onboarding 20-200 collaborators
|
|
51
|
+
- support operator explaining invite outcomes
|
|
52
|
+
- Primary user stories:
|
|
53
|
+
|
|
54
|
+
| ID | Actor | Wants | Benefit | Acceptance / evidence |
|
|
55
|
+
|----|-------|-------|---------|-----------------------|
|
|
56
|
+
| US-001 | Workspace admin | upload a CSV of invite emails | invite many collaborators without one-by-one entry | mixed valid rows produce visible accepted outcomes |
|
|
57
|
+
| US-002 | Workspace admin | see duplicate, invalid, and over-limit row states | understand what happened without support help | every skipped or rejected row has a reason |
|
|
58
|
+
| US-003 | Support operator | trust the audit trail for each row outcome | explain invite history consistently | audit entries match visible row outcomes |
|
|
59
|
+
|
|
60
|
+
- Edge / recovery stories:
|
|
61
|
+
|
|
62
|
+
| ID | Actor | Failure / boundary | Desired outcome | Acceptance / evidence |
|
|
63
|
+
|----|-------|--------------------|-----------------|-----------------------|
|
|
64
|
+
| US-EDGE-001 | Workspace admin | CSV contains duplicates and invalid emails | safe rows can proceed while bad rows are explained | rule matrix covers duplicate and invalid cases |
|
|
65
|
+
| US-EDGE-002 | Workspace admin | upload exceeds seat limits | over-limit rows are rejected consistently | billing-seat tests match UI summary |
|
|
66
|
+
|
|
67
|
+
- Implementation decisions:
|
|
68
|
+
- Freeze one row-outcome matrix before execution resumes.
|
|
69
|
+
- Reuse the existing invite engine, billing seat checks, and audit log contract.
|
|
70
|
+
- Keep enterprise provisioning and background retry orchestration outside this requirement.
|
|
71
|
+
- Testing decisions:
|
|
72
|
+
- Test row semantics through bulk-import rules and the admin upload flow.
|
|
73
|
+
- Verify audit mapping against visible row outcomes.
|
|
74
|
+
- Use existing invite and admin panel tests as prior art.
|
|
75
|
+
- Out of scope:
|
|
76
|
+
- enterprise SCIM provisioning
|
|
77
|
+
- background job redesign
|
|
78
|
+
- rollback wizard for partial success
|
|
79
|
+
- Further notes:
|
|
80
|
+
- This design remains blocked until duplicate and seat-limit semantics are approved.
|
|
81
|
+
|
|
45
82
|
## Success Criteria
|
|
46
83
|
|
|
47
84
|
- Observable success signals:
|
|
@@ -131,6 +168,7 @@
|
|
|
131
168
|
- Ambiguity scan: blocked; duplicate + seat-limit semantics still need sharper wording
|
|
132
169
|
- Feasibility scan: pass
|
|
133
170
|
- Source alignment: pass; roadmap still prioritizes trust over speed
|
|
171
|
+
- PRD brief scan: pass for actors and stories; blocked on duplicate and seat-limit semantics
|
|
134
172
|
- UI / interaction review summary: result states are acceptable if semantics are frozen first
|
|
135
173
|
- DX review summary: execution still needs a single row-outcome matrix
|
|
136
174
|
- Auto-decided items:
|
|
@@ -5,6 +5,47 @@
|
|
|
5
5
|
"updatedAt": "2026-04-16T12:00:00.000Z",
|
|
6
6
|
"requirementId": "REQ-002",
|
|
7
7
|
"requirementVersion": "REQ-002.v2",
|
|
8
|
+
"planningMeta": {
|
|
9
|
+
"reqPlanSkillVersion": "3.7.5",
|
|
10
|
+
"designVersion": "design.v2",
|
|
11
|
+
"approvedAt": null,
|
|
12
|
+
"approvedBy": null,
|
|
13
|
+
"basedOnOption": "Option B",
|
|
14
|
+
"requirementBrief": {
|
|
15
|
+
"problemStatement": "Admins onboarding larger teams need predictable bulk invite behavior for duplicates, invalid rows, and seat limits.",
|
|
16
|
+
"solutionSummary": "Freeze deterministic CSV row outcomes before executing the bulk invite flow.",
|
|
17
|
+
"actors": ["workspace admin", "support operator"],
|
|
18
|
+
"userStories": [
|
|
19
|
+
{
|
|
20
|
+
"id": "US-001",
|
|
21
|
+
"actor": "workspace admin",
|
|
22
|
+
"want": "upload a CSV of invite emails",
|
|
23
|
+
"benefit": "invite many collaborators without one-by-one entry",
|
|
24
|
+
"acceptance": ["Mixed valid rows produce visible accepted outcomes"]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "US-002",
|
|
28
|
+
"actor": "workspace admin",
|
|
29
|
+
"want": "see duplicate, invalid, and over-limit row states",
|
|
30
|
+
"benefit": "understand what happened without support help",
|
|
31
|
+
"acceptance": ["Every skipped or rejected row has a reason"]
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"edgeOrRecoveryStories": [
|
|
35
|
+
{
|
|
36
|
+
"id": "US-EDGE-001",
|
|
37
|
+
"actor": "workspace admin",
|
|
38
|
+
"boundary": "CSV contains duplicates, invalid emails, or over-limit rows",
|
|
39
|
+
"desiredOutcome": "safe rows can proceed while bad rows are explained",
|
|
40
|
+
"acceptance": ["Rule matrix covers duplicate, invalid, and seat-limit cases"]
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"implementationDecisions": ["Freeze one row-outcome matrix before execution resumes"],
|
|
44
|
+
"testingDecisions": ["Test row semantics through bulk-import rules and the admin upload flow"],
|
|
45
|
+
"outOfScope": ["enterprise SCIM provisioning", "background job redesign", "rollback wizard for partial success"],
|
|
46
|
+
"furtherNotes": ["Design remains blocked until duplicate and seat-limit semantics are approved"]
|
|
47
|
+
}
|
|
48
|
+
},
|
|
8
49
|
"currentTaskId": null,
|
|
9
50
|
"activePhase": null,
|
|
10
51
|
"tasks": [
|