@howlil/ez-agents 3.4.2 → 3.5.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.
Files changed (74) hide show
  1. package/README.md +77 -2
  2. package/agents/ez-observer-agent.md +260 -0
  3. package/agents/ez-release-agent.md +333 -0
  4. package/agents/ez-requirements-agent.md +377 -0
  5. package/agents/ez-scrum-master-agent.md +242 -0
  6. package/agents/ez-tech-lead-agent.md +267 -0
  7. package/bin/install.js +3221 -3272
  8. package/commands/ez/arch-review.md +102 -0
  9. package/commands/ez/execute-phase.md +11 -0
  10. package/commands/ez/export-session.md +79 -0
  11. package/commands/ez/gather-requirements.md +117 -0
  12. package/commands/ez/git-workflow.md +72 -0
  13. package/commands/ez/hotfix.md +120 -0
  14. package/commands/ez/import-session.md +82 -0
  15. package/commands/ez/list-sessions.md +96 -0
  16. package/commands/ez/package-manager.md +316 -0
  17. package/commands/ez/plan-phase.md +9 -1
  18. package/commands/ez/preflight.md +79 -0
  19. package/commands/ez/progress.md +13 -1
  20. package/commands/ez/release.md +153 -0
  21. package/commands/ez/resume.md +107 -0
  22. package/commands/ez/standup.md +85 -0
  23. package/ez-agents/bin/ez-tools.cjs +1095 -716
  24. package/ez-agents/bin/lib/bdd-validator.cjs +622 -0
  25. package/ez-agents/bin/lib/content-scanner.cjs +238 -0
  26. package/ez-agents/bin/lib/context-cache.cjs +154 -0
  27. package/ez-agents/bin/lib/context-errors.cjs +71 -0
  28. package/ez-agents/bin/lib/context-manager.cjs +220 -0
  29. package/ez-agents/bin/lib/discussion-synthesizer.cjs +458 -0
  30. package/ez-agents/bin/lib/file-access.cjs +207 -0
  31. package/ez-agents/bin/lib/git-errors.cjs +83 -0
  32. package/ez-agents/bin/lib/git-utils.cjs +321 -203
  33. package/ez-agents/bin/lib/git-workflow-engine.cjs +1157 -0
  34. package/ez-agents/bin/lib/index.cjs +46 -2
  35. package/ez-agents/bin/lib/lockfile-validator.cjs +227 -0
  36. package/ez-agents/bin/lib/logger.cjs +124 -154
  37. package/ez-agents/bin/lib/memory-compression.cjs +256 -0
  38. package/ez-agents/bin/lib/metrics-tracker.cjs +406 -0
  39. package/ez-agents/bin/lib/package-manager-detector.cjs +203 -0
  40. package/ez-agents/bin/lib/package-manager-executor.cjs +385 -0
  41. package/ez-agents/bin/lib/package-manager-service.cjs +216 -0
  42. package/ez-agents/bin/lib/release-validator.cjs +614 -0
  43. package/ez-agents/bin/lib/safe-exec.cjs +128 -214
  44. package/ez-agents/bin/lib/session-chain.cjs +304 -0
  45. package/ez-agents/bin/lib/session-errors.cjs +81 -0
  46. package/ez-agents/bin/lib/session-export.cjs +251 -0
  47. package/ez-agents/bin/lib/session-import.cjs +262 -0
  48. package/ez-agents/bin/lib/session-manager.cjs +280 -0
  49. package/ez-agents/bin/lib/tier-manager.cjs +428 -0
  50. package/ez-agents/bin/lib/url-fetch.cjs +170 -0
  51. package/ez-agents/references/metrics-schema.md +118 -0
  52. package/ez-agents/references/planning-config.md +140 -0
  53. package/ez-agents/references/tier-strategy.md +103 -0
  54. package/ez-agents/templates/bdd-feature.md +173 -0
  55. package/ez-agents/templates/discussion.md +68 -0
  56. package/ez-agents/templates/incident-runbook.md +205 -0
  57. package/ez-agents/templates/release-checklist.md +133 -0
  58. package/ez-agents/templates/rollback-plan.md +201 -0
  59. package/ez-agents/workflows/arch-review.md +54 -0
  60. package/ez-agents/workflows/autonomous.md +844 -743
  61. package/ez-agents/workflows/execute-phase.md +45 -0
  62. package/ez-agents/workflows/export-session.md +255 -0
  63. package/ez-agents/workflows/gather-requirements.md +206 -0
  64. package/ez-agents/workflows/help.md +92 -0
  65. package/ez-agents/workflows/hotfix.md +291 -0
  66. package/ez-agents/workflows/import-session.md +303 -0
  67. package/ez-agents/workflows/new-milestone.md +713 -384
  68. package/ez-agents/workflows/new-project.md +1107 -1113
  69. package/ez-agents/workflows/plan-phase.md +22 -0
  70. package/ez-agents/workflows/progress.md +15 -25
  71. package/ez-agents/workflows/release.md +253 -0
  72. package/ez-agents/workflows/resume-session.md +215 -0
  73. package/ez-agents/workflows/standup.md +64 -0
  74. package/package.json +9 -2
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * URL Fetch Service
5
+ *
6
+ * Provides secure URL fetching with HTTPS validation and user confirmation.
7
+ * Only HTTPS URLs are allowed. HTTP, file, data, javascript, and vbscript protocols are blocked.
8
+ */
9
+
10
+ const { URL } = require('url');
11
+ const { URLFetchError } = require('./context-errors.cjs');
12
+
13
+ const DEFAULT_TIMEOUT = 30000; // 30 seconds
14
+ const BLOCKED_PROTOCOLS = ['http:', 'file:', 'data:', 'javascript:', 'vbscript:'];
15
+
16
+ class URLValidator {
17
+ /**
18
+ * Validate a URL string
19
+ * @param {string} urlString - The URL to validate
20
+ * @returns {{valid: boolean, error?: string}} - Validation result
21
+ */
22
+ static validate(urlString) {
23
+ if (!urlString || typeof urlString !== 'string') {
24
+ return { valid: false, error: 'URL is required' };
25
+ }
26
+
27
+ try {
28
+ const url = new URL(urlString);
29
+
30
+ // Check protocol
31
+ if (url.protocol !== 'https:') {
32
+ if (BLOCKED_PROTOCOLS.includes(url.protocol)) {
33
+ return {
34
+ valid: false,
35
+ error: `Protocol '${url.protocol}' is not allowed. Only HTTPS is permitted.`
36
+ };
37
+ }
38
+ return {
39
+ valid: false,
40
+ error: `Invalid protocol '${url.protocol}'. Only HTTPS is allowed.`
41
+ };
42
+ }
43
+
44
+ // Check hostname exists
45
+ if (!url.hostname || url.hostname.trim() === '') {
46
+ return { valid: false, error: 'Invalid URL: missing hostname' };
47
+ }
48
+
49
+ // Reject localhost URLs
50
+ if (url.hostname === 'localhost' ||
51
+ url.hostname === '127.0.0.1' ||
52
+ url.hostname === '::1' ||
53
+ url.hostname.endsWith('.localhost')) {
54
+ return {
55
+ valid: false,
56
+ error: 'Localhost URLs are not allowed. Use a publicly accessible HTTPS URL.'
57
+ };
58
+ }
59
+
60
+ return { valid: true };
61
+ } catch (err) {
62
+ return {
63
+ valid: false,
64
+ error: `Invalid URL format: ${err.message}`
65
+ };
66
+ }
67
+ }
68
+ }
69
+
70
+ class URLFetchService {
71
+ /**
72
+ * Create a new URLFetchService instance
73
+ * @param {number} timeout - Request timeout in milliseconds (default: 30000)
74
+ */
75
+ constructor(timeout = DEFAULT_TIMEOUT) {
76
+ this.timeout = timeout;
77
+ }
78
+
79
+ /**
80
+ * Validate a URL
81
+ * @param {string} urlString - The URL to validate
82
+ * @returns {{valid: boolean, error?: string}} - Validation result
83
+ */
84
+ validateUrl(urlString) {
85
+ return URLValidator.validate(urlString);
86
+ }
87
+
88
+ /**
89
+ * Fetch content from a URL
90
+ * @param {string} url - The URL to fetch
91
+ * @returns {{content: string, contentType: string}} - Fetched content
92
+ * @throws {URLFetchError} - On fetch errors
93
+ */
94
+ async fetchUrl(url) {
95
+ // Validate URL first
96
+ const validation = this.validateUrl(url);
97
+ if (!validation.valid) {
98
+ throw new URLFetchError(url, validation.error);
99
+ }
100
+
101
+ try {
102
+ // Create abort controller for timeout
103
+ const controller = new AbortController();
104
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
105
+
106
+ const response = await fetch(url, {
107
+ headers: {
108
+ 'User-Agent': 'ez-agents/1.0'
109
+ },
110
+ signal: controller.signal,
111
+ redirect: 'follow'
112
+ });
113
+
114
+ clearTimeout(timeoutId);
115
+
116
+ // Check for HTTP errors
117
+ if (!response.ok) {
118
+ throw new URLFetchError(
119
+ url,
120
+ `HTTP ${response.status}: ${response.statusText}`
121
+ );
122
+ }
123
+
124
+ // Get content type
125
+ const contentType = response.headers.get('content-type') || 'text/plain';
126
+
127
+ // Get content
128
+ const content = await response.text();
129
+
130
+ return {
131
+ content,
132
+ contentType
133
+ };
134
+ } catch (err) {
135
+ if (err.name === 'AbortError') {
136
+ throw new URLFetchError(url, `Request timeout after ${this.timeout}ms`);
137
+ }
138
+
139
+ if (err.name === 'URLFetchError') {
140
+ throw err;
141
+ }
142
+
143
+ throw new URLFetchError(url, `Network error: ${err.message}`);
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Prompt user for confirmation before fetching a URL
149
+ * @param {string} url - The URL to fetch
150
+ * @returns {Promise<boolean>} - True if user confirmed
151
+ */
152
+ static async confirmUrlFetch(url) {
153
+ const readline = require('readline');
154
+
155
+ return new Promise((resolve) => {
156
+ const rl = readline.createInterface({
157
+ input: process.stdin,
158
+ output: process.stdout
159
+ });
160
+
161
+ rl.question(`Fetch ${url}? (y/n): `, (answer) => {
162
+ rl.close();
163
+ resolve(answer.toLowerCase() === 'y');
164
+ });
165
+ });
166
+ }
167
+ }
168
+
169
+ module.exports = URLFetchService;
170
+ module.exports.URLValidator = URLValidator;
@@ -0,0 +1,118 @@
1
+ # Metrics Schema Reference
2
+
3
+ Schema for `.planning/metrics.json` — the EZ Agents success metrics store.
4
+
5
+ ## Full Schema
6
+
7
+ ```json
8
+ {
9
+ "schema_version": "1.0",
10
+ "project": "project-name",
11
+ "updated": "2026-03-19T00:00:00Z",
12
+
13
+ "phase_metrics": [
14
+ {
15
+ "phase": 18,
16
+ "phase_name": "session-memory",
17
+ "plans_total": 4,
18
+ "plans_completed": 4,
19
+ "velocity_min": 24,
20
+ "defect_density": 0.12,
21
+ "bdd_pass_rate": 0.84,
22
+ "bdd_must_passing": 8,
23
+ "bdd_must_total": 9,
24
+ "deviation_count": 2,
25
+ "completed_at": "2026-03-19T00:00:00Z"
26
+ }
27
+ ],
28
+
29
+ "project_metrics": {
30
+ "requirements_coverage_pct": 78,
31
+ "test_coverage_pct": 74,
32
+ "bdd_scenarios_total": 60,
33
+ "bdd_scenarios_passing": 45,
34
+ "bdd_scenarios_must": 25,
35
+ "bdd_scenarios_must_passing": 24
36
+ },
37
+
38
+ "agent_metrics": {
39
+ "total_token_cost_usd": 18.40,
40
+ "avg_cost_per_plan": 0.27,
41
+ "deviation_rate": 0.15,
42
+ "avg_plans_per_phase": 3.2,
43
+ "avg_velocity_min_per_plan": 22
44
+ },
45
+
46
+ "business_metrics": {
47
+ "time_to_first_ship_days": 95,
48
+ "hotfixes_deployed": 0,
49
+ "milestones_shipped": 1,
50
+ "current_tier": "medium",
51
+ "phases_total": 29,
52
+ "phases_completed": 18
53
+ }
54
+ }
55
+ ```
56
+
57
+ ## Field Definitions
58
+
59
+ ### phase_metrics[]
60
+
61
+ | Field | Type | Source | Description |
62
+ |-------|------|--------|-------------|
63
+ | `phase` | int | ez-executor | Phase number |
64
+ | `plans_total` | int | ez-executor | Plans in phase |
65
+ | `plans_completed` | int | ez-executor | Plans with SUMMARY.md |
66
+ | `velocity_min` | int | ez-executor | Minutes from first to last commit in phase |
67
+ | `defect_density` | float | ez-executor | Deviations / tasks executed |
68
+ | `bdd_pass_rate` | float | ez-verifier | @must scenarios passing / total @must |
69
+ | `deviation_count` | int | ez-executor | Auto-fix deviations logged |
70
+
71
+ ### project_metrics
72
+
73
+ | Field | Type | Source | Description |
74
+ |-------|------|--------|-------------|
75
+ | `requirements_coverage_pct` | int | ez-executor | % of REQUIREMENTS.md checked off |
76
+ | `test_coverage_pct` | int | ez-verifier | From coverage tool output |
77
+ | `bdd_scenarios_passing` | int | ez-verifier | Scenarios with green status |
78
+
79
+ ### agent_metrics
80
+
81
+ | Field | Type | Source | Description |
82
+ |-------|------|--------|-------------|
83
+ | `total_token_cost_usd` | float | metrics-tracker | Accumulated from state.record-metric |
84
+ | `avg_cost_per_plan` | float | metrics-tracker | total / plans_completed |
85
+ | `deviation_rate` | float | metrics-tracker | total_deviations / total_tasks |
86
+
87
+ ### business_metrics
88
+
89
+ | Field | Type | Source | Description |
90
+ |-------|------|--------|-------------|
91
+ | `time_to_first_ship_days` | int | ez-release-agent | Days from project init to first release |
92
+ | `hotfixes_deployed` | int | ez-release-agent | Hotfixes tagged and pushed |
93
+ | `current_tier` | string | tier-manager | mvp / medium / enterprise |
94
+
95
+ ## Capture Points
96
+
97
+ | Metric | When Captured | Who Captures |
98
+ |--------|---------------|--------------|
99
+ | velocity_min | After SUMMARY.md created | ez-executor (state record-metric) |
100
+ | deviation_count | During execution | ez-executor (per deviation Rule 1-3) |
101
+ | defect_density | After plan completes | ez-executor (computed) |
102
+ | bdd_pass_rate | After VERIFICATION.md | ez-verifier (metrics record-bdd) |
103
+ | test_coverage_pct | After verification | ez-verifier (from coverage tool) |
104
+ | requirements_coverage_pct | After mark-complete | ez-executor (computed from REQUIREMENTS.md) |
105
+ | total_token_cost_usd | Ongoing | ez-executor (from state.record-metric cost field) |
106
+ | hotfixes_deployed | After hotfix tag | ez-release-agent |
107
+
108
+ ## Dashboard Output
109
+
110
+ ```
111
+ /ez:stats → enhanced dashboard
112
+
113
+ PROGRESS: Phase 18/29 (62%) | Requirements 78% | BDD 80%
114
+ VELOCITY: 22 min/plan avg | Trend: ↑ IMPROVING
115
+ QUALITY: Coverage 74% | Defect density 0.12 | Deviation 15%
116
+ COSTS: $18.40 total | $0.27/plan | Est. remaining: ~$3.00
117
+ RELEASE: Tier: Medium | Hotfixes: 0 | Blockers: 0
118
+ ```
@@ -197,4 +197,144 @@ Squash merge is recommended — keeps main branch history clean while preserving
197
197
 
198
198
  </branching_strategy_behavior>
199
199
 
200
+
201
+ <smart_orchestration_config>
202
+
203
+ **`smart_orchestration` block:**
204
+
205
+ ```json
206
+ "smart_orchestration": {
207
+ "enabled": true,
208
+ "show_auto_prefix": true,
209
+ "auto_invoke": {
210
+ "preflight": ["progress", "execute-phase"],
211
+ "arch_review": ["execute-phase"],
212
+ "standup": []
213
+ }
214
+ }
215
+ ```
216
+
217
+ | Option | Default | Description |
218
+ |--------|---------|-------------|
219
+ | `enabled` | `true` | Master toggle for smart orchestration auto-invocations |
220
+ | `show_auto_prefix` | `true` | Prefix auto-invoked agent output with `[AUTO]` label |
221
+ | `auto_invoke.preflight` | `["progress", "execute-phase"]` | Commands that silently run health check before executing |
222
+ | `auto_invoke.arch_review` | `["execute-phase"]` | Commands that auto-spawn tech lead review when `agent_discussion` enabled |
223
+ | `auto_invoke.standup` | `[]` | Commands that auto-generate standup before running |
224
+
225
+ **Disabling per-invocation:** Pass `--no-auto` flag to any command to skip smart orchestration for that run.
226
+
227
+ </smart_orchestration_config>
228
+
229
+ <agent_discussion_config>
230
+
231
+ **`agent_discussion` block:**
232
+
233
+ ```json
234
+ "agent_discussion": {
235
+ "enabled": false,
236
+ "pre_flight_observer": false,
237
+ "tech_lead_review": false,
238
+ "scrum_master_standup": false,
239
+ "cost_warning": true
240
+ }
241
+ ```
242
+
243
+ | Option | Default | Description |
244
+ |--------|---------|-------------|
245
+ | `enabled` | `false` | Master toggle for optional discussion agents |
246
+ | `pre_flight_observer` | `false` | Spawn observer agent before execution to surface risks |
247
+ | `tech_lead_review` | `false` | Auto-spawn tech lead review after `/ez:plan-phase` completes |
248
+ | `scrum_master_standup` | `false` | Auto-generate standup report at session start |
249
+ | `cost_warning` | `true` | Warn before spawning expensive agents (Opus-class) |
250
+
251
+ **Enable via `/ez:settings`:** The settings workflow provides a guided UI for toggling these options. Avoid manual JSON edits.
252
+
253
+ </agent_discussion_config>
254
+
255
+ <sessions_config>
256
+
257
+ **`sessions` block:**
258
+
259
+ ```json
260
+ "sessions": {
261
+ "retention_policy": "keep_last_10",
262
+ "auto_compress_threshold": 50,
263
+ "chain_navigation_enabled": true
264
+ }
265
+ ```
266
+
267
+ | Option | Default | Description |
268
+ |--------|---------|-------------|
269
+ | `retention_policy` | `"keep_last_10"` | How many sessions to retain. Options: `"keep_all"`, `"keep_last_N"`, `"keep_days_N"` |
270
+ | `auto_compress_threshold` | `50` | Compress session memory when token count exceeds this (in thousands) |
271
+ | `chain_navigation_enabled` | `true` | Enable `--previous`/`--next`/`--chain` flags in `/ez:resume` |
272
+
273
+ **Session files location:** `.planning/sessions/` — each session is a JSON file. Use `/ez:export-session` and `/ez:import-session` for cross-model handoffs.
274
+
275
+ </sessions_config>
276
+
277
+ <release_tiers_config>
278
+
279
+ **`release.tiers` block:**
280
+
281
+ ```json
282
+ "release": {
283
+ "tier": "mvp",
284
+ "tiers": {
285
+ "mvp": {
286
+ "coverage_threshold": 0,
287
+ "checklist_items": ["build_passes", "no_blockers"],
288
+ "git_strategy": "direct_to_main"
289
+ },
290
+ "medium": {
291
+ "coverage_threshold": 60,
292
+ "checklist_items": ["build_passes", "no_blockers", "tests_pass", "security_scan"],
293
+ "git_strategy": "pr_required"
294
+ },
295
+ "enterprise": {
296
+ "coverage_threshold": 80,
297
+ "checklist_items": ["build_passes", "no_blockers", "tests_pass", "security_scan", "coverage_gate", "changelog_updated", "rollback_plan"],
298
+ "git_strategy": "gitflow"
299
+ }
300
+ }
301
+ }
302
+ ```
303
+
304
+ | Tier | Coverage | Git Strategy | Checklist |
305
+ |------|----------|--------------|-----------|
306
+ | `mvp` | None | Direct to main | Build + no blockers |
307
+ | `medium` | 60% | PR required | Build + tests + security scan |
308
+ | `enterprise` | 80% | GitFlow (main + develop) | Full gates including rollback plan |
309
+
310
+ **Hotfix behavior by tier:** MVP hotfixes merge directly; Medium requires PR; Enterprise merges to main AND syncs to develop. See `/ez:hotfix` documentation.
311
+
312
+ **Set tier:** `node "$HOME/.claude/ez-agents/bin/ez-tools.cjs" config-set release.tier enterprise`
313
+
314
+ </release_tiers_config>
315
+
316
+ <package_manager_config>
317
+
318
+ **`packageManager` block:**
319
+
320
+ ```json
321
+ "packageManager": {
322
+ "default": "npm",
323
+ "autoDetect": true,
324
+ "respectLockfile": true
325
+ }
326
+ ```
327
+
328
+ | Option | Default | Description |
329
+ |--------|---------|-------------|
330
+ | `default` | `"npm"` | Fallback package manager when auto-detection fails. Options: `"npm"`, `"yarn"`, `"pnpm"`, `"bun"` |
331
+ | `autoDetect` | `true` | Detect package manager from lock file presence (`yarn.lock`, `pnpm-lock.yaml`, `bun.lockb`) |
332
+ | `respectLockfile` | `true` | Use `--frozen-lockfile` / `--ci` flags during install to prevent lock file mutations |
333
+
334
+ **Auto-detection order:** `bun.lockb` → bun, `pnpm-lock.yaml` → pnpm, `yarn.lock` → yarn, `package-lock.json` → npm, fallback to `default`.
335
+
336
+ **Set explicitly:** `node "$HOME/.claude/ez-agents/bin/ez-tools.cjs" config-set packageManager.default pnpm`
337
+
338
+ </package_manager_config>
339
+
200
340
  </planning_config>
@@ -0,0 +1,103 @@
1
+ # Tier Strategy Reference
2
+
3
+ Decision reference for git branching and release strategy per tier.
4
+
5
+ ## Quick Decision Matrix
6
+
7
+ | Question | MVP | Medium | Enterprise |
8
+ |----------|-----|--------|------------|
9
+ | Git strategy | Trunk (tag main) | GitHub Flow | GitFlow |
10
+ | Release branch | None | `release/vX.Y.Z` | `release/vX.Y.Z` from develop |
11
+ | Hotfix to develop? | No | No | Yes |
12
+ | PR required? | No | Yes (optional) | Yes (required) |
13
+ | Coverage gate | 60% | 80% | 95% |
14
+ | Checklist items | 6 | 18 | 30 |
15
+ | MoSCoW scope | @must | @must + @should | All |
16
+ | Rollback window | 30 min | 15 min | 5 min |
17
+
18
+ ## When to Use Each Tier
19
+
20
+ **MVP** — You need to ship NOW
21
+ - First public release
22
+ - Early access / beta
23
+ - Founder-driven sales demo
24
+ - Internal tool, no SLA
25
+
26
+ **Medium** — Real users, real consequences
27
+ - General availability
28
+ - Paying customers
29
+ - Public-facing product
30
+ - Team of 2-10 developers
31
+
32
+ **Enterprise** — Compliance matters
33
+ - Fortune 500 customers
34
+ - Regulated industry (finance, health, legal)
35
+ - SOC2 / GDPR required
36
+ - 24/7 SLA commitment
37
+
38
+ ## Tier Promotion Path
39
+
40
+ ```
41
+ Initial release → MVP v1.0.0
42
+ ↓ (enough users to need reliability)
43
+ GA release → Medium v1.5.0
44
+ ↓ (enterprise deal signed)
45
+ Enterprise → v2.0.0
46
+ ```
47
+
48
+ Each promotion is additive — enterprise features are behind feature flags in the codebase from day one. Promotion just enables the flags and runs the stricter checklist.
49
+
50
+ ## Feature Flag Convention
51
+
52
+ ```javascript
53
+ // In code: guard enterprise/medium features
54
+ const ENABLE_SHOULD_FEATURES = process.env.ENABLE_SHOULD_FEATURES === 'true';
55
+ const ENABLE_COULD_FEATURES = process.env.ENABLE_COULD_FEATURES === 'true';
56
+
57
+ // MVP deploy: both = false (no overhead)
58
+ // Medium deploy: SHOULD = true
59
+ // Enterprise: SHOULD = true, COULD = true
60
+ ```
61
+
62
+ ## GitFlow (Enterprise) Branch Layout
63
+
64
+ ```
65
+ main ← production releases (tagged)
66
+ develop ← integration branch
67
+ feature/* ← new features
68
+ fix/* ← bug fixes
69
+ release/vX.Y.Z ← release preparation (from develop → main)
70
+ hotfix/* ← emergency production fixes (from main → main + develop)
71
+ ```
72
+
73
+ ## GitHub Flow (Medium) Branch Layout
74
+
75
+ ```
76
+ main ← production (deploy on merge)
77
+ feature/* ← all work branches
78
+ release/vX.Y.Z ← optional: release prep branch
79
+ hotfix/* ← emergency fixes
80
+ ```
81
+
82
+ ## Trunk-Based (MVP) Branch Layout
83
+
84
+ ```
85
+ main ← production + development
86
+ task/* ← short-lived feature branches (optional)
87
+ ← hotfix directly if needed
88
+ ```
89
+
90
+ ## Config Location
91
+
92
+ Tier is stored in `.planning/config.json`:
93
+
94
+ ```json
95
+ {
96
+ "release": {
97
+ "tier": "mvp",
98
+ "tiers": { ... }
99
+ }
100
+ }
101
+ ```
102
+
103
+ Update with: `node ez-tools.cjs tier-manager save-tier medium`
@@ -0,0 +1,173 @@
1
+ # BDD Feature File Template
2
+
3
+ Use this template when creating `.feature` files for a phase.
4
+
5
+ Replace `{placeholders}` with actual content.
6
+
7
+ ---
8
+
9
+ ```gherkin
10
+ # specs/features/{domain}/{feature-name}.feature
11
+ #
12
+ # Feature: {feature-name}
13
+ # Phase: {phase-number} — {phase-name}
14
+ # MoSCoW: @must | @should | @could | @wont
15
+ # Tier: @mvp | @medium | @enterprise
16
+ #
17
+ # Requirements: {REQ-IDs this feature satisfies}
18
+
19
+ Feature: {Feature Name}
20
+ As a {user role}
21
+ I want to {action/capability}
22
+ So that {benefit/value delivered}
23
+
24
+ # Background sets up shared preconditions for all scenarios in this Feature.
25
+ # Remove if no shared setup needed.
26
+ Background:
27
+ Given {shared precondition 1}
28
+ And {shared precondition 2}
29
+
30
+ # ─────────────────────────────────────────────
31
+ # MUST — Required for MVP (phase gate)
32
+ # ─────────────────────────────────────────────
33
+
34
+ @must @mvp
35
+ Scenario: {Happy path — primary success case}
36
+ Given {initial context / system state}
37
+ When {user performs action}
38
+ Then {expected outcome}
39
+ And {additional assertion}
40
+
41
+ @must @mvp
42
+ Scenario: {Primary error case}
43
+ Given {initial context}
44
+ When {user performs invalid action}
45
+ Then {expected error response}
46
+ And {system remains in valid state}
47
+
48
+ # ─────────────────────────────────────────────
49
+ # SHOULD — Target for medium tier release
50
+ # ─────────────────────────────────────────────
51
+
52
+ @should @medium
53
+ Scenario: {Secondary success case or edge case}
54
+ Given {context}
55
+ When {action}
56
+ Then {outcome}
57
+
58
+ @should @medium
59
+ Scenario: {Error recovery or retry flow}
60
+ Given {context where partial failure occurred}
61
+ When {user attempts recovery}
62
+ Then {system handles gracefully}
63
+
64
+ # ─────────────────────────────────────────────
65
+ # COULD — Nice-to-have for enterprise tier
66
+ # ─────────────────────────────────────────────
67
+
68
+ @could @enterprise
69
+ Scenario: {Advanced or compliance feature}
70
+ Given {enterprise context}
71
+ When {action}
72
+ Then {enterprise-specific outcome}
73
+
74
+ # ─────────────────────────────────────────────
75
+ # WONT — Explicitly deferred (document reasons)
76
+ # ─────────────────────────────────────────────
77
+ # @wont — SSO integration: deferred to Phase XX, depends on identity provider decision
78
+ # @wont — Biometric auth: deferred — mobile-only feature, out of scope for web
79
+ ```
80
+
81
+ ---
82
+
83
+ ## Scenario Writing Guide
84
+
85
+ ### Given (Precondition)
86
+ Sets up the world before the action. Should be:
87
+ - Specific: "Given a user exists with email test@example.com" not "Given a user exists"
88
+ - Minimal: Only include context relevant to this scenario
89
+ - Reusable: Use Background for context shared by all scenarios
90
+
91
+ ```gherkin
92
+ # Good
93
+ Given a registered user with email "alice@example.com" exists
94
+ And the user's account is in "active" status
95
+
96
+ # Bad (too vague)
97
+ Given there is a user
98
+ ```
99
+
100
+ ### When (Action)
101
+ The single event being tested. Rules:
102
+ - One action per scenario (split if multiple)
103
+ - Active voice: "When I submit the form" not "When the form is submitted"
104
+ - From user's perspective
105
+
106
+ ```gherkin
107
+ # Good
108
+ When I submit the login form with email "alice@example.com" and password "secret123"
109
+
110
+ # Bad (multiple actions)
111
+ When I fill in the form and click submit and wait for response
112
+ ```
113
+
114
+ ### Then (Outcome)
115
+ Observable, verifiable result. Must be:
116
+ - Testable: Can be automated
117
+ - Specific: Exact values, not "something happens"
118
+ - From user's perspective
119
+
120
+ ```gherkin
121
+ # Good
122
+ Then I am redirected to "/dashboard"
123
+ And the page title contains "Welcome, Alice"
124
+ And a session cookie named "ez_session" is present
125
+
126
+ # Bad (subjective)
127
+ Then it works correctly
128
+ And the user is happy
129
+ ```
130
+
131
+ ### And / But
132
+ - `And` — continues the clause type (Given+And, When+And, Then+And)
133
+ - `But` — negative assertion ("But I should not see...")
134
+
135
+ ---
136
+
137
+ ## MoSCoW Quick Reference
138
+
139
+ | Tag | When to Use | Tier |
140
+ |-----|-------------|------|
141
+ | `@must` | System is broken/unusable without it | `@mvp` |
142
+ | `@should` | Important but workaround exists | `@medium` |
143
+ | `@could` | Enhances experience but not critical | `@enterprise` |
144
+ | `@wont` | Explicitly out of scope (document why) | — |
145
+
146
+ ---
147
+
148
+ ## File Naming Convention
149
+
150
+ ```
151
+ specs/
152
+ features/
153
+ {domain}/
154
+ {feature-name}.feature # e.g., auth/login.feature
155
+ {feature-name}.feature # e.g., auth/registration.feature
156
+ {domain2}/
157
+ {feature-name}.feature
158
+ ```
159
+
160
+ Domain examples: `auth`, `payments`, `dashboard`, `onboarding`, `settings`, `api`
161
+
162
+ ---
163
+
164
+ ## INVEST Checklist
165
+
166
+ Before finalizing a Feature, verify all scenarios as a group:
167
+
168
+ - [ ] **Independent**: Feature can be developed without dependency on other features in this file
169
+ - [ ] **Negotiable**: Implementation details (not described in Then) are flexible
170
+ - [ ] **Valuable**: The Feature statement explains clear user value
171
+ - [ ] **Estimable**: A developer can estimate effort from these scenarios
172
+ - [ ] **Small**: All @must scenarios fit in one phase (split if more than ~8 must scenarios)
173
+ - [ ] **Testable**: Every Then clause can be automated