@caiqueoak/flow 0.3.0 → 0.3.2

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/README.md CHANGED
@@ -11,7 +11,7 @@ npx flow init
11
11
 
12
12
  `flow init` is interactive, or use `--runtime codex,claude` in automation. Built-in adapters install the public `/flow` skill in `.codex/skills/flow/` or `.claude/skills/flow/`; a custom project-local skills directory is also available interactively.
13
13
 
14
- Skills are always installed inside the current project. Runtime integration directories never contain project state. If `.flow/` already exists, `flow init` only adds coding-agent integrations and updates `.flow/config.yaml`; it does not modify canonical project artifacts.
14
+ Skills are always installed inside the current project. Runtime integration directories never contain project state. If `.flow/` already exists, `flow init` only adds missing coding-agent integrations and updates `.flow/config.yaml`. If all built-in integrations are already configured, it exits without prompting. It does not modify canonical project artifacts.
15
15
 
16
16
  ## Project bootstrap
17
17
 
@@ -22,7 +22,7 @@ Skills are always installed inside the current project. Runtime integration dire
22
22
  └── config.yaml
23
23
  ```
24
24
 
25
- It does not create a PRD, engineering guide, backlog, state, decisions, work items, gates, or templates. The `/flow` skill creates those artifacts only when they become valid canonical project information.
25
+ It does not create a PRD, engineering guide, backlog, graph, state, decisions, work items, gates, or templates. During `/flow`, new project documents and artifacts are created only when the developer explicitly requests or authorizes them. Flow updates existing approved artifacts instead of inventing ad-hoc progress, summary, handoff, or status documents.
26
26
 
27
27
  ## Workflow
28
28
 
@@ -34,17 +34,31 @@ There is one public skill:
34
34
 
35
35
  Use `/flow <intent>` to start or change work, for example `/flow I want to build a diet app`. Use `/flow` with no extra input to continue from `.flow/STATE.md`.
36
36
 
37
- Flow internally loads only the guidance needed for discovery, planning, build, review, or reconciliation. It asks only for consequential decisions and uses the largest safe degree of parallelism.
37
+ Flow internally loads only the guidance needed for discovery, planning, build, review, or reconciliation. It asks only for consequential decisions and uses the largest safe degree of parallelism. Once execution is underway, it does not stop merely to announce completed tasks, progress, or next steps; it continues automatically until developer input, external approval, an unrecoverable blocker, or no ready work requires a real stop.
38
+
39
+ When authorized, Flow keeps a concise artifact model: product truth in `PRD.md`, engineering truth in `ENGINEERING.md`, decisions in `DECISIONS.md`, execution context in `STATE.md`, the canonical work-item DAG in `BACKLOG.yaml`, and a human-readable derived projection in `GRAPH.md`. Work items use `SPEC.md` plus `TASKS.yaml`. `SUMMARY.md` is not part of the model.
40
+
41
+ In `GRAPH.md`, work-item states are consistent: complete is green, in progress is blue, blocked is red when unfinished dependencies remain, and pending is yellow when all dependencies are complete and the item is ready to execute. Each Mermaid card contains only the work-item ID and canonical title. Every dependency arrow goes from dependency to dependent item and uses the color and line style of its source card.
38
42
 
39
43
  ## Update
40
44
 
41
45
  Updates are explicit:
42
46
 
43
47
  ```bash
44
- npx flow update
48
+ flow update
45
49
  ```
46
50
 
47
- `flow update` updates the npm package and refreshes `/flow` for every coding agent configured in `.flow/config.yaml`. There is no background update check or automatic update mechanism.
51
+ `flow update` detects how the active Flow CLI is installed. If the project contains `@caiqueoak/flow`, it updates that project dependency; if the CLI is globally installed, it updates the global package instead. It then refreshes `/flow` for every coding agent configured in `.flow/config.yaml` without modifying canonical project state.
52
+
53
+ On Windows, npm is invoked through the command shell so `npm.cmd` can be executed correctly. When Flow is installed as a project dependency, `npx flow update` is equivalent.
54
+
55
+ There is no background update check or automatic update mechanism.
56
+
57
+ ## Releases
58
+
59
+ Merges to `main` are released automatically after the test matrix passes. The release pipeline uses npm Trusted Publishing (OIDC), creates a signed npm provenance record, and tags the release; no npm token or manual version bump is needed.
60
+
61
+ Use Conventional Commit prefixes in the PR title (and retained commits): `fix:` produces a patch, `feat:` a minor, and `feat!:` or a `BREAKING CHANGE:` footer a major release. `docs:`, `test:`, `chore:`, and `ci:` do not publish a package.
48
62
 
49
63
  ## CLI
50
64
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caiqueoak/flow",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Readability-first, agent-agnostic software development workflow for coding agents.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -19,31 +19,35 @@ Do not require the developer to know or invoke internal workflow phases.
19
19
 
20
20
  1. **Readability first.** Canonical artifacts must be understandable without Flow internals.
21
21
  2. **Decision ownership.** The developer owns consequential product and engineering decisions; the agent executes within approved rules and obvious conventions.
22
- 3. **Autonomy by default.** Continue until a consequential decision, external approval, unrecoverable blocker, or no-ready-work condition.
22
+ 3. **Autonomy by default.** Continue until a consequential decision requiring developer input, external approval, unrecoverable blocker, or no-ready-work condition.
23
23
  4. **Just-in-time detail.** Resolve global decisions during discovery and work-item detail only when that item becomes active.
24
24
  5. **Production-aware MVP.** MVP includes product capability plus the technical, infrastructure, quality, deployment, and operational work needed to run it.
25
25
  6. **Parallelism first.** Execute the largest safe independent set while preserving correctness and token efficiency.
26
- 7. **Automatic synchronization.** Keep state, decisions, PRD, engineering definition, backlog, specs, and summaries aligned.
26
+ 7. **Automatic synchronization.** Keep state, decisions, PRD, engineering definition, backlog, graph, specs, and tasks aligned.
27
+ 8. **Artifact restraint.** Never create a new project document or artifact unless the developer explicitly requests or authorizes it. Update existing approved artifacts instead whenever possible.
28
+ 9. **Execution continuity.** Do not pause execution merely to report progress, completion, or next steps. Continue automatically while ready work exists. Surface status only when execution has actually stopped or when developer input is required.
27
29
 
28
30
  ## Canonical project artifacts
29
31
 
30
- Create artifacts only when they become valid. `flow init` creates only `.flow/config.yaml`.
32
+ Create artifacts only when they become valid and only when the developer has explicitly requested or authorized their creation. `flow init` creates only `.flow/config.yaml`.
31
33
 
32
34
  Developer-facing knowledge is Markdown:
33
35
 
34
36
  - `.flow/PRD.md` - current global product truth and MVP boundary.
35
37
  - `.flow/ENGINEERING.md` - global engineering truth.
36
- - `.flow/SUMMARY.md` - concise project overview derived from canonical state.
37
38
  - `.flow/DECISIONS.md` - consequential decision record and rationale.
38
- - `.flow/STATE.md` - concise navigation/status view.
39
+ - `.flow/STATE.md` - concise current execution/navigation checkpoint and resume context.
40
+ - `.flow/GRAPH.md` - human-readable derived projection of the work-item dependency graph and current readiness state.
39
41
  - `.flow/work-items/<folder>/SPEC.md` - readable lifecycle/specification of one work item.
40
42
 
41
43
  Graph/control data is YAML:
42
44
 
43
- - `.flow/BACKLOG.yaml` - work-item DAG.
45
+ - `.flow/BACKLOG.yaml` - canonical work-item DAG and work-item state.
44
46
  - `.flow/work-items/<folder>/TASKS.yaml` - task DAG and execution ownership.
45
47
 
46
- Do not create completion logs. Completed `SPEC.md` files retain concise Overview and Validation sections.
48
+ Do not create `SUMMARY.md`, completion logs, ad-hoc progress documents, handoff documents, reports, or any other new project artifact unless the developer explicitly requests or authorizes them. Completed `SPEC.md` files retain concise Overview and Validation sections.
49
+
50
+ `GRAPH.md` is derived only. It must never become an independent source of truth and must be reconciled whenever work-item existence, title, dependencies, or status change. Before creating or changing it, read `references/graph.md` and follow that contract exactly; do not preserve an established style that conflicts with it.
47
51
 
48
52
  ## Work item model
49
53
 
@@ -53,6 +57,15 @@ Do not create completion logs. Completed `SPEC.md` files retain concise Overview
53
57
 
54
58
  Folder format is `<three-digit-sequence><kind-code>-<slug>` (for example, `001F-user-profile`). The sequence is a stable readability aid, never execution order. Dependencies determine readiness.
55
59
 
60
+ Work-item states are derived consistently:
61
+
62
+ - `complete` (`✅`, green) - the item is completed.
63
+ - `in_progress` (`🔵`, blue) - the item has active execution.
64
+ - `blocked` (`🔴`, red) - the item is neither complete nor in progress and at least one work-item dependency is not complete.
65
+ - `pending` (`🟡`, yellow) - the item is neither complete nor in progress and every work-item dependency is complete; it is ready to execute.
66
+
67
+ The graph must use these meanings consistently for nodes and outgoing dependency-line styling.
68
+
56
69
  ## Decision authority
57
70
 
58
71
  Apply low-impact and conventional choices automatically. A decision requires developer approval when materially different choices affect product behavior or scope; architecture/public contracts; production infrastructure or cost; persistent data; security/privacy; testing strategy or gates; project-wide conventions; or other work-item assumptions.
@@ -108,17 +121,21 @@ Load only the reference needed for current state:
108
121
  - Ready planned tasks: `references/build.md`
109
122
  - Completed implementation awaiting validation: `references/review.md`
110
123
  - Decision impact or inconsistent artifacts: `references/reconcile.md`
124
+ - Creating or updating `GRAPH.md`: additionally load `references/graph.md`
111
125
 
112
126
  ## Orchestration loop
113
127
 
114
128
  1. Read `.flow/config.yaml`.
115
- 2. Read only the minimum navigation context from `.flow/STATE.md` and `.flow/SUMMARY.md` when present.
129
+ 2. Read only the minimum navigation context from `.flow/STATE.md` when present.
116
130
  3. Classify new intent and its impact on canonical truth, backlog, active work, or execution detail.
117
131
  4. Respect work/tasks already `in_progress` under another execution ID.
118
132
  5. Route to the minimal internal reference.
119
133
  6. Claim selected work before parallel execution.
120
134
  7. Continue planning, build, gates, review, fixes/reconciliation, and completion without another invocation.
121
- 8. Recompute readiness after completion and continue if configured.
135
+ 8. Recompute work-item states and readiness after every meaningful transition, synchronize `BACKLOG.yaml`, `STATE.md`, and `GRAPH.md`, and continue if ready work exists.
136
+ 9. Do not stop or return control merely to announce that a task/work item completed or to describe the next step. Stop only when developer input is required for a consequential decision, an external approval is required, an unrecoverable blocker prevents useful progress, or no ready work remains.
137
+
138
+ When execution stops, report the stopping reason and the smallest relevant status summary. During uninterrupted execution, avoid progress-only messages.
122
139
 
123
140
  ## Parallelism and gates
124
141
 
@@ -2,4 +2,6 @@
2
2
 
3
3
  Compute ready tasks, exclude claims by another execution ID, select the largest safe set, and mark it `in_progress` before editing or delegating. Load only relevant specs, decisions, code, and gates. Follow approved conventions, avoid unrelated refactors, run the cheapest relevant deterministic checks, make atomic commits, and mark tasks complete only after acceptance checks pass.
4
4
 
5
- Synchronize TASKS, STATE, and affected canonical artifacts at each meaningful transition. If a consequential new choice emerges, stop only the affected path and present the decision while independent paths continue when safe.
5
+ Synchronize `TASKS.yaml`, `BACKLOG.yaml`, `STATE.md`, `GRAPH.md`, and other affected approved canonical artifacts at each meaningful transition. Never create a new document or artifact unless the developer explicitly requested or authorized it. If a consequential new choice emerges, stop only the affected path and present the decision while independent paths continue when safe.
6
+
7
+ Do not pause or return control merely to report that a task or work item completed, to announce progress, or to state the next step. Recompute readiness and continue automatically while useful ready work exists. Surface execution status only when developer input is required or execution has actually stopped.
@@ -10,4 +10,6 @@ Resolve only consequential global decisions affecting the problem, users, MVP, b
10
10
 
11
11
  ## Outputs
12
12
 
13
- Create or update only valid canonical artifacts: `PRD.md`, `ENGINEERING.md`, `DECISIONS.md`, `BACKLOG.yaml`, `STATE.md`, `SUMMARY.md`, and approved gate definitions. Discovery ends when no unresolved global decision is needed for a coherent production-capable MVP and initial work-item DAG.
13
+ Update valid canonical artifacts when their truth changes. Create `PRD.md`, `ENGINEERING.md`, `DECISIONS.md`, `BACKLOG.yaml`, `STATE.md`, `GRAPH.md`, work-item artifacts, or gate definitions only when the developer explicitly requested or authorized creation of that artifact class. Never create substitute, progress, summary, handoff, or ad-hoc documents to capture information that belongs in an existing approved artifact.
14
+
15
+ `GRAPH.md` is a derived human-readable projection of `BACKLOG.yaml`, not an independent source of truth. Discovery ends when no unresolved global decision is needed for a coherent production-capable MVP and initial work-item DAG.
@@ -0,0 +1,62 @@
1
+ # `GRAPH.md` Rules
2
+
3
+ Every Flow `GRAPH.md` must be a derived, human-readable projection of
4
+ `.flow/BACKLOG.yaml`. It never becomes an independent source of truth.
5
+
6
+ ## Card content
7
+
8
+ Each Mermaid card contains exactly two lines:
9
+
10
+ ```text
11
+ <work-item ID>
12
+ <work-item title>
13
+ ```
14
+
15
+ Do not include status, priority, folder, dependency lists, or explanatory
16
+ prose inside a card. The title is the canonical `title` value from
17
+ `BACKLOG.yaml`.
18
+
19
+ ## Status derivation and colors
20
+
21
+ Derive status from the backlog and dependencies after every meaningful state
22
+ transition.
23
+
24
+ | Status | Meaning | Card color | Outgoing arrow style |
25
+ | --- | --- | --- | --- |
26
+ | Complete | Work item is accepted and complete. | Green (`#16a34a`) | Solid green |
27
+ | In progress | Work item has active execution. | Blue (`#2563eb`) | Solid blue, thicker |
28
+ | Pending | Every dependency is complete and the item is ready to start. | Yellow (`#d97706`) | Dashed yellow |
29
+ | Blocked | The item is neither complete nor in progress and one or more dependencies are incomplete. | Red (`#dc2626`) | Dotted red |
30
+
31
+ Use matching fill, stroke, and readable text colors for cards. Every graph
32
+ must include a titled status legend using these colors.
33
+
34
+ ## Dependencies and arrows
35
+
36
+ - Draw one arrow for every `depends_on` relationship in `BACKLOG.yaml`.
37
+ - The arrow goes from dependency to dependent item.
38
+ - Every outgoing arrow inherits the color and line style of its source card.
39
+ - Recalculate Mermaid `linkStyle` indexes whenever edges change; do not leave
40
+ a stale style assignment behind.
41
+ - Do not add visual-only dependency edges to force layout.
42
+
43
+ ## Parallelism and layout
44
+
45
+ - Items on the same vertical rank must have no dependency on one another and
46
+ are candidates for parallel work.
47
+ - Keep independent, ready items on the same vertical rank where Mermaid can
48
+ represent the real dependency graph without artificial edges.
49
+ - Do not represent blocked items as pending merely because they are planned;
50
+ dependency readiness determines their graph status.
51
+
52
+ ## Synchronization checklist
53
+
54
+ When work-item state, existence, title, or dependencies change:
55
+
56
+ 1. Update `BACKLOG.yaml` first.
57
+ 2. Recompute derived statuses using the definitions above.
58
+ 3. Update `GRAPH.md`, including cards, arrows, styles, legend, and parallel
59
+ layout.
60
+ 4. Update `STATE.md` when the active path or next ready work changes.
61
+ 5. Verify that every backlog item appears exactly once and every dependency
62
+ appears exactly once in the graph.
@@ -2,4 +2,6 @@
2
2
 
3
3
  Read only relevant global decisions, backlog context, existing spec/tasks, and source. Ask consequential work-item decisions only when viable answers materially change behavior, contracts, data semantics, technical boundaries, security, UX, or gates.
4
4
 
5
- Create `.flow/work-items/<id>/SPEC.md` with goal, scope/non-goals, relevant decisions, approach, requirements, acceptance criteria, gates, dependencies/impacts, and validation. Create `TASKS.yaml` with bounded, testable, independently executable tasks, real blocking dependencies only, and concise acceptance/validation expectations.
5
+ For an already authorized work-item artifact class, create or update `.flow/work-items/<id>/SPEC.md` with goal, scope/non-goals, relevant decisions, approach, requirements, acceptance criteria, gates, dependencies/impacts, and validation. Create or update `TASKS.yaml` with bounded, testable, independently executable tasks, real blocking dependencies only, and concise acceptance/validation expectations.
6
+
7
+ If the required `SPEC.md` or `TASKS.yaml` does not yet exist and the developer has not explicitly requested or authorized creation of that artifact class, request authorization before creating it. Do not create substitute planning documents. After planning, continue automatically into ready execution instead of stopping to report the plan unless a consequential developer decision is required.
@@ -1,3 +1,5 @@
1
1
  # Reconciliation
2
2
 
3
- Keep canonical truth and active plans aligned when new intent or accepted decisions affect work. Reconcile pending/planned work before execution, preserve unaffected in-progress work, and create maintenance work for completed work that must change. Preserve superseded decisions with links to their replacements. Update only artifacts whose current truth changed.
3
+ Keep canonical truth and active plans aligned when new intent or accepted decisions affect work. Reconcile pending/planned work before execution, preserve unaffected in-progress work, and create maintenance work for completed work that must change. Preserve superseded decisions with links to their replacements. Update only approved artifacts whose current truth changed, including the derived `GRAPH.md` whenever work-item existence, dependencies, or status change.
4
+
5
+ Never create a new document or artifact during reconciliation unless the developer explicitly requested or authorized it. After reconciliation, recompute readiness and continue execution automatically when safe rather than pausing to report status.
@@ -1,3 +1,5 @@
1
1
  # Review
2
2
 
3
- Verify completed work against its spec and applicable gates: inspect task completion and diff, validate requirements and acceptance criteria, run deterministic blocking gates, then applicable agentic gates, and check integration/regressions. Create targeted fix tasks within approved scope; request a decision only for consequential new choices. On success, update the spec Overview and Validation, then synchronize backlog, state, and summary.
3
+ Verify completed work against its spec and applicable gates: inspect task completion and diff, validate requirements and acceptance criteria, run deterministic blocking gates, then applicable agentic gates, and check integration/regressions. Create targeted fix tasks within approved scope; request a decision only for consequential new choices. On success, update the spec Overview and Validation, then synchronize `BACKLOG.yaml`, `STATE.md`, `GRAPH.md`, and other affected approved canonical artifacts.
4
+
5
+ Never create a new document or artifact during review unless the developer explicitly requested or authorized it. Do not stop merely to announce successful validation or the next ready work item; return to orchestration and continue while useful ready work exists.
package/src/cli.mjs CHANGED
@@ -27,6 +27,38 @@ function valueAfter(name) { const i = args.indexOf(name); return i >= 0 ? args[i
27
27
  function npmCommand() { return process.platform === 'win32' ? 'npm.cmd' : 'npm'; }
28
28
  function projectRoot() { return path.resolve(valueAfter('--path') || process.cwd()); }
29
29
  function configPath(root) { return path.join(root, '.flow', 'config.yaml'); }
30
+ function packagePath(root) { return path.join(root, 'node_modules', '@caiqueoak', 'flow'); }
31
+
32
+ function abortedPromptError() {
33
+ const error = new Error('Prompt aborted.');
34
+ error.code = 'ABORT_ERR';
35
+ return error;
36
+ }
37
+
38
+ function question(rl, message) {
39
+ return new Promise((resolve, reject) => {
40
+ let settled = false;
41
+ const finish = (callback, value) => {
42
+ if (settled) return;
43
+ settled = true;
44
+ rl.removeListener('close', onClose);
45
+ callback(value);
46
+ };
47
+ const onClose = () => finish(reject, abortedPromptError());
48
+ rl.once('close', onClose);
49
+ rl.question(message).then(
50
+ (answer) => finish(resolve, answer),
51
+ (error) => finish(reject, error)
52
+ );
53
+ });
54
+ }
55
+
56
+ function runNpm(npmArgs, options = {}) {
57
+ return execFileSync(npmCommand(), npmArgs, {
58
+ ...options,
59
+ shell: process.platform === 'win32'
60
+ });
61
+ }
30
62
 
31
63
  function copyDir(source, target) {
32
64
  fs.mkdirSync(target, { recursive: true });
@@ -82,6 +114,11 @@ function parseRuntimeFlag() {
82
114
  return raw ? raw.split(',').map((x) => x.trim().toLowerCase()).filter(Boolean) : null;
83
115
  }
84
116
 
117
+ function missingBuiltinRuntimes(existing) {
118
+ const existingTypes = new Set(existing.map((r) => r.type));
119
+ return Object.keys(RUNTIME_DEFINITIONS).filter((type) => !existingTypes.has(type));
120
+ }
121
+
85
122
  async function promptMultiSelect(existing) {
86
123
  const existingTypes = new Set(existing.map((r) => r.type));
87
124
  const options = Object.entries(RUNTIME_DEFINITIONS).filter(([type]) => !existingTypes.has(type)).map(([value, def]) => ({ value, label: def.label }));
@@ -92,7 +129,7 @@ async function promptMultiSelect(existing) {
92
129
  const rl = readline.createInterface({ input: inputStream, output: outputStream });
93
130
  try {
94
131
  while (true) {
95
- const answer = (await rl.question('Selection: ')).trim();
132
+ const answer = (await question(rl, 'Selection: ')).trim();
96
133
  const indices = [...new Set(answer.split(',').map((v) => Number.parseInt(v.trim(), 10)).filter(Number.isInteger))];
97
134
  if (indices.length && indices.every((n) => n >= 1 && n <= options.length)) return indices.map((n) => options[n - 1].value);
98
135
  info('Choose one or more valid numbers.');
@@ -103,7 +140,7 @@ async function promptMultiSelect(existing) {
103
140
  async function promptText(message, defaultValue = '') {
104
141
  const rl = readline.createInterface({ input: inputStream, output: outputStream });
105
142
  try {
106
- const answer = (await rl.question(`${message}${defaultValue ? ` [${defaultValue}]` : ''}: `)).trim();
143
+ const answer = (await question(rl, `${message}${defaultValue ? ` [${defaultValue}]` : ''}: `)).trim();
107
144
  return answer || defaultValue;
108
145
  } finally { rl.close(); }
109
146
  }
@@ -129,7 +166,15 @@ async function initProject() {
129
166
  info('Flow project already exists. Canonical project artifacts will not be created or modified.');
130
167
  if (config.runtimes.length) info(`Configured coding agents: ${config.runtimes.map((r) => r.type).join(', ')}`);
131
168
  }
132
- const selected = parseRuntimeFlag() || await promptMultiSelect(config.runtimes);
169
+
170
+ const requested = parseRuntimeFlag();
171
+ if (existed && !requested && missingBuiltinRuntimes(config.runtimes).length === 0) {
172
+ info('All built-in coding agents are already configured. Nothing to add.');
173
+ info('Use --runtime custom only when you intentionally want to add a custom coding agent.');
174
+ return;
175
+ }
176
+
177
+ const selected = requested || await promptMultiSelect(config.runtimes);
133
178
  const knownTypes = new Set(config.runtimes.map((r) => r.type));
134
179
  const added = [];
135
180
  for (const type of selected) {
@@ -156,29 +201,88 @@ function dependencySection(root) {
156
201
  return '--save-dev';
157
202
  }
158
203
 
204
+ function containingNodeModules(packageRoot) {
205
+ let current = path.resolve(packageRoot);
206
+ while (true) {
207
+ if (path.basename(current).toLowerCase() === 'node_modules') return current;
208
+ const parent = path.dirname(current);
209
+ if (parent === current) return null;
210
+ current = parent;
211
+ }
212
+ }
213
+
214
+ function updatePlan(root) {
215
+ const projectPackageRoot = packagePath(root);
216
+ if (fs.existsSync(path.join(projectPackageRoot, 'package.json'))) {
217
+ return {
218
+ npmArgs: ['install', dependencySection(root), `${PACKAGE_NAME}@latest`],
219
+ cwd: root,
220
+ packageRoot: projectPackageRoot,
221
+ mode: 'project'
222
+ };
223
+ }
224
+
225
+ try {
226
+ const globalNodeModules = path.resolve(runNpm(['root', '--global'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim());
227
+ const globalPackageRoot = path.join(globalNodeModules, '@caiqueoak', 'flow');
228
+ if (path.resolve(ROOT).startsWith(`${globalNodeModules}${path.sep}`) && fs.existsSync(path.join(globalPackageRoot, 'package.json'))) {
229
+ return {
230
+ npmArgs: ['install', '--global', `${PACKAGE_NAME}@latest`],
231
+ cwd: root,
232
+ packageRoot: globalPackageRoot,
233
+ mode: 'global'
234
+ };
235
+ }
236
+ } catch { /* fall through to local installation detection */ }
237
+
238
+ const nodeModules = containingNodeModules(ROOT);
239
+ if (nodeModules) {
240
+ const installRoot = path.dirname(nodeModules);
241
+ return {
242
+ npmArgs: ['install', dependencySection(installRoot), `${PACKAGE_NAME}@latest`],
243
+ cwd: installRoot,
244
+ packageRoot: ROOT,
245
+ mode: 'local'
246
+ };
247
+ }
248
+
249
+ fail('cannot determine how this Flow CLI was installed. Reinstall @caiqueoak/flow with npm, then run flow update again.');
250
+ }
251
+
159
252
  function update() {
160
253
  const root = projectRoot();
161
254
  const config = readConfig(root);
162
255
  if (!config) fail('this project is not initialized. Run flow init first.');
163
256
  if (!config.runtimes.length) fail('no coding agents are configured. Run flow init to add one.');
164
- info(`Updating ${PACKAGE_NAME}...`);
165
- try { execFileSync(npmCommand(), ['install', dependencySection(root), `${PACKAGE_NAME}@latest`], { cwd: root, stdio: 'inherit' }); }
257
+
258
+ const plan = updatePlan(root);
259
+ info(`Updating ${PACKAGE_NAME} (${plan.mode} installation)...`);
260
+ try { runNpm(plan.npmArgs, { cwd: plan.cwd, stdio: 'inherit' }); }
166
261
  catch { fail('npm update failed. Existing project state and installed skills were not intentionally removed.'); }
167
- const packageRoot = path.join(root, 'node_modules', '@caiqueoak', 'flow');
168
- if (!fs.existsSync(path.join(packageRoot, 'package.json'))) fail(`updated package not found at ${path.relative(root, packageRoot)}.`);
169
- const latest = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
170
- for (const runtime of config.runtimes) info(`✓ ${runtime.type}: ${path.relative(root, installRuntimeSkill(root, runtime, packageRoot))}`);
262
+
263
+ if (!fs.existsSync(path.join(plan.packageRoot, 'package.json'))) fail(`updated package not found at ${plan.packageRoot}.`);
264
+ const latest = JSON.parse(fs.readFileSync(path.join(plan.packageRoot, 'package.json'), 'utf8'));
265
+ for (const runtime of config.runtimes) info(`✓ ${runtime.type}: ${path.relative(root, installRuntimeSkill(root, runtime, plan.packageRoot))}`);
171
266
  const text = fs.readFileSync(configPath(root), 'utf8');
172
267
  fs.writeFileSync(configPath(root), text.replace(/(^framework:\s*\n(?:.*\n)*?\s+version:\s*)[^\n]+/m, `$1${latest.version}`), 'utf8');
173
268
  info(`Flow updated to ${latest.version}.`);
174
269
  }
175
270
 
176
271
  function help() {
177
- info(`Flow ${VERSION}\n\nUsage:\n flow init [--path <project>] [--runtime codex,claude]\n flow update [--path <project>]\n flow --version\n\nflow init creates only .flow/config.yaml and installs the project-local /flow skill for selected coding agents.\nIf .flow already exists, init only adds coding-agent integrations.\nThere is no flow install command and no automatic/background update mechanism.`);
272
+ info(`Flow ${VERSION}\n\nUsage:\n flow init [--path <project>] [--runtime codex,claude]\n flow update [--path <project>]\n flow --version\n\nflow init creates only .flow/config.yaml and installs the project-local /flow skill for selected coding agents.\nIf .flow already exists, init only adds coding-agent integrations and exits without prompting when all built-in integrations are already configured.\nflow update updates the installation that provides the Flow CLI (project-local or global) and refreshes every configured project-local skill.\nThere is no flow install command and no automatic/background update mechanism.`);
178
273
  }
179
274
 
180
- if (!args.length || hasFlag('--help') || hasFlag('-h')) help();
181
- else if (hasFlag('--version') || hasFlag('-v')) info(VERSION);
182
- else if (args[0] === 'init') await initProject();
183
- else if (args[0] === 'update') update();
184
- else fail(`unknown command '${args[0]}'. Run flow --help.`);
275
+ try {
276
+ if (!args.length || hasFlag('--help') || hasFlag('-h')) help();
277
+ else if (hasFlag('--version') || hasFlag('-v')) info(VERSION);
278
+ else if (args[0] === 'init') await initProject();
279
+ else if (args[0] === 'update') update();
280
+ else fail(`unknown command '${args[0]}'. Run flow --help.`);
281
+ } catch (error) {
282
+ if (error?.code === 'ABORT_ERR') {
283
+ info('\nFlow command canceled.');
284
+ process.exitCode = 130;
285
+ } else {
286
+ throw error;
287
+ }
288
+ }
@@ -1,5 +0,0 @@
1
- # Canonical Artifact Guidance
2
-
3
- Create canonical project files only when they become valid. `PRD.md` holds global product truth; `ENGINEERING.md` holds current global engineering truth; `SUMMARY.md` is a concise derived orientation view; `STATE.md` is a concise navigation/status view; and `DECISIONS.md` preserves consequential decisions, options, rationale, and impacts.
4
-
5
- `BACKLOG.yaml` is the work-item DAG. Each work item has a readable `SPEC.md` and a `TASKS.yaml` task DAG with status, dependencies, acceptance/validation, and optional ownership areas. Do not create a separate completion log: keep delivered behavior and validation in the completed spec.