gswd 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/gswd/architecture-drafter.md +70 -0
- package/agents/gswd/brainstorm-alternatives.md +60 -0
- package/agents/gswd/devils-advocate.md +57 -0
- package/agents/gswd/icp-persona.md +58 -0
- package/agents/gswd/integrations-checker.md +68 -0
- package/agents/gswd/journey-mapper.md +69 -0
- package/agents/gswd/market-researcher.md +54 -0
- package/agents/gswd/positioning.md +54 -0
- package/bin/gswd-tools.cjs +716 -0
- package/lib/audit.ts +959 -0
- package/lib/bootstrap.ts +617 -0
- package/lib/compile.ts +940 -0
- package/lib/config.ts +164 -0
- package/lib/imagine-agents.ts +154 -0
- package/lib/imagine-gate.ts +156 -0
- package/lib/imagine-input.ts +242 -0
- package/lib/imagine-synthesis.ts +402 -0
- package/lib/imagine.ts +433 -0
- package/lib/parse.ts +196 -0
- package/lib/render.ts +200 -0
- package/lib/specify-agents.ts +332 -0
- package/lib/specify-journeys.ts +410 -0
- package/lib/specify-nfr.ts +208 -0
- package/lib/specify-roles.ts +122 -0
- package/lib/specify.ts +773 -0
- package/lib/state.ts +305 -0
- package/package.json +26 -0
- package/templates/gswd/ARCHITECTURE.template.md +17 -0
- package/templates/gswd/AUDIT.template.md +31 -0
- package/templates/gswd/COMPETITION.template.md +18 -0
- package/templates/gswd/DECISIONS.template.md +18 -0
- package/templates/gswd/GTM.template.md +18 -0
- package/templates/gswd/ICP.template.md +18 -0
- package/templates/gswd/IMAGINE.template.md +24 -0
- package/templates/gswd/INTEGRATIONS.template.md +7 -0
- package/templates/gswd/JOURNEYS.template.md +7 -0
- package/templates/gswd/NFR.template.md +7 -0
- package/templates/gswd/PROJECT.template.md +21 -0
- package/templates/gswd/REQUIREMENTS.template.md +31 -0
- package/templates/gswd/ROADMAP.template.md +21 -0
- package/templates/gswd/SPEC.template.md +19 -0
- package/templates/gswd/STATE.template.md +15 -0
package/lib/state.ts
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GSWD State Module — STATE.json CRUD with atomic writes
|
|
3
|
+
*
|
|
4
|
+
* All file writes use the atomic pattern: write to .tmp -> verify -> rename.
|
|
5
|
+
* STATE.json is updated only AFTER artifact writes complete.
|
|
6
|
+
*
|
|
7
|
+
* Schema: GSWD_SPEC.md Section 5.1
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import * as fs from 'node:fs';
|
|
11
|
+
import * as path from 'node:path';
|
|
12
|
+
|
|
13
|
+
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
export interface StageStatus {
|
|
16
|
+
imagine: 'not_started' | 'in_progress' | 'done';
|
|
17
|
+
specify: 'not_started' | 'in_progress' | 'done';
|
|
18
|
+
audit: 'not_started' | 'in_progress' | 'pass' | 'fail';
|
|
19
|
+
compile: 'not_started' | 'in_progress' | 'done';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface Checkpoint {
|
|
23
|
+
workflow: string;
|
|
24
|
+
checkpoint_id: string;
|
|
25
|
+
timestamp: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface PaidIntegration {
|
|
29
|
+
integration_id: string;
|
|
30
|
+
name: string;
|
|
31
|
+
monthly_cost_usd: number;
|
|
32
|
+
status: 'approved' | 'rejected';
|
|
33
|
+
approved_at: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface IdRange {
|
|
37
|
+
agent: string;
|
|
38
|
+
start: number;
|
|
39
|
+
end: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface IdRegistry {
|
|
43
|
+
allocated_ranges: Record<string, IdRange[]>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface GswdState {
|
|
47
|
+
version: number;
|
|
48
|
+
project_slug: string;
|
|
49
|
+
created_at: string;
|
|
50
|
+
updated_at: string;
|
|
51
|
+
stage: 'init' | 'imagine' | 'specify' | 'audit' | 'compile' | 'done';
|
|
52
|
+
stage_status: StageStatus;
|
|
53
|
+
last_checkpoint: Checkpoint | null;
|
|
54
|
+
auto: {
|
|
55
|
+
enabled: boolean;
|
|
56
|
+
policy: 'strict' | 'balanced' | 'aggressive';
|
|
57
|
+
interrupt_reasons: string[];
|
|
58
|
+
decisions?: Array<{ type: string; chosen: string; rationale: string; score?: number; recorded_at: string }>;
|
|
59
|
+
};
|
|
60
|
+
approvals: {
|
|
61
|
+
auth_model: string;
|
|
62
|
+
data_store: string;
|
|
63
|
+
paid_integrations: PaidIntegration[];
|
|
64
|
+
};
|
|
65
|
+
id_registry?: IdRegistry;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ─── Atomic File I/O ─────────────────────────────────────────────────────────
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Atomically write a file: write to .tmp, verify, rename.
|
|
72
|
+
* Cleans up .tmp on any failure.
|
|
73
|
+
*/
|
|
74
|
+
export function safeWriteFile(filePath: string, content: string): void {
|
|
75
|
+
const tmpPath = filePath + '.tmp';
|
|
76
|
+
const dir = path.dirname(filePath);
|
|
77
|
+
|
|
78
|
+
// Ensure parent directory exists
|
|
79
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
// Write to temp file
|
|
83
|
+
fs.writeFileSync(tmpPath, content, 'utf-8');
|
|
84
|
+
|
|
85
|
+
// Verify temp file was written correctly
|
|
86
|
+
const written = fs.readFileSync(tmpPath, 'utf-8');
|
|
87
|
+
if (written !== content) {
|
|
88
|
+
throw new Error(`Write verification failed for ${filePath}: content mismatch`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Atomic rename (atomic on Unix/macOS)
|
|
92
|
+
fs.renameSync(tmpPath, filePath);
|
|
93
|
+
} catch (err) {
|
|
94
|
+
// Clean up .tmp on any failure
|
|
95
|
+
try {
|
|
96
|
+
if (fs.existsSync(tmpPath)) {
|
|
97
|
+
fs.unlinkSync(tmpPath);
|
|
98
|
+
}
|
|
99
|
+
} catch {
|
|
100
|
+
// Ignore cleanup errors
|
|
101
|
+
}
|
|
102
|
+
throw err;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Atomically write JSON: pretty-print, atomic write, then verify round-trip.
|
|
108
|
+
*/
|
|
109
|
+
export function safeWriteJson(filePath: string, data: unknown): void {
|
|
110
|
+
const content = JSON.stringify(data, null, 2) + '\n';
|
|
111
|
+
safeWriteFile(filePath, content);
|
|
112
|
+
|
|
113
|
+
// Post-rename verification: re-read and parse
|
|
114
|
+
const verify = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
115
|
+
if (JSON.stringify(verify) !== JSON.stringify(data)) {
|
|
116
|
+
throw new Error(`JSON round-trip verification failed for ${filePath}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ─── State CRUD ──────────────────────────────────────────────────────────────
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Create a default STATE.json object matching GSWD_SPEC Section 5.1.
|
|
124
|
+
*/
|
|
125
|
+
export function createDefaultState(projectSlug: string): GswdState {
|
|
126
|
+
const now = new Date().toISOString();
|
|
127
|
+
return {
|
|
128
|
+
version: 1,
|
|
129
|
+
project_slug: projectSlug,
|
|
130
|
+
created_at: now,
|
|
131
|
+
updated_at: now,
|
|
132
|
+
stage: 'init',
|
|
133
|
+
stage_status: {
|
|
134
|
+
imagine: 'not_started',
|
|
135
|
+
specify: 'not_started',
|
|
136
|
+
audit: 'not_started',
|
|
137
|
+
compile: 'not_started',
|
|
138
|
+
},
|
|
139
|
+
last_checkpoint: null,
|
|
140
|
+
auto: {
|
|
141
|
+
enabled: false,
|
|
142
|
+
policy: 'balanced',
|
|
143
|
+
interrupt_reasons: [],
|
|
144
|
+
decisions: [],
|
|
145
|
+
},
|
|
146
|
+
approvals: {
|
|
147
|
+
auth_model: 'unapproved',
|
|
148
|
+
data_store: 'unapproved',
|
|
149
|
+
paid_integrations: [],
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Read STATE.json. Returns null if file doesn't exist or is invalid JSON.
|
|
156
|
+
*/
|
|
157
|
+
export function readState(statePath: string): GswdState | null {
|
|
158
|
+
try {
|
|
159
|
+
const content = fs.readFileSync(statePath, 'utf-8');
|
|
160
|
+
const parsed = JSON.parse(content);
|
|
161
|
+
// Basic validation: check required top-level fields
|
|
162
|
+
if (typeof parsed.version !== 'number' || typeof parsed.project_slug !== 'string') {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
return parsed as GswdState;
|
|
166
|
+
} catch {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Write STATE.json atomically. Updates updated_at timestamp.
|
|
173
|
+
*/
|
|
174
|
+
export function writeState(statePath: string, state: GswdState): void {
|
|
175
|
+
state.updated_at = new Date().toISOString();
|
|
176
|
+
safeWriteJson(statePath, state);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Idempotent init: create STATE.json only if missing or corrupt.
|
|
181
|
+
* If valid state exists, returns it unchanged (no timestamp update).
|
|
182
|
+
*/
|
|
183
|
+
export function initState(stateDir: string, projectSlug: string): GswdState {
|
|
184
|
+
const statePath = path.join(stateDir, 'STATE.json');
|
|
185
|
+
|
|
186
|
+
// Try reading existing state
|
|
187
|
+
const existing = readState(statePath);
|
|
188
|
+
if (existing !== null) {
|
|
189
|
+
return existing;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Create new state
|
|
193
|
+
const state = createDefaultState(projectSlug);
|
|
194
|
+
safeWriteJson(statePath, state);
|
|
195
|
+
return state;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Update a specific stage status. Read-modify-write pattern.
|
|
200
|
+
*/
|
|
201
|
+
export function updateStageStatus(
|
|
202
|
+
statePath: string,
|
|
203
|
+
stage: keyof StageStatus,
|
|
204
|
+
status: string
|
|
205
|
+
): void {
|
|
206
|
+
const state = readState(statePath);
|
|
207
|
+
if (!state) {
|
|
208
|
+
throw new Error(`Cannot read STATE.json at ${statePath}`);
|
|
209
|
+
}
|
|
210
|
+
(state.stage_status as Record<string, string>)[stage] = status;
|
|
211
|
+
writeState(statePath, state);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Write a checkpoint to STATE.json.
|
|
216
|
+
*/
|
|
217
|
+
export function writeCheckpoint(
|
|
218
|
+
statePath: string,
|
|
219
|
+
workflow: string,
|
|
220
|
+
checkpointId: string
|
|
221
|
+
): void {
|
|
222
|
+
const state = readState(statePath);
|
|
223
|
+
if (!state) {
|
|
224
|
+
throw new Error(`Cannot read STATE.json at ${statePath}`);
|
|
225
|
+
}
|
|
226
|
+
state.last_checkpoint = {
|
|
227
|
+
workflow,
|
|
228
|
+
checkpoint_id: checkpointId,
|
|
229
|
+
timestamp: new Date().toISOString(),
|
|
230
|
+
};
|
|
231
|
+
writeState(statePath, state);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// ─── ID Registry ─────────────────────────────────────────────────────────────
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Allocate an ID range for an agent. Ranges are non-overlapping per ID type.
|
|
238
|
+
*/
|
|
239
|
+
export function allocateIdRange(
|
|
240
|
+
statePath: string,
|
|
241
|
+
idType: string,
|
|
242
|
+
agentName: string,
|
|
243
|
+
rangeSize: number = 50
|
|
244
|
+
): { start: number; end: number } {
|
|
245
|
+
const state = readState(statePath);
|
|
246
|
+
if (!state) {
|
|
247
|
+
throw new Error(`Cannot read STATE.json at ${statePath}`);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (!state.id_registry) {
|
|
251
|
+
state.id_registry = { allocated_ranges: {} };
|
|
252
|
+
}
|
|
253
|
+
if (!state.id_registry.allocated_ranges[idType]) {
|
|
254
|
+
state.id_registry.allocated_ranges[idType] = [];
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const ranges = state.id_registry.allocated_ranges[idType];
|
|
258
|
+
const lastEnd = ranges.length > 0
|
|
259
|
+
? Math.max(...ranges.map(r => r.end))
|
|
260
|
+
: 0;
|
|
261
|
+
|
|
262
|
+
const newRange: IdRange = {
|
|
263
|
+
agent: agentName,
|
|
264
|
+
start: lastEnd + 1,
|
|
265
|
+
end: lastEnd + rangeSize,
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
ranges.push(newRange);
|
|
269
|
+
writeState(statePath, state);
|
|
270
|
+
|
|
271
|
+
return { start: newRange.start, end: newRange.end };
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Get allocated ID ranges, optionally filtered by type.
|
|
276
|
+
*/
|
|
277
|
+
export function getIdRanges(
|
|
278
|
+
statePath: string,
|
|
279
|
+
idType?: string
|
|
280
|
+
): Record<string, IdRange[]> {
|
|
281
|
+
const state = readState(statePath);
|
|
282
|
+
if (!state || !state.id_registry) {
|
|
283
|
+
return {};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (idType) {
|
|
287
|
+
const ranges = state.id_registry.allocated_ranges[idType];
|
|
288
|
+
return ranges ? { [idType]: ranges } : {};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return state.id_registry.allocated_ranges;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Reset all allocated ID ranges.
|
|
296
|
+
*/
|
|
297
|
+
export function resetIdRegistry(statePath: string): void {
|
|
298
|
+
const state = readState(statePath);
|
|
299
|
+
if (!state) {
|
|
300
|
+
throw new Error(`Cannot read STATE.json at ${statePath}`);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
state.id_registry = { allocated_ranges: {} };
|
|
304
|
+
writeState(statePath, state);
|
|
305
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gswd",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "commonjs",
|
|
5
|
+
"description": "Get Shit Well Done — CLI meta-prompting and spec-generation system",
|
|
6
|
+
"bin": {
|
|
7
|
+
"gswd": "./bin/gswd-tools.cjs",
|
|
8
|
+
"gswd-tools": "./bin/gswd-tools.cjs"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin/",
|
|
12
|
+
"lib/",
|
|
13
|
+
"templates/",
|
|
14
|
+
"agents/"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "node --import tsx --test tests/*.test.ts",
|
|
18
|
+
"test:cjs": "node --test tests/*.test.cjs",
|
|
19
|
+
"build": "tsc"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"typescript": "^5.7.0",
|
|
23
|
+
"@types/node": "^22.0.0",
|
|
24
|
+
"tsx": "^4.19.0"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Audit Report
|
|
2
|
+
|
|
3
|
+
**Date:** {date}
|
|
4
|
+
**Result:** {PASS|FAIL}
|
|
5
|
+
**Summary:** {passed}/{total} checks passed, {findings} issue(s) found
|
|
6
|
+
|
|
7
|
+
## Coverage Matrix
|
|
8
|
+
|
|
9
|
+
| Journey | Linked FRs | Linked NFRs | Acceptance Tests | Integrations | Status |
|
|
10
|
+
|---------|------------|-------------|------------------|--------------|--------|
|
|
11
|
+
|
|
12
|
+
## Coverage Statistics
|
|
13
|
+
|
|
14
|
+
| Metric | Count |
|
|
15
|
+
|--------|-------|
|
|
16
|
+
| Journeys | {N} |
|
|
17
|
+
| Functional Requirements | {N} |
|
|
18
|
+
| Non-Functional Requirements | {N} |
|
|
19
|
+
| Integrations | {N} |
|
|
20
|
+
|
|
21
|
+
## Check Results
|
|
22
|
+
|
|
23
|
+
### Journey FR Coverage
|
|
24
|
+
### Journey Test Coverage
|
|
25
|
+
### Orphan v1 FRs
|
|
26
|
+
### Integration Approval
|
|
27
|
+
### Required Headings
|
|
28
|
+
|
|
29
|
+
## Actionable Checklist
|
|
30
|
+
|
|
31
|
+
{Only present on FAIL}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Competition
|
|
2
|
+
|
|
3
|
+
## Market Overview
|
|
4
|
+
<!-- GSWD:CONTENT market_overview -->
|
|
5
|
+
|
|
6
|
+
## Competitors
|
|
7
|
+
<!-- GSWD:CONTENT competitors -->
|
|
8
|
+
|
|
9
|
+
## Market Gaps
|
|
10
|
+
<!-- GSWD:CONTENT gaps -->
|
|
11
|
+
|
|
12
|
+
## Opportunities
|
|
13
|
+
<!-- GSWD:CONTENT opportunities -->
|
|
14
|
+
|
|
15
|
+
## Competitive Positioning
|
|
16
|
+
<!-- GSWD:CONTENT competitive_positioning -->
|
|
17
|
+
|
|
18
|
+
<!-- GSWD:COMPLETE -->
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Decisions
|
|
2
|
+
|
|
3
|
+
## Frozen Decisions
|
|
4
|
+
<!-- GSWD:CONTENT - Minimum 8 frozen decisions required -->
|
|
5
|
+
|
|
6
|
+
## Success Metrics
|
|
7
|
+
<!-- GSWD:CONTENT - 1-3 measurable success metrics -->
|
|
8
|
+
|
|
9
|
+
## Out of Scope
|
|
10
|
+
<!-- GSWD:CONTENT - Explicit exclusions -->
|
|
11
|
+
|
|
12
|
+
## Risks & Mitigations
|
|
13
|
+
<!-- GSWD:CONTENT - Minimum 5 risks with mitigations -->
|
|
14
|
+
|
|
15
|
+
## Open Questions
|
|
16
|
+
<!-- GSWD:CONTENT - Unresolved questions for future resolution -->
|
|
17
|
+
|
|
18
|
+
<!-- GSWD:COMPLETE -->
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Go-to-Market
|
|
2
|
+
|
|
3
|
+
## Value Proposition
|
|
4
|
+
<!-- GSWD:CONTENT value_prop -->
|
|
5
|
+
|
|
6
|
+
## Positioning Statement
|
|
7
|
+
<!-- GSWD:CONTENT positioning -->
|
|
8
|
+
|
|
9
|
+
## Key Differentiators
|
|
10
|
+
<!-- GSWD:CONTENT differentiators -->
|
|
11
|
+
|
|
12
|
+
## Go-to-Market Angle
|
|
13
|
+
<!-- GSWD:CONTENT gtm_angle -->
|
|
14
|
+
|
|
15
|
+
## Early Traction Strategy
|
|
16
|
+
<!-- GSWD:CONTENT traction -->
|
|
17
|
+
|
|
18
|
+
<!-- GSWD:COMPLETE -->
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Ideal Customer Profile
|
|
2
|
+
|
|
3
|
+
## ICP Profile
|
|
4
|
+
<!-- GSWD:CONTENT icp_profile -->
|
|
5
|
+
|
|
6
|
+
## Pain Points
|
|
7
|
+
<!-- GSWD:CONTENT pain_points -->
|
|
8
|
+
|
|
9
|
+
## Willingness to Pay
|
|
10
|
+
<!-- GSWD:CONTENT wtp -->
|
|
11
|
+
|
|
12
|
+
## Reachability
|
|
13
|
+
<!-- GSWD:CONTENT reachability -->
|
|
14
|
+
|
|
15
|
+
## Behavioral Traits
|
|
16
|
+
<!-- GSWD:CONTENT traits -->
|
|
17
|
+
|
|
18
|
+
<!-- GSWD:COMPLETE -->
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Imagine
|
|
2
|
+
|
|
3
|
+
## Vision
|
|
4
|
+
<!-- GSWD:CONTENT vision -->
|
|
5
|
+
|
|
6
|
+
## Target User
|
|
7
|
+
<!-- GSWD:CONTENT target_user -->
|
|
8
|
+
|
|
9
|
+
## Problem Statement
|
|
10
|
+
<!-- GSWD:CONTENT problem -->
|
|
11
|
+
|
|
12
|
+
## Product Direction
|
|
13
|
+
<!-- GSWD:CONTENT direction -->
|
|
14
|
+
|
|
15
|
+
## Alternatives
|
|
16
|
+
<!-- GSWD:CONTENT alternatives -->
|
|
17
|
+
|
|
18
|
+
## Wedge / MVP Boundary
|
|
19
|
+
<!-- GSWD:CONTENT wedge -->
|
|
20
|
+
|
|
21
|
+
## Success Metrics
|
|
22
|
+
<!-- GSWD:CONTENT metrics -->
|
|
23
|
+
|
|
24
|
+
<!-- GSWD:COMPLETE -->
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# {project_slug}
|
|
2
|
+
|
|
3
|
+
## What This Is
|
|
4
|
+
<!-- Compiled from IMAGINE.md vision -->
|
|
5
|
+
|
|
6
|
+
## Target User
|
|
7
|
+
<!-- Compiled from IMAGINE.md target user / ICP -->
|
|
8
|
+
|
|
9
|
+
## Problem Statement
|
|
10
|
+
<!-- Compiled from IMAGINE.md product direction -->
|
|
11
|
+
|
|
12
|
+
## Wedge / MVP Boundary
|
|
13
|
+
<!-- Compiled from IMAGINE.md wedge -->
|
|
14
|
+
|
|
15
|
+
## Success Metrics
|
|
16
|
+
<!-- Compiled from DECISIONS.md success metrics -->
|
|
17
|
+
|
|
18
|
+
## Out of Scope
|
|
19
|
+
<!-- Compiled from DECISIONS.md out of scope -->
|
|
20
|
+
|
|
21
|
+
<!-- GSWD:COMPILED -->
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Requirements
|
|
2
|
+
|
|
3
|
+
## Functional Requirements
|
|
4
|
+
|
|
5
|
+
### v1 (In Scope)
|
|
6
|
+
<!-- FRs with Scope: v1, sorted by Priority then ID -->
|
|
7
|
+
|
|
8
|
+
### v2 (Future)
|
|
9
|
+
<!-- FRs with Scope: v2, sorted by Priority then ID -->
|
|
10
|
+
|
|
11
|
+
## Non-Functional Requirements
|
|
12
|
+
|
|
13
|
+
### Security
|
|
14
|
+
<!-- NFRs in security category -->
|
|
15
|
+
|
|
16
|
+
### Privacy
|
|
17
|
+
<!-- NFRs in privacy category -->
|
|
18
|
+
|
|
19
|
+
### Performance
|
|
20
|
+
<!-- NFRs in performance category -->
|
|
21
|
+
|
|
22
|
+
### Observability
|
|
23
|
+
<!-- NFRs in observability category -->
|
|
24
|
+
|
|
25
|
+
## Traceability
|
|
26
|
+
|
|
27
|
+
<!-- FR-to-Journey mapping table for v1 FRs -->
|
|
28
|
+
| FR | Description | Journeys |
|
|
29
|
+
|----|-------------|----------|
|
|
30
|
+
|
|
31
|
+
<!-- GSWD:COMPILED -->
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
v1 journeys assigned to 4 phases following deterministic rules.
|
|
6
|
+
|
|
7
|
+
## Phases
|
|
8
|
+
|
|
9
|
+
### Phase 1: Skeleton & Core Loop
|
|
10
|
+
<!-- onboarding + core_action journeys -->
|
|
11
|
+
|
|
12
|
+
### Phase 2: Persistence & History
|
|
13
|
+
<!-- view_results journeys -->
|
|
14
|
+
|
|
15
|
+
### Phase 3: Polish: errors, empty states, settings
|
|
16
|
+
<!-- error_states + empty_states + settings journeys -->
|
|
17
|
+
|
|
18
|
+
### Phase 4: Observability & Hardening
|
|
19
|
+
<!-- Observability + security NFRs (no journeys) -->
|
|
20
|
+
|
|
21
|
+
<!-- GSWD:COMPILED -->
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Specification
|
|
2
|
+
|
|
3
|
+
## Roles & Permissions
|
|
4
|
+
|
|
5
|
+
<!-- GSWD:CONTENT:ROLES -->
|
|
6
|
+
|
|
7
|
+
## Functional Requirements
|
|
8
|
+
|
|
9
|
+
<!-- GSWD:CONTENT:FRS -->
|
|
10
|
+
|
|
11
|
+
## Acceptance Criteria
|
|
12
|
+
|
|
13
|
+
<!-- GSWD:CONTENT:ACCEPTANCE -->
|
|
14
|
+
|
|
15
|
+
## Traceability
|
|
16
|
+
|
|
17
|
+
<!-- GSWD:CONTENT:TRACEABILITY -->
|
|
18
|
+
|
|
19
|
+
<!-- GSWD:COMPLETE -->
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Project State
|
|
2
|
+
|
|
3
|
+
## Frozen Decisions
|
|
4
|
+
<!-- Numbered list from DECISIONS.md -->
|
|
5
|
+
|
|
6
|
+
## Approvals
|
|
7
|
+
<!-- Auth model, data store, paid integrations from STATE.json -->
|
|
8
|
+
|
|
9
|
+
## Open Questions
|
|
10
|
+
<!-- Bulleted list from DECISIONS.md -->
|
|
11
|
+
|
|
12
|
+
## Risks
|
|
13
|
+
<!-- Bulleted list from DECISIONS.md risks & mitigations -->
|
|
14
|
+
|
|
15
|
+
<!-- GSWD:COMPILED -->
|