create-issflow 1.10.1 → 1.12.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/bin/cli.js +49 -22
- package/package.json +1 -1
- package/template/.issflow/README.md +8 -2
- package/template/.issflow/agents/planner.md +13 -3
- package/template/.issflow/agents/synthesizer.md +17 -8
- package/template/.issflow/commands/change-request.md +10 -2
- package/template/.issflow/commands/design.md +35 -20
- package/template/.issflow/commands/feature.md +33 -13
- package/template/.issflow/commands/goal.md +17 -8
- package/template/.issflow/commands/overview.md +46 -7
- package/template/.issflow/commands/phase.md +99 -32
- package/template/.issflow/commands/propose.md +25 -7
- package/template/.issflow/commands/quick.md +16 -4
- package/template/.issflow/commands/sprint.md +21 -12
- package/template/.issflow/commands/synthesize.md +10 -6
- package/template/.issflow/flow-config.json +11 -4
- package/template/.issflow/hooks/pre-compact.js +4 -0
- package/template/.issflow/hooks/session-start.js +84 -123
- package/template/.issflow/istartsoft-flow/METHODOLOGY.md +186 -46
- package/template/.issflow/models/MODEL-MATRIX.md +33 -0
- package/template/.issflow/routing/model-router.js +66 -0
- package/template/.issflow/routing/package.json +1 -0
- package/template/.issflow/routing/policy.json +69 -0
- package/template/.issflow/runtime/HOSTS.md +41 -0
- package/template/.issflow/runtime/README.md +150 -0
- package/template/.issflow/runtime/package.json +1 -0
- package/template/.issflow/runtime/workflow.js +187 -0
- package/template/.issflow/scripts/entry-notice.js +20 -0
- package/template/.issflow/scripts/package.json +1 -0
- package/template/.issflow/scripts/token-lint.js +58 -0
- package/template/.issflow/skills/ui-ux-pro-max/SKILL.md +7 -2
- package/template/.issflow/skills/ux-design/SKILL.md +4 -0
- package/template/.issflow/templates/ARCHITECTURE-template.md +7 -3
- package/template/.issflow/templates/PLAN-SCOPED.md +12 -0
- package/template/.issflow/templates/UX-PACK-template.md +19 -8
- package/template/.issflow/templates/design/DIRECTION.md +22 -0
- package/template/.issflow/templates/design/inventory.md +18 -0
- package/template/.issflow/templates/design/picker.html +165 -0
- package/template/.issflow/templates/design/platforms/line-oa.md +16 -0
- package/template/.issflow/templates/design/platforms/mobile-app.md +10 -0
- package/template/.issflow/templates/design/platforms/pwa.md +11 -0
- package/template/.issflow/templates/design/platforms/web-responsive.md +9 -0
- package/template/.issflow/templates/design/screens/SCREEN.md +19 -0
- package/template/.issflow/templates/design/tokens.css +47 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// SessionStart
|
|
3
|
-
// Pure Node, cross-platform (macOS / Windows / Linux) — no bash/jq/python needed.
|
|
2
|
+
// SessionStart — Tier A inject (~lean). stdout → agent context.
|
|
4
3
|
'use strict';
|
|
5
4
|
const fs = require('fs');
|
|
6
5
|
const path = require('path');
|
|
@@ -15,144 +14,106 @@ const read = (f) => { try { return fs.readFileSync(f, 'utf8'); } catch (_) { ret
|
|
|
15
14
|
const exists = (f) => fs.existsSync(f);
|
|
16
15
|
const sh = (cmd) => { try { return execSync(cmd, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }); } catch (_) { return ''; } };
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
let cfg = {};
|
|
18
|
+
try { cfg = JSON.parse(read('.issflow/flow-config.json') || '{}'); } catch (_) {}
|
|
19
|
+
const configuredLines = cfg.context && cfg.context.injectMaxLines;
|
|
20
|
+
const maxStateLines = Number.isInteger(configuredLines) ? Math.max(1, Math.min(100, configuredLines)) : 25;
|
|
21
|
+
const staleHours = (cfg.delivery && cfg.delivery.staleAfterHours) || 24;
|
|
22
|
+
|
|
23
|
+
// Resume/compact: keep inject tiny (Pattern 1 — skip heavy bodies)
|
|
24
|
+
let source = 'startup';
|
|
25
|
+
try {
|
|
26
|
+
const raw = fs.readFileSync(0, 'utf8');
|
|
27
|
+
if (raw) {
|
|
28
|
+
const j = JSON.parse(raw);
|
|
29
|
+
source = j.source || j.hook_event_name || source;
|
|
30
|
+
}
|
|
31
|
+
} catch (_) {}
|
|
32
|
+
const leanResume = /resume|compact/i.test(String(source));
|
|
20
33
|
|
|
21
|
-
|
|
22
|
-
emit('
|
|
23
|
-
emit('
|
|
24
|
-
|
|
25
|
-
emit('uncommitted: ' + uncommitted + ' file(s)');
|
|
26
|
-
for (const l of sh('git log --oneline -3').replace(/\n+$/, '').split('\n').filter(Boolean)) emit(' ' + l);
|
|
34
|
+
emit('=== iStartSoftFlow Tier-A (session) ===');
|
|
35
|
+
emit('source: ' + source);
|
|
36
|
+
emit('git: ' + (sh('git branch --show-current').trim() || 'n/a') +
|
|
37
|
+
' · dirty ' + sh('git status --short').split('\n').filter((l) => l.trim()).length);
|
|
27
38
|
emit('');
|
|
28
39
|
|
|
29
|
-
// 2. active state (cap size — STATE.md is meant to stay small)
|
|
30
40
|
const state = read('docs/STATE.md');
|
|
31
|
-
if (state
|
|
32
|
-
emit('
|
|
33
|
-
const sl = state.replace(/\n$/, '').split('\n');
|
|
34
|
-
for (const l of sl.slice(0, 40)) emit(l);
|
|
35
|
-
if (sl.length > 40) emit(`… (+${sl.length - 40} more — STATE.md should be small; trim it)`);
|
|
36
|
-
emit('');
|
|
41
|
+
if (!state) {
|
|
42
|
+
emit('STATE.md missing → /overview');
|
|
37
43
|
} else {
|
|
38
|
-
emit('## STATE
|
|
39
|
-
|
|
40
|
-
|
|
44
|
+
emit('## STATE (read first)');
|
|
45
|
+
const lines = state.replace(/\n$/, '').split('\n');
|
|
46
|
+
for (const l of lines.slice(0, maxStateLines)) emit(l.slice(0, 500));
|
|
47
|
+
if (lines.length > maxStateLines) emit(`… (+${lines.length - maxStateLines} more)`);
|
|
41
48
|
|
|
42
|
-
//
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
// Delivery / WAITING_STALE nudge
|
|
50
|
+
const waitSince = (state.match(/waiting_since:\s*(\S+)/) || [])[1];
|
|
51
|
+
const status = (state.match(/^\s*status:\s*(\S+)/m) || [])[1] || '';
|
|
52
|
+
const waitingFor = (state.match(/waiting_for:\s*(.+)/) || [])[1];
|
|
53
|
+
const nextHuman = (state.match(/next_human_action:\s*(.+)/) || [])[1];
|
|
54
|
+
const agentEta = (state.match(/agent_eta:\s*(\S+)/) || [])[1];
|
|
55
|
+
if (agentEta && agentEta !== 'none') emit('delivery.agent_eta: ' + agentEta + ' · status: ' + status);
|
|
56
|
+
if (/WAITING/i.test(status) || (waitingFor && waitingFor.trim() !== 'none')) {
|
|
57
|
+
emit('WAITING_ON_HUMAN: ' + (waitingFor || status).trim());
|
|
58
|
+
if (nextHuman) emit('next_human_action: ' + nextHuman.trim());
|
|
59
|
+
if (waitSince && waitSince !== 'none') {
|
|
60
|
+
const since = Date.parse(waitSince);
|
|
61
|
+
if (!Number.isNaN(since)) {
|
|
62
|
+
const hours = (Date.now() - since) / 3600000;
|
|
63
|
+
if (hours >= staleHours) emit('WAITING_STALE: human gate older than ' + staleHours + 'h — AI clock paused; not an agent hang.');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
54
66
|
}
|
|
55
67
|
}
|
|
68
|
+
emit('');
|
|
56
69
|
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
for
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
emit('
|
|
70
|
+
// Durable workflow state is advisory: never auto-retry a running task after interruption.
|
|
71
|
+
const workflowFile = 'docs/WORKFLOW.json';
|
|
72
|
+
if (exists(workflowFile)) {
|
|
73
|
+
emit('## Autonomous workflow checkpoint');
|
|
74
|
+
try {
|
|
75
|
+
const workflow = require('../runtime/workflow.js');
|
|
76
|
+
const summary = workflow.status(workflowFile);
|
|
77
|
+
emit(JSON.stringify({ state: summary.state, revision: summary.revision,
|
|
78
|
+
budget: summary.budget, spent: summary.spent, remaining: summary.remaining,
|
|
79
|
+
runnable: summary.runnable.slice(0, 10), totalTasks: summary.tasks.length }));
|
|
80
|
+
const unfinished = summary.tasks.filter(task => task.state !== 'done');
|
|
81
|
+
for (const task of unfinished.slice(0, 10)) {
|
|
82
|
+
emit(JSON.stringify({ id: task.id, state: task.state, attempts: task.attempts,
|
|
83
|
+
reason: task.reason.slice(0, 160), blockers: task.blockers.slice(0, 3) }));
|
|
84
|
+
}
|
|
85
|
+
emit(`Read ${workflowFile} for full task/evidence details (${unfinished.length} unfinished).`);
|
|
86
|
+
emit('Reconcile running work and its evidence before retrying; resume only within existing approval and budget.');
|
|
87
|
+
} catch (error) {
|
|
88
|
+
emit('Workflow checkpoint unreadable: ' + error.message + '. Preserve it; do not silently reset progress.');
|
|
76
89
|
}
|
|
77
90
|
emit('');
|
|
78
91
|
}
|
|
79
92
|
|
|
80
|
-
// 3b. research index — token economy: inject only the 5 newest rows, each
|
|
81
|
-
// truncated; the full table stays on disk for grep, sessions don't re-pay it.
|
|
82
|
-
const idx = read('docs/research/INDEX.md');
|
|
83
|
-
if (idx !== null) {
|
|
84
|
-
const rows = idx.split('\n').filter((l) => /^\|\s*\d{4}-\d{2}-\d{2}/.test(l));
|
|
85
|
-
emit(`## research/INDEX.md (${rows.length} prior investigations)`);
|
|
86
|
-
emit('grep this before any new research or debugging.');
|
|
87
|
-
for (const l of rows.slice(-5)) emit(' ' + (l.length > 220 ? l.slice(0, 217) + '…' : l));
|
|
88
|
-
if (rows.length > 5) emit(` … (+${rows.length - 5} older — grep docs/research/INDEX.md)`);
|
|
89
|
-
emit('');
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// 3d. shared KB — pull latest + load snapshot
|
|
93
|
-
const KB_CONFIG = '.issflow/kb-config.json';
|
|
94
|
-
let kbActive = false;
|
|
95
|
-
if (exists(KB_CONFIG)) {
|
|
96
|
-
let cfg = {}; try { cfg = JSON.parse(read(KB_CONFIG) || '{}'); } catch (_) {}
|
|
97
|
-
let kbPath = cfg.kb_path || '';
|
|
98
|
-
if (kbPath.startsWith('~')) kbPath = path.join(os.homedir(), kbPath.slice(1));
|
|
99
|
-
if (kbPath && exists(kbPath) && fs.statSync(kbPath).isDirectory()) {
|
|
100
|
-
emit('## Shared KB');
|
|
101
|
-
let pulled = true;
|
|
102
|
-
try { execSync(`git -C "${kbPath}" pull --ff-only --quiet`, { stdio: 'ignore' }); } catch (_) { pulled = false; }
|
|
103
|
-
emit(pulled ? 'KB pulled: OK' : 'KB pull skipped (offline or conflict — using local copy)');
|
|
104
93
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if (line.includes('|')) total++;
|
|
115
|
-
const entryDate = (line.split('|')[0] || '').trim();
|
|
116
|
-
if (/^\d{4}-\d{2}-\d{2}$/.test(entryDate) && entryDate < cutoff) { snap.push('[STALE] ' + line); stale++; }
|
|
117
|
-
else snap.push(line);
|
|
118
|
-
}
|
|
119
|
-
try { fs.mkdirSync('docs', { recursive: true }); fs.writeFileSync('docs/.kb-snapshot.md', snap.join('\n') + '\n'); } catch (_) {}
|
|
120
|
-
emit(`KB snapshot loaded: ${total} entries (${stale} stale — researcher will re-research these)`);
|
|
121
|
-
emit('Snapshot at docs/.kb-snapshot.md — researcher reads this before web search.');
|
|
122
|
-
} else {
|
|
123
|
-
emit(`KB INDEX.md not found at ${kbPath} — run /store-wisdom to populate it.`);
|
|
94
|
+
if (!leanResume) {
|
|
95
|
+
const issues = read('docs/ISSUES.md');
|
|
96
|
+
let openCount = 0;
|
|
97
|
+
if (issues) {
|
|
98
|
+
const blocks = [];
|
|
99
|
+
let cur = null;
|
|
100
|
+
for (const l of issues.split('\n')) {
|
|
101
|
+
if (/^### /.test(l)) { if (cur) blocks.push(cur); cur = [l]; }
|
|
102
|
+
else if (cur) cur.push(l);
|
|
124
103
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
} else {
|
|
128
|
-
emit('## Shared KB: configured but path not found (' + (cfg.kb_path || '') + ')');
|
|
129
|
-
emit('Fix kb_path in .issflow/kb-config.json (or re-run: npx create-issflow).');
|
|
130
|
-
emit('');
|
|
104
|
+
if (cur) blocks.push(cur);
|
|
105
|
+
openCount = blocks.filter((b) => b.some((l) => /- \[ \]/.test(l))).length;
|
|
131
106
|
}
|
|
107
|
+
emit('open issues: ' + openCount + ' (grep docs/ISSUES.md — bodies not injected)');
|
|
108
|
+
emit('');
|
|
132
109
|
}
|
|
133
110
|
|
|
134
|
-
|
|
135
|
-
emit('
|
|
136
|
-
emit('-
|
|
137
|
-
emit('
|
|
138
|
-
emit('
|
|
139
|
-
emit('-
|
|
140
|
-
emit('
|
|
141
|
-
emit(' PENDING — the plan needs a human sign-off via /overview first.');
|
|
142
|
-
emit('- UNDERSTAND-FIRST (rule 14): new free-text task -> brief back your understanding');
|
|
143
|
-
emit(' (goal · scope · assumptions · blast radius) and WAIT for confirm before executing.');
|
|
144
|
-
emit('- before debugging ANY error: grep ISSUES.md AND research/INDEX.md first.');
|
|
145
|
-
emit('- debug attempts: WARN at 2; cap 3. AUTO: log + park the slice + continue (batched');
|
|
146
|
-
emit(' report at the phase boundary). GUIDED: stop and ask you.');
|
|
147
|
-
emit('- end of every phase: run /synthesize, then /clear.');
|
|
148
|
-
emit('- small obvious change? use /quick, not /phase.');
|
|
149
|
-
emit('- token economy: keep context lean. Delegate noisy work to subagents (they');
|
|
150
|
-
emit(' return summaries). If one phase grows past ~50% of the model window, split');
|
|
151
|
-
emit(' it or /synthesize -> /clear — do not coast to auto-compact.');
|
|
152
|
-
if (kbActive) {
|
|
153
|
-
emit('- KB active: researcher checks docs/.kb-snapshot.md before web search.');
|
|
154
|
-
emit('- learned something worth keeping? run /store-wisdom.');
|
|
155
|
-
}
|
|
156
|
-
emit('=== END AUTO-CONTEXT ===');
|
|
111
|
+
emit('## RULES');
|
|
112
|
+
emit('- PM-mode: report ETA/stage/DONE|BLOCKED|WAITING|SLIP|HANDOFF — do not pair as junior dev.');
|
|
113
|
+
emit('- Plan PENDING → no source edits (rule 13). Design-direction locked before UI propose.');
|
|
114
|
+
emit('- Past agent_eta while AGENT_ACTIVE → SLIP report. Waiting human → eta_paused.');
|
|
115
|
+
emit('- Assumption budget per phase (flow-config). End phase: checkpoint with /synthesize (keep delivery:); use only supported host reset tools.');
|
|
116
|
+
emit('- Prefer a supported reset plus saved handoff near the context gate.');
|
|
117
|
+
emit('=== END Tier-A ===');
|
|
157
118
|
|
|
158
119
|
process.stdout.write(out.join('\n') + '\n');
|
|
@@ -35,8 +35,10 @@
|
|
|
35
35
|
Caveman ULTRA mode always on. Apply the `karpathy-guidelines` skill (engineering
|
|
36
36
|
discipline) on every coding and debugging task. Apply the `ux-design` skill (the UX
|
|
37
37
|
cookbook + wireframe baseline) on every UI-facing task. When **authoring** a new
|
|
38
|
-
visual direction (
|
|
39
|
-
first and fold the look into
|
|
38
|
+
visual direction (the overview Direction Picker, or an explicitly approved
|
|
39
|
+
direction change), apply `ui-ux-pro-max` first and fold the look into locked
|
|
40
|
+
tokens + UX pack. A missing UX-PACK does not unlock an approved direction;
|
|
41
|
+
never re-roll styles at phase CLOSE.
|
|
40
42
|
Apply the `security` skill (the Secure SDLC cookbook) at design (threat model),
|
|
41
43
|
while coding (secure coding), and before any deploy. Apply the `code-standards`
|
|
42
44
|
skill (naming per the language's own idiom + the declared architecture) on every
|
|
@@ -72,7 +74,8 @@ approval JSON is not cryptographic proof of the human approver. Require protecte
|
|
|
72
74
|
branches, required CI checks, and an actual human GitHub PR review for merge.
|
|
73
75
|
No tool can treat a self-edited approval file as owner authorization.
|
|
74
76
|
|
|
75
|
-
**Recovery:** If approval metadata is missing or malformed, stop implementation
|
|
77
|
+
**Recovery:** If approval metadata is missing or malformed, stop implementation
|
|
78
|
+
for that plan and its dependents; independent, separately approved work may continue.
|
|
76
79
|
A human should inspect the plan, restore the correct pointer and approval record,
|
|
77
80
|
then rerun verification. Never bypass the gate by editing `STATE.md` or disabling
|
|
78
81
|
checks. A scoped feature lane does not inherit approval from another plan.
|
|
@@ -91,7 +94,8 @@ metadata and any required disclosures.
|
|
|
91
94
|
|
|
92
95
|
`design-research -> grill (×2) -> plan -> implement -> test -> deploy`, one
|
|
93
96
|
VERTICAL SLICE per phase. Implement AND test a phase before the next. The last
|
|
94
|
-
phase always includes deployment
|
|
97
|
+
phase always includes deployment preparation; deployment itself requires the
|
|
98
|
+
release authorization and checks below.
|
|
95
99
|
|
|
96
100
|
A phase runs in one of two orders, chosen at RESEARCH time by the TDD
|
|
97
101
|
APPLICABILITY check (see Procedures → `phase`):
|
|
@@ -200,14 +204,28 @@ those gates, never the plan, the money, or the design/arch frame.
|
|
|
200
204
|
|
|
201
205
|
| House role | Kit surface |
|
|
202
206
|
|------------|-------------|
|
|
203
|
-
| BA / PM | `/overview` grill · `grill-me` · PLAN / PROPOSAL / CR gates |
|
|
204
|
-
| UX / UI | `/design`
|
|
205
|
-
| Architect | `/design`
|
|
206
|
-
| Developer | `implementer` · `/phase` · `/feature` · `/quick` |
|
|
207
|
+
| BA / PM | `/overview` grill · `grill-me` · PLAN / PROPOSAL / CR gates · delivery ETA board |
|
|
208
|
+
| UX / UI | Direction Picker → tokens · `/design` UX pack · `ui-ux-pro-max` (only if unlocked) · `ux-design` · `/ui-audit` |
|
|
209
|
+
| Architect / SA | `/design` ARCHITECTURE + auth decision · `researcher` DESIGN · `/log-decision` |
|
|
210
|
+
| Developer | `implementer` · `/phase` · `/feature` · `/quick` — **no direct user chat** |
|
|
207
211
|
| QA | `test-author` · `e2e-runner` · `/qa-audit` · `/uat` |
|
|
208
212
|
| DevOps | final-phase deploy · `/release` promote |
|
|
209
213
|
| Support | `/support` · `/log-issue` · `/runbook` · release hypercare |
|
|
210
214
|
|
|
215
|
+
**Human conversation mode:** the owner talks to the orchestrator as PM/SA. Subagents
|
|
216
|
+
never address the user. During AUTO build, report stage / ETA / WAITING / SLIP /
|
|
217
|
+
DONE — do not pair-program unless GUIDED.
|
|
218
|
+
|
|
219
|
+
### When `grill-me` runs
|
|
220
|
+
|
|
221
|
+
| Command | Grill? |
|
|
222
|
+
|---------|--------|
|
|
223
|
+
| `/overview` | Yes — automatic double grill |
|
|
224
|
+
| `/design` | Short grill only if auth/surfaces still open |
|
|
225
|
+
| `/change-request` | No full grill — 1–3 mini-asks if UX/arch/auth hit |
|
|
226
|
+
| `/phase` · `/feature` build | No — use STATE + stuck/ETA |
|
|
227
|
+
| User says “grill me” | On demand anytime |
|
|
228
|
+
|
|
211
229
|
-----
|
|
212
230
|
|
|
213
231
|
## Feature lane (hands-off delivery — `/feature`)
|
|
@@ -242,7 +260,8 @@ Three layers make "hands-off" real — each uses the mechanism suited to its job
|
|
|
242
260
|
model-run rituals.
|
|
243
261
|
3. **No-human-at-the-keyboard → a headless runner.** `ISSFLOW_HEADLESS=1` tells the
|
|
244
262
|
lane no human is present: every hard-stop degrades to a `BLOCKED.md` report +
|
|
245
|
-
|
|
263
|
+
lane return/exit — never a guess; an enclosing goal can still run independent
|
|
264
|
+
approved units. Two shipped runners (`create-issflow --ci|--docker`,
|
|
246
265
|
sources in `.issflow/templates/automation/`):
|
|
247
266
|
- **GitHub Actions** — label an issue `feature:approved` (or dispatch with a doc
|
|
248
267
|
path); the workflow runs the lane on an ephemeral runner.
|
|
@@ -258,12 +277,20 @@ Three layers make "hands-off" real — each uses the mechanism suited to its job
|
|
|
258
277
|
features build in parallel without touching your checkout or each other
|
|
259
278
|
(path-identical mounts: Linux/macOS).
|
|
260
279
|
|
|
261
|
-
**Approval semantics (rule-13 scoped).** The
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
280
|
+
**Approval semantics (rule-13 scoped).** The Feature approval confirms intake
|
|
281
|
+
for that document only. Apply Plan-scoped approvals before implementation;
|
|
282
|
+
feature or goal headers never override an invalid revision/digest or path scope.
|
|
283
|
+
Derived execution notes may break down approved work, not silently expand it.
|
|
284
|
+
Scope creep returns to `/change-request` and the relevant approval gate.
|
|
285
|
+
|
|
286
|
+
**Publication mode:** `> Automation: none|push|push+pr` defaults to `none`.
|
|
287
|
+
`none` delivers local results only. `push` permits the specified feature branch
|
|
288
|
+
push; `push+pr` permits that push and opening its PR to the agreed target. Either
|
|
289
|
+
outbound mode requires explicit human authorization covering this run, repository,
|
|
290
|
+
branch, and destination; a header an agent writes is not consent. Respect later
|
|
291
|
+
restrictions, including no-commit/no-push. Never infer publication from AUTO,
|
|
292
|
+
headless mode, or implementation approval. Merge and production deployment remain
|
|
293
|
+
separate human release gates, never implied by these publication modes.
|
|
267
294
|
|
|
268
295
|
-----
|
|
269
296
|
|
|
@@ -329,7 +356,8 @@ can. Escalation is at most two hops.
|
|
|
329
356
|
- **synthesizer** — compresses `docs/STATE.md` / `docs/ISSUES.md`, prunes
|
|
330
357
|
snapshots. On the final phase, also updates `README.md` + `docs/OVERVIEW.md`.
|
|
331
358
|
|
|
332
|
-
The orchestrator ROUTES
|
|
359
|
+
The orchestrator ROUTES to isolated workers where supported. Otherwise use the
|
|
360
|
+
sequential role passes in Host capabilities and continuity; do not claim isolation.
|
|
333
361
|
|
|
334
362
|
**Model routing (per-role tiers).** Each role's `.issflow/agents/<role>.md` pins a
|
|
335
363
|
`model:` tier suited to its work, so the RIGHT model runs each task by default:
|
|
@@ -341,9 +369,31 @@ The orchestrator ROUTES. It does not implement or debug.
|
|
|
341
369
|
| synthesizer | `haiku` | mechanical compression — cheapest tier |
|
|
342
370
|
|
|
343
371
|
Owner wants a SPECIFIC model? Edit the role's `model:` line — values `haiku` ·
|
|
344
|
-
`sonnet` · `opus` · `inherit` · or a full model id.
|
|
345
|
-
|
|
346
|
-
|
|
372
|
+
`sonnet` · `opus` · `inherit` · or a full model id. Cross-host suggestions live in
|
|
373
|
+
`.issflow/models/MODEL-MATRIX.md` (update `as_of` when vendors change). Adaptive
|
|
374
|
+
router under `.issflow/routing/` is advisory/fail-closed — never invent unverified
|
|
375
|
+
API IDs. Hosts without per-agent model support run the session model (graceful degrade).
|
|
376
|
+
|
|
377
|
+
### Delivery clocks (finish-date honesty)
|
|
378
|
+
|
|
379
|
+
Three clocks — do not mix:
|
|
380
|
+
|
|
381
|
+
1. **Scope effort (A)** — ideal-days for commercial value / pricing
|
|
382
|
+
2. **Agent-active ETA (B)** — when AI may finish DoD if not waiting on humans
|
|
383
|
+
3. **Waiting-on-human (C)** — pauses B; `WAITING_STALE` after `staleAfterHours`
|
|
384
|
+
|
|
385
|
+
STATE `delivery:` is mandatory during `/phase` and `/feature`. Past `agent_eta`
|
|
386
|
+
while `AGENT_ACTIVE` → SLIP report. Assumption budget per phase from flow-config.
|
|
387
|
+
These are estimates and observed state updates, not background runtime guarantees.
|
|
388
|
+
Evaluate time changes at the next actual execution opportunity; never claim a timer,
|
|
389
|
+
heartbeat, or scheduler ran when the host did not provide it. A waiting/blocked
|
|
390
|
+
unit does not pause independent approved units: retain per-unit status and ETA.
|
|
391
|
+
Only mark a package DONE when every required unit and gate is verified.
|
|
392
|
+
|
|
393
|
+
### Plan-Ready (before rule 13 approve)
|
|
394
|
+
|
|
395
|
+
Testable acceptance per phase · no TBD on auth/money/PII/primary surfaces ·
|
|
396
|
+
direction locked if UI · size+lane tags · dependencies clear.
|
|
347
397
|
|
|
348
398
|
-----
|
|
349
399
|
|
|
@@ -387,7 +437,8 @@ surface or need its own acceptance criteria? -> `/feature`. Otherwise `/quick`.
|
|
|
387
437
|
verification. Headless-capable (CI / Docker, `ISSFLOW_HEADLESS=1`). See "Feature lane".
|
|
388
438
|
- **goal [set|run|status|done|drop]** — the goal layer: declare an OUTCOME with a
|
|
389
439
|
measurable Done-when + budget (`set`, behind the rule-14 brief-back), then
|
|
390
|
-
`run` loops pick-next-unit → route lane → tick until done / budget /
|
|
440
|
+
`run` loops pick-next-unit → route lane → tick until done / budget / no ready
|
|
441
|
+
independent unit / run-wide hard-stop; local blockers park only their lane.
|
|
391
442
|
Goal-driven, not time-driven: it stops itself on the finish line. Recurrence is
|
|
392
443
|
host-level (interval loop or the cron-ready `issflow-goal.yml`). `docs/GOALS.md`
|
|
393
444
|
holds state; its `Approved:` line arms headless passes.
|
|
@@ -448,15 +499,18 @@ inject context, the model performs them itself.
|
|
|
448
499
|
|
|
449
500
|
### SESSION-OPEN (start / clear / compact-resume)
|
|
450
501
|
|
|
451
|
-
|
|
452
|
-
1. git
|
|
453
|
-
2. `docs/STATE.md` —
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
502
|
+
**Tier A (default — keep short):** SessionStart hook / model-run checklist:
|
|
503
|
+
1. git one-liner (branch · dirty count · tip).
|
|
504
|
+
2. `docs/STATE.md` top — phase, plan, design-direction, **delivery ETA/status**.
|
|
505
|
+
3. open-issue count (not full dump).
|
|
506
|
+
4. If `WAITING_STALE` / past `agent_eta` while AGENT_ACTIVE → surface that first.
|
|
507
|
+
5. Hard-rule one-liner (plan PENDING → no source edits).
|
|
508
|
+
|
|
509
|
+
**Tier B (full, on demand / first overview):** research INDEX · infra/auth · KB
|
|
510
|
+
snapshot · sprint burndown. Prefer Hard handoff (`/synthesize` keep `delivery:` →
|
|
511
|
+
`/clear`) over cold `/compact` near the context gate.
|
|
512
|
+
|
|
513
|
+
Hosts without hooks: the orchestrator runs Tier A by hand before any Edit/Write.
|
|
460
514
|
|
|
461
515
|
### SPRINT-STANDUP (auto — at phase close inside an active sprint)
|
|
462
516
|
|
|
@@ -475,10 +529,15 @@ recover: current phase, next action, open blocker.
|
|
|
475
529
|
|
|
476
530
|
The cheapest token is the one never loaded. The kit is built to minimise context:
|
|
477
531
|
|
|
478
|
-
- **
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
532
|
+
- **SessionStart is Tier A** — git one-liner + STATE top + open-issue count +
|
|
533
|
+
delivery ETA/WAITING nudge. Target a small inject; resume/compact stays leaner.
|
|
534
|
+
- **Near context gate:** prefer writing handoff into STATE + `/synthesize` +
|
|
535
|
+
host-supported reset over `/compact` where available. Use configured context
|
|
536
|
+
thresholds (`flow-config.json`), never invented telemetry or reset guarantees.
|
|
537
|
+
- **Phase boundary is the primary checkpoint.** Synthesize at each boundary;
|
|
538
|
+
reset context only if needed and supported by the host. Continue the approved
|
|
539
|
+
driver without routine confirmation. Preserve the `delivery:` block and all
|
|
540
|
+
active/parked execution records. Sprint close provides a coarser checkpoint.
|
|
482
541
|
- **Lazy, not always-on.** This methodology + the skills load on demand; only the
|
|
483
542
|
SessionStart hook output is paid every session, and it injects just the live
|
|
484
543
|
STATE + *open* issues (resolved ones stay on disk for grep, not re-paid in tokens).
|
|
@@ -503,29 +562,35 @@ a recorded sign-off) stay interactive in both modes. AUTO governs only the **dev
|
|
|
503
562
|
close): there, interruptions are expensive, so it follows the plan instead of asking.
|
|
504
563
|
|
|
505
564
|
- **AUTO (default) — during DEVELOPMENT, follow the plan, don't interrupt.** Once a
|
|
506
|
-
plan
|
|
565
|
+
plan is approved, the dev loop prefers DECIDING over asking. Resolve any in-process
|
|
507
566
|
choice from (1) the PLAN/OVERVIEW/spec, (2) the codebase, (3) a sensible default +
|
|
508
567
|
the worker's recommendation — then RECORD it (`docs/DESIGN_LOG.md` or STATE) and
|
|
509
568
|
CONTINUE. Do not stop mid-build to ask.
|
|
510
569
|
- **GUIDED — ask at each fork in dev too.** The original behaviour: the development
|
|
511
570
|
loop also surfaces choices and waits. Use when exploring an unfamiliar codebase.
|
|
512
571
|
|
|
513
|
-
**Decision protocol (AUTO, dev loop).**
|
|
514
|
-
|
|
572
|
+
**Decision protocol (AUTO, dev loop).** Resolve routine implementation details
|
|
573
|
+
within the approved acceptance criteria, file boundaries, and risk limits; log
|
|
574
|
+
the interpretation as an Assumption and continue. Do not add requirements or
|
|
575
|
+
rewrite an approved plan to make a decision fit.
|
|
515
576
|
Ambiguous TDD classification → apply the default (`TDD_PHASE=true`), log the reason,
|
|
516
577
|
continue. A worker that would have asked the user instead writes its question + its
|
|
517
578
|
own best answer to STATE and proceeds on that answer. (If the gap is in the PLAN
|
|
518
579
|
itself — not just an implementation detail — that's a planning question: surface it.)
|
|
519
580
|
|
|
520
|
-
**Batched escalation (AUTO).**
|
|
581
|
+
**Batched escalation (AUTO).** A local blocker does not halt independent work. On first stuck,
|
|
521
582
|
auto-run `/unstuck` (deep re-research) — capped at ONCE per phase, since it is
|
|
522
|
-
token-expensive
|
|
583
|
+
token-expensive; allow one fresh three-attempt debug cycle after it, never an
|
|
584
|
+
unbounded reset of the counter. Still stuck → park the blocked slice in execution
|
|
585
|
+
state (do not mutate the approved plan digest), move
|
|
523
586
|
to the next independent slice, and surface ONE consolidated report of all parked
|
|
524
587
|
blockers + logged assumptions at the phase boundary / end of run. The human reviews
|
|
525
588
|
THERE (the `/re` checkpoint), not mid-flow.
|
|
526
589
|
|
|
527
|
-
**Hard stops (BOTH modes
|
|
528
|
-
|
|
590
|
+
**Hard stops (BOTH modes).** Pause the affected action and dependent work for
|
|
591
|
+
human input; continue only independently approved, safe work. Autonomy is for
|
|
592
|
+
*development*, not permission escalation. The gates above and host permission
|
|
593
|
+
policy still apply. Stop for:
|
|
529
594
|
1. Irreversible or outbound actions — deploy to prod, data deletion/migration,
|
|
530
595
|
`git push`, publish, spending money, sending external messages.
|
|
531
596
|
2. Security-sensitive changes — auth, secrets, permissions, data exposure.
|
|
@@ -533,10 +598,76 @@ THERE (the `/re` checkpoint), not mid-flow.
|
|
|
533
598
|
+ log instead).
|
|
534
599
|
4. The debug budget is spent AND no independent slice remains to make progress.
|
|
535
600
|
|
|
601
|
+
An existing explicit authorization covering the exact action satisfies a gate
|
|
602
|
+
only where that gate permits pre-approval. Never infer publish, push, deploy,
|
|
603
|
+
spend, or security permissions from AUTO or a general build request. Release,
|
|
604
|
+
UAT, and merge remain human gates. A security finding blocks affected completion
|
|
605
|
+
and release, not unrelated safe work.
|
|
606
|
+
|
|
536
607
|
AUTO removes *questions*, not *discipline*: tests, the phase gate, issue logging,
|
|
537
608
|
and the regression corpus all still run. The point is an efficient, end-to-end
|
|
538
609
|
development run that follows the spec and logs every problem so it never recurs.
|
|
539
610
|
|
|
611
|
+
|
|
612
|
+
### Execution contract (short tasks and long runs)
|
|
613
|
+
|
|
614
|
+
Use the smallest eligible lane. After its intake and approval gates, AUTO runs
|
|
615
|
+
implement → test → fix → verify without requesting approval for each routine
|
|
616
|
+
step. A short `/quick` still verifies; a long `/goal` or `/sprint` tracks units,
|
|
617
|
+
dependencies, and a finite run budget. A single `/phase` or `/feature` request
|
|
618
|
+
does not authorize unrelated work. Select only approved units whose dependencies
|
|
619
|
+
are verified done; never skip a failed prerequisite to keep busy.
|
|
620
|
+
|
|
621
|
+
Checkpoint after each meaningful step, before a context reset, and on interruption
|
|
622
|
+
or a blocker: task ID, plan revision/digest, branch and base commit, dependencies,
|
|
623
|
+
status, files changed, commands/results and evidence paths, attempt counts,
|
|
624
|
+
remaining run budget, blocker and exact next action. Keep execution progress
|
|
625
|
+
separate from immutable approved plan content. Optional local runtime checkpoints
|
|
626
|
+
are bookkeeping, not approval, test evidence, or a background execution service.
|
|
627
|
+
|
|
628
|
+
For a multi-unit run, the optional CLI is `node .issflow/runtime/workflow.js`.
|
|
629
|
+
See `.issflow/runtime/README.md` for validated input schemas. Use
|
|
630
|
+
`docs/WORKFLOW.json` when session-hook discovery is desired: `init` once from the
|
|
631
|
+
approved task breakdown, `next` to claim, `update` after actual work, and `status`
|
|
632
|
+
on resume. Each mutation persists state. The helper does not verify approval,
|
|
633
|
+
execute tasks, or attest tests; retain the detailed evidence above separately.
|
|
634
|
+
Never recreate a checkpoint to evade its spent budget. A changed task definition
|
|
635
|
+
requires reviewed scope and carries forward relevant prior attempts explicitly.
|
|
636
|
+
|
|
637
|
+
On resume, inspect the real worktree and latest approval before trusting a
|
|
638
|
+
checkpoint. Reconcile already-applied edits and uncertain tool outcomes; do not
|
|
639
|
+
repeat commits, outbound actions, or migrations blindly. Preserve retry counters
|
|
640
|
+
and parked blockers across resume. Reopen a parked unit only with new evidence,
|
|
641
|
+
a resolved prerequisite, or explicit direction; do not cycle it through new
|
|
642
|
+
sprints to reset its budget. Bound environment/flake retries too (default two
|
|
643
|
+
retries per failing check, within the run budget); unavailable services are
|
|
644
|
+
`blocked`, not passing tests. Research retries use the same bounded policy.
|
|
645
|
+
|
|
646
|
+
Completion requires observed acceptance and gate evidence for the current diff.
|
|
647
|
+
Report `done`, `blocked`, `pending`, and `not run` distinctly, including actual
|
|
648
|
+
commands, exit results, and remaining work. A generated test plan is not UAT;
|
|
649
|
+
a skipped or unavailable check is not green. Missing metrics are `unavailable`,
|
|
650
|
+
not invented percentages. Never mark an entire feature/goal done while a required
|
|
651
|
+
unit is parked. Report local implementation separately from release readiness.
|
|
652
|
+
|
|
653
|
+
### Host capabilities and continuity
|
|
654
|
+
|
|
655
|
+
See `.issflow/runtime/HOSTS.md` for the installed capability matrix and smoke checks.
|
|
656
|
+
|
|
657
|
+
Check the actual session's tools rather than assuming a product name grants
|
|
658
|
+
capabilities. Claude Code can use installed native agents/hooks; Codex can use
|
|
659
|
+
available delegation and execution tools; Cursor uses its installed command/rule
|
|
660
|
+
and supported hook surfaces. Where delegation is unavailable, perform role passes
|
|
661
|
+
sequentially and disclose when genuine blind test isolation cannot be provided.
|
|
662
|
+
A model-run ritual is guidance, not tool enforcement. Never claim a Claude hook
|
|
663
|
+
protects Codex or Cursor, or that any prompt guarantees unattended execution.
|
|
664
|
+
|
|
665
|
+
Continue while the session is active and budget remains. Prompts and checkpoints
|
|
666
|
+
do not create a persistent runtime, scheduler, or automatic wake-up. Use only an
|
|
667
|
+
actually configured host scheduler/CI runner for recurrence, with its own limits
|
|
668
|
+
and authorization; otherwise leave a resumable checkpoint and say a new invocation
|
|
669
|
+
is needed. Do not invent `/clear`, `/loop`, or background execution capabilities.
|
|
670
|
+
|
|
540
671
|
-----
|
|
541
672
|
|
|
542
673
|
## Dry-run (preview — change nothing)
|
|
@@ -563,7 +694,9 @@ Mirrors the installer's `--dry-run`. (In a dry-run, even AUTO never acts — it
|
|
|
563
694
|
The cap protects efficiency (no flailing / token burn) in both modes.
|
|
564
695
|
3. Every resolved error -> logged to `docs/ISSUES.md` with root cause + failed
|
|
565
696
|
attempts.
|
|
566
|
-
4. End of phase -> synthesize ->
|
|
697
|
+
4. End of phase -> synthesize -> checkpoint -> next approved, ready phase.
|
|
698
|
+
Reset context only using an available host mechanism; if that ends execution,
|
|
699
|
+
leave the exact resume instruction. Do not claim to continue after session exit.
|
|
567
700
|
5. **PHASE GATE** = the current-phase REAL API suite passes AND (frontend phase)
|
|
568
701
|
the E2E suite passes AND the accumulated mock regression corpus stays green AND
|
|
569
702
|
every `docs/ENDPOINTS.md` entry has at least one test in `tests/regression/`.
|
|
@@ -605,7 +738,9 @@ Mirrors the installer's `--dry-run`. (In a dry-run, even AUTO never acts — it
|
|
|
605
738
|
(the language's standard tool), names follow the language's OWN idiom, and the
|
|
606
739
|
code conforms to the declared architecture (Feature-Based by default) — checked
|
|
607
740
|
at CLOSE. Lint/format errors or idiom violations BLOCK the close. (`code-standards`.)
|
|
608
|
-
13. **PLAN-APPROVAL gate.**
|
|
741
|
+
13. **PLAN-APPROVAL gate.** Plan-scoped approvals above take precedence; the
|
|
742
|
+
following header convention applies only to legacy plans. No phase / sprint /
|
|
743
|
+
build work starts until `docs/PLAN.md`
|
|
609
744
|
carries a human approval. `/overview` ends by presenting the plan and STOPPING for
|
|
610
745
|
sign-off; on approval the gate is RECORDED in three places — the PLAN.md
|
|
611
746
|
`> Approval:` header (`approved <date> v<n>`), `plan:` in `docs/STATE.md`, and a
|
|
@@ -623,6 +758,8 @@ Mirrors the installer's `--dry-run`. (In a dry-run, even AUTO never acts — it
|
|
|
623
758
|
A recorded approval artifact IS the confirmation for its lane (approved
|
|
624
759
|
PLAN → phases · APPROVED FEATURE doc → the feature lane · approved CR → the
|
|
625
760
|
change · `Approved:` goal → goal runs) — that is exactly what arms headless.
|
|
761
|
+
Reuse that confirmation for routine steps and retries within the same scope;
|
|
762
|
+
goal approval does not replace the required approval of each execution plan.
|
|
626
763
|
Rationale: a wrong understanding burns tokens and context at 100× the cost
|
|
627
764
|
of one confirm turn. AUTO governs execution AFTER intake, never instead of it.
|
|
628
765
|
15. **DESIGN + ARCHITECTURE gates.** After a client proposal is signed (quoted
|
|
@@ -658,10 +795,13 @@ fail the other.
|
|
|
658
795
|
|
|
659
796
|
## Shared KB (optional)
|
|
660
797
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
798
|
+
The lean SessionStart hook does not pull the KB or generate a snapshot. If
|
|
799
|
+
`.issflow/kb-config.json` exists and the task needs prior research, explicitly
|
|
800
|
+
perform the authorized Tier-B/model-run refresh, or use the existing local KB
|
|
801
|
+
with its freshness disclosed. The researcher checks `docs/.kb-snapshot.md` when
|
|
802
|
+
available; never claim it was refreshed automatically. Run `store-wisdom` to
|
|
803
|
+
promote resolved issues + research to the KB with its sharing approval. The kit
|
|
804
|
+
works normally without a KB.
|
|
665
805
|
|
|
666
806
|
-----
|
|
667
807
|
|