Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a configurable Mano “run mode” (manual default vs auto) as per-clone local execution context, adds the mano mode command to manage it, and updates the workflow + skill contracts to define how auto-chaining and hook execution behave under each mode.
Changes:
- Add run-mode detection/serialization (
MODE: manual|auto) tostate.jsprojections viaphaseRouting, plus a newmode.jsscript andmano modeskill. - Extend workflow and skill docs for auto-mode chaining (pause/stop rules) and add hook kinds (
suggestvscommand) with mode-dependent behavior. - Add eval coverage and fixtures for run-mode defaults/projections and for specific planning-flow rules (mid-phase assignment + rules visibility for new categories).
Reviewed changes
Copilot reviewed 37 out of 37 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| src/workflow.md | Documents mano mode and defines auto-mode chaining + hook-mode contracts. |
| src/skills/ux.md | Updates hook guidance to respect hook ## Mode. |
| src/skills/ui.md | Updates hook guidance to respect hook ## Mode. |
| src/skills/stories.md | Adds mid-phase assignment procedure + hook-mode guidance. |
| src/skills/start.md | Adds auto-mode arming message and mid-phase “route, don’t dead-end” guidance. |
| src/skills/spec.md | Updates hook guidance to respect hook ## Mode. |
| src/skills/rules.md | Updates hook guidance to respect hook ## Mode. |
| src/skills/review.md | Updates hook guidance to respect hook ## Mode. |
| src/skills/mode.md | New skill contract for mano mode command. |
| src/skills/import.md | Updates hook guidance to respect hook ## Mode. |
| src/scripts/state.js | Threads run mode into all relevant projections (MODE: lines). |
| src/scripts/phase.js | Adds run-mode resolution (MANO_MODE / git config mano.mode) and exports it. |
| src/scripts/mode.js | New script to show/set/clear run mode via local git config. |
| src/hooks/README.md | Documents hook kinds (suggest vs command) and their behavior by run mode. |
| src/hooks/post-ux.example.md | Updates template commentary for hook kinds. |
| src/hooks/post-ui.example.md | Updates template commentary for hook kinds. |
| src/hooks/post-stories.example.md | Updates template commentary for hook kinds. |
| src/hooks/post-start.example.md | Updates template commentary for hook kinds. |
| src/hooks/post-spec.example.md | Updates template commentary for hook kinds. |
| src/hooks/post-rules.example.md | Updates template commentary for hook kinds. |
| src/hooks/post-review.example.md | Updates template commentary for hook kinds. |
| src/hooks/post-import.example.md | Updates template commentary for hook kinds. |
| src/bootstrap/cursorrules | Adds mapping for mano mode → _mano/skills/mode.md. |
| src/bootstrap/AGENTS.md | Documents run mode + hook kinds in the universal agent contract. |
| README.md | Adds user-facing documentation for auto mode and hook kinds. |
| eval/test_scripts.py | Adds tests for mode defaults/opt-in and mode propagation through projections. |
| eval/fixtures/stories-midphase-assign/story-4-upcoming-export.md | Fixture story file for mid-phase assignment scenario. |
| eval/fixtures/stories-midphase-assign/story-3-existing-shipped.md | Fixture story file for mid-phase assignment scenario. |
| eval/fixtures/stories-midphase-assign/stories-README.md | Fixture story index for mid-phase assignment scenario. |
| eval/fixtures/stories-midphase-assign/phase-brief.md | Fixture phase brief used to validate “goal check” and “brief untouched”. |
| eval/fixtures/stories-midphase-assign/backlog.md | Fixture backlog used to validate assignment + non-target item unchanged. |
| eval/fixtures/start-new-category/tech-spec.md | Fixture to ensure existence filters don’t hide necessary next actions. |
| eval/fixtures/start-new-category/project-rules.md | Fixture mature rules file for “new category still suggests rules”. |
| eval/fixtures/start-new-category/backlog.md | Fixture backlog defining “new category” phase. |
| eval/cases/stories-midphase-assign.json | New eval case for mid-phase backlog assignment flow. |
| eval/cases/start-suggests-rules-for-new-category.json | New eval case for “keep rules visible for new category”. |
| eval/assertions.py | Adds assertions for mid-phase assignment + start rules visibility. |
Suppressed comments (8)
src/hooks/post-import.example.md:60
- This reference points to
hooks/README.md, but hooks ship under_mano/hooks/(see installer layout and other docs referencing_mano/hooks/*). The path should match the installed location to avoid broken references.
When this hook is active, do not run it automatically. (This applies to `## Mode: suggest`, which is what this file declares. If you change `## Mode` to `command`, the mode wins over this line and the command runs automatically — see hooks/README.md.)
src/hooks/post-spec.example.md:59
- This reference points to
hooks/README.md, but hooks ship under_mano/hooks/(see installer layout and other docs referencing_mano/hooks/*). The path should match the installed location to avoid broken references.
When this hook is active, do not run it automatically. (This applies to `## Mode: suggest`, which is what this file declares. If you change `## Mode` to `command`, the mode wins over this line and the command runs automatically — see hooks/README.md.)
src/hooks/post-rules.example.md:61
- This reference points to
hooks/README.md, but hooks ship under_mano/hooks/(see installer layout and other docs referencing_mano/hooks/*). The path should match the installed location to avoid broken references.
When this hook is active, do not run it automatically. (This applies to `## Mode: suggest`, which is what this file declares. If you change `## Mode` to `command`, the mode wins over this line and the command runs automatically — see hooks/README.md.)
src/hooks/post-start.example.md:62
- This reference points to
hooks/README.md, but hooks ship under_mano/hooks/(see installer layout and other docs referencing_mano/hooks/*). The path should match the installed location to avoid broken references.
When this hook is active, do not run it automatically. (This applies to `## Mode: suggest`, which is what this file declares. If you change `## Mode` to `command`, the mode wins over this line and the command runs automatically — see hooks/README.md.)
src/hooks/post-ux.example.md:60
- This reference points to
hooks/README.md, but hooks ship under_mano/hooks/(see installer layout and other docs referencing_mano/hooks/*). The path should match the installed location to avoid broken references.
When this hook is active, do not run it automatically. (This applies to `## Mode: suggest`, which is what this file declares. If you change `## Mode` to `command`, the mode wins over this line and the command runs automatically — see hooks/README.md.)
src/hooks/post-ui.example.md:65
- This reference points to
hooks/README.md, but hooks ship under_mano/hooks/(see installer layout and other docs referencing_mano/hooks/*). The path should match the installed location to avoid broken references.
When this hook is active, do not run it automatically. (This applies to `## Mode: suggest`, which is what this file declares. If you change `## Mode` to `command`, the mode wins over this line and the command runs automatically — see hooks/README.md.)
src/hooks/post-stories.example.md:65
- This reference points to
hooks/README.md, but hooks ship under_mano/hooks/(see installer layout and other docs referencing_mano/hooks/*). The path should match the installed location to avoid broken references.
When this hook is active, do not run it automatically. (This applies to `## Mode: suggest`, which is what this file declares. If you change `## Mode` to `command`, the mode wins over this line and the command runs automatically — see hooks/README.md.)
src/hooks/post-review.example.md:63
- This reference points to
hooks/README.md, but hooks ship under_mano/hooks/(see installer layout and other docs referencing_mano/hooks/*). The path should match the installed location to avoid broken references.
When this hook is active, do not run it automatically. (This applies to `## Mode: suggest`, which is what this file declares. If you change `## Mode` to `command`, the mode wins over this line and the command runs automatically — see hooks/README.md.)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| hooks/post-spec.example.md -> inactive | ||
| hooks/post-spec.md -> active |
| <!-- Two kinds of hook. `suggest` (this one) produces findings: Mano asks | ||
| before running it and you approve each finding. Change this to `command` | ||
| and add a `## Command` section naming one command to instead run that | ||
| command automatically, every time, after this skill. See hooks/README.md. --> |
| <!-- Two kinds of hook. `suggest` (this one) produces findings: Mano asks | ||
| before running it and you approve each finding. Change this to `command` | ||
| and add a `## Command` section naming one command to instead run that | ||
| command automatically, every time, after this skill. See hooks/README.md. --> |
| <!-- Two kinds of hook. `suggest` (this one) produces findings: Mano asks | ||
| before running it and you approve each finding. Change this to `command` | ||
| and add a `## Command` section naming one command to instead run that | ||
| command automatically, every time, after this skill. See hooks/README.md. --> |
| <!-- Two kinds of hook. `suggest` (this one) produces findings: Mano asks | ||
| before running it and you approve each finding. Change this to `command` | ||
| and add a `## Command` section naming one command to instead run that | ||
| command automatically, every time, after this skill. See hooks/README.md. --> |
| <!-- Two kinds of hook. `suggest` (this one) produces findings: Mano asks | ||
| before running it and you approve each finding. Change this to `command` | ||
| and add a `## Command` section naming one command to instead run that | ||
| command automatically, every time, after this skill. See hooks/README.md. --> |
| <!-- Two kinds of hook. `suggest` (this one) produces findings: Mano asks | ||
| before running it and you approve each finding. Change this to `command` | ||
| and add a `## Command` section naming one command to instead run that | ||
| command automatically, every time, after this skill. See hooks/README.md. --> |
| <!-- Two kinds of hook. `suggest` (this one) produces findings: Mano asks | ||
| before running it and you approve each finding. Change this to `command` | ||
| and add a `## Command` section naming one command to instead run that | ||
| command automatically, every time, after this skill. See hooks/README.md. --> |
| <!-- Two kinds of hook. `suggest` (this one) produces findings: Mano asks | ||
| before running it and you approve each finding. Change this to `command` | ||
| and add a `## Command` section naming one command to instead run that | ||
| command automatically, every time, after this skill. See hooks/README.md. --> |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 37 out of 37 changed files in this pull request and generated no new comments.
Suppressed comments (8)
src/skills/ux.md:82
- This line forbids auto-running
suggesthooks unconditionally, but the updated workflow/hook contract sayssuggesthooks run automatically inmano mode autoand pause for findings triage. As written,mano uxwould fail to runsuggesthooks in auto mode.
src/skills/ui.md:232 - This line forbids auto-running
suggesthooks unconditionally, but the updated workflow/hook contract sayssuggesthooks run automatically inmano mode autoand pause for findings triage. As written,mano uiwould fail to runsuggesthooks in auto mode.
src/skills/review.md:310 - This line forbids auto-running
suggesthooks unconditionally, but the updated workflow/hook contract sayssuggesthooks run automatically inmano mode autoand pause for findings triage. As written,mano reviewwould fail to runsuggesthooks in auto mode.
Check the hook's `## Mode` first: a `command` hook runs automatically in both modes and is reported in the execution log, never as a suggestion (`_mano/workflow.md` → **Optional Post-Skill Hooks**). Do not run a `suggest` hook automatically.
src/skills/import.md:136
- This paragraph says “Do not run a
suggesthook automatically” without accounting formano mode auto. The workflow and hooks README now specify thatsuggesthooks run automatically in auto mode and pause the chain for findings triage, so this instruction would prevent the promised auto-mode hook behavior formano import.
If an active `post-import.md` hook exists, mention it in the final response before the next-action line. Check its `## Mode` first: a `command` hook runs automatically in both modes (report it in the execution log, never as a suggestion) — see `_mano/workflow.md` → **Optional Post-Skill Hooks**. The rest of this section describes a `suggest` hook. Do not run a `suggest` hook automatically. Do not mention specific third-party skill names or the hook's suggested prompt unless the user explicitly asks to run or inspect it. Do not write hook suggestions into generated artifacts.
src/skills/spec.md:334
- This paragraph says “Do not run a
suggesthook automatically” without accounting formano mode auto. The workflow and hooks README now specify thatsuggesthooks run automatically in auto mode and pause the chain for findings triage, so this instruction would prevent the promised auto-mode hook behavior formano spec.
src/skills/rules.md:279 - This paragraph says “Do not run a
suggesthook automatically” without accounting formano mode auto. The workflow and hooks README now specify thatsuggesthooks run automatically in auto mode and pause the chain for findings triage, so this instruction would prevent the promised auto-mode hook behavior formano rules.
src/workflow.md:86 - This sentence says post-skill hooks run automatically only in auto mode, but the PR introduces
commandhooks that always run in both modes. Clarifying that this subsection is aboutsuggesthooks (and thatcommandhooks always run) would avoid contradicting the “two hook kinds” contract later in the document and in hooks/README.md.
src/skills/stories.md:584 - This paragraph says “Do not run a
suggesthook automatically” without accounting formano mode auto. The workflow and hooks README now specify thatsuggesthooks run automatically in auto mode and pause the chain for findings triage, so this instruction would prevent the promised auto-mode hook behavior formano stories.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 39 out of 39 changed files in this pull request and generated no new comments.
Suppressed comments (3)
src/workflow.md:10
mano modealso supportsclear(andshow), and this same document later referencesmano mode clear. The command synopsis should includeclearso users can discover the reset-to-default behavior from the command list.
README.md:70- The docs and the
mode.jsscript supportmano mode clear, but the command table only shows[auto|manual]. Includingclearhere improves discoverability and keeps the README consistent with the documented interface.
| `mano mode [auto\|manual]` | Show or set whether finished actions chain automatically through to implementation. Defaults to `manual`. |
src/bootstrap/AGENTS.md:29
mano modesupportsclearin addition toauto/manual; listing it here makes the command surface consistent with the skill contract (_mano/skills/mode.md) and avoids hiding the “reset to default” path.
- `mano mode [auto|manual]` → read `_mano/skills/mode.md`; show or set whether finished actions chain automatically
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 46 out of 48 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
src/scripts/phase.js:85
resolveConfiguredMode()throws whenMANO_MODEis present but empty. Given the contract that a missing/unreadable setting must default tomanual, treating an empty env override as “unset” avoids surprising hard failures (e.g., shells that export an empty var).
| const value = String(result.stdout || "").trim(); | ||
| return value ? validateMode(value) : null; |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 57 out of 59 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/scripts/phase.js:84
resolveConfiguredMode()/gitConfigMode()currently throw when the stored mode value is invalid (or whenMANO_MODEis set but empty). The workflow/docs explicitly say missing or unreadable mode configuration must fall back tomanualrather than crashing state/skill projections. Treat invalid/empty values as “unreadable” and default tomanualinstead of throwing.
src/scripts/mode.js:16- The
mano modehelp text showsnode mode.js ..., but in practice users will be invoking this via the installed path (node _mano/scripts/mode.js ...). Advertisingnode mode.jsis likely to fail unless the user happens to be in that directory.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 65 out of 67 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/scripts/state.js:314
scanGaps()now callsresolveConfiguredMode(projectRoot), which can throw (e.g., invalid/emptyMANO_MODE). In the--gapsCLI path this ends up reported as a backlog read failure, which is misleading. Catch and rethrow with explicit mode-resolution context so callers surface the right root cause.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 66 out of 68 changed files in this pull request and generated no new comments.
Suppressed comments (4)
src/scripts/state.js:74
--sourcetreats any value starting with-as a missing argument, which prevents filtering by a legitimate source substring like "-draft" and is inconsistent with other commands accepting such values. Consider supporting an inline--source=<text>form so values starting with-remain expressible while still erroring on--sourcewith no value.
src/scripts/state.js:79--tracktreats any value starting with-as a missing argument. That makes it impossible to explicitly scope/filter with tracks that start with-(even though track validation allows it elsewhere) and also blocks cases where the intended track name begins with a hyphen. Supporting an inline--track=<name>form keeps the safety check for the space-separated form while allowing hyphen-prefixed values.
src/scripts/scaffold.js:138- The generator merge currently skips only top-level
.gitpaths. A generator that creates nested.git/directories (e.g., in a subproject/template) would have those copied into the real project, which is risky and surprising. Consider skipping any generated path that contains a.gitsegment, not just when it is the first path component.
CHANGELOG.md:11 - The PR description says this change is about adding
mode auto, but the code and docs also introduce additional user-facing features (e.g.,mano track, command hooks, scaffold runner, review evidence changes). If this is intentional, consider updating the PR title/description to reflect the full scope (or splitting into smaller PRs) to make review and release notes easier to track.
## 1.3.0 — August 10, 2026
### Added
- **`mano mode auto|manual` adds an explicit, local hands-off option** — `manual` remains the default. After the human approves a phase scope, auto mode runs the approved, phase-specific planning chain through `mano dev yolo`, pauses for every human decision or blocker, and always stops before `mano review` or another phase. The mode lives in repository-local Git config, can be overridden with `MANO_MODE`, and is projected by every `state.js` view, including gap-only and JSON output.
- **Hooks now support deterministic `command` mode** — a command hook names one project command that runs after its skill in both manual and auto modes. Existing and mode-less hooks remain `suggest`: Mano asks before running them in manual or unarmed work, while an approved auto chain runs them as the substitute for skipped intermediate human review and pauses if their findings need triage.
- **Exact backlog items can be pulled into an open phase through `mano stories`** — when the human names an existing item and it fits the already-approved goal, stories may assign that exact title with the backlog writer and add a lettered story. It cannot choose work, hand-edit the backlog, broaden the phase goal, or bypass the normal readiness gates.
- **Greenfield scaffolding now has a non-destructive runner** — `scaffold.js` runs empty-directory project generators outside the project, preflights every destination, preserves identical files, rejects differing collisions before copying, and never overwrites or deletes existing Mano artifacts. Spec, stories, and development contracts require this guarded path instead of moving `_mano` / `_mano_output` away or hand-merging generated files.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 66 out of 68 changed files in this pull request and generated no new comments.
Suppressed comments (4)
src/scripts/state.js:79
--trackcurrently preserves leading/trailing whitespace in the stored value, but matching lower down usestrim().toLowerCase(). Trim here so the renderedTRACK:/ scope labels reflect the actual constraint and whitespace-only inputs fail consistently.
src/scripts/state.js:74--sourcestores the raw argument (including leading/trailing whitespace), but filtering normalizes withtrim().toLowerCase(). That can make the renderedSource contains ...label and any downstream consumer ofargs.sourcedisagree with the effective filter (and can print confusing whitespace). Trim the value at parse time and treat all-whitespace input as missing so the existing validation errors cleanly.
This issue also appears on line 75 of the same file.
src/scripts/scaffold.js:315
- If staging-directory cleanup fails,
removeOwnedStage()will throw after files have been merged and verified, causing the command to exit non-zero even though the scaffold merge succeeded. That makes automation treat a successful run as a failure. Consider treating cleanup failure as a warning and leaving the stage on disk instead of throwing.
package.json:9 - The PR description only mentions adding
mode auto, but this change set also introduces additional user-facing features (e.g.,mano track, greenfieldscaffold.jsrunner, hookcommandmode semantics, review/validation template changes, and a version bump to 1.3.0). Please update the PR description to reflect the broader scope (or split into separate PRs) so reviewers and release notes consumers can accurately track intent.
"version": "1.3.0",
"description": "Installer for Mano — a fast planning loop for AI-assisted development: plan in small phases and validate each assumption before it becomes code, with the human in control at every step.",
"bin": {
"mano-plan": "bin/mano-plan.js"
},
"scripts": {
"test": "node --test && python3 -m unittest discover -s eval -p 'test_*.py'",
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 68 out of 70 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/scripts/backlog.js:126
--track(and--source) consume the next argv token unconditionally, so a missing value can silently swallow the next flag (e.g.--track --status backlog), leading to misparsed args and potentially persisting an unintended Track value. Add a value-present check so these options fail fast when the next token is missing or another flag.
CHANGELOG.md:11- The PR title/description only mentions adding
mode auto, but this diff also introduces additional user-facing features (e.g.mano track,scaffold.jsrunner + template changes, and hookcommandmode). Please update the PR title/description to reflect the broader scope so reviewers and release notes match what’s actually shipping.
## 1.3.0 — August 10, 2026
### Added
- **`mano mode auto|manual` adds an explicit, local hands-off option** — `manual` remains the default. After the human approves a phase scope, auto mode runs the approved, phase-specific planning chain through `mano dev yolo`, pauses for every human decision or blocker, and always stops before `mano review` or another phase. The mode lives in repository-local Git config, can be overridden with `MANO_MODE`, and is projected by every `state.js` view, including gap-only and JSON output.
- **Hooks now support deterministic `command` mode** — a command hook names one project command that runs after its skill in both manual and auto modes. Existing and mode-less hooks remain `suggest`: Mano asks before running them in manual or unarmed work, while an approved auto chain runs them as the substitute for skipped intermediate human review and pauses if their findings need triage.
- **Exact backlog items can be pulled into an open phase through `mano stories`** — when the human names an existing item and it fits the already-approved goal, stories may assign that exact title with the backlog writer and add a lettered story. It cannot choose work, hand-edit the backlog, broaden the phase goal, or bypass the normal readiness gates.
- **Greenfield scaffolding now has a non-destructive runner** — `scaffold.js` runs empty-directory project generators outside the project, preflights every destination, preserves identical files, rejects differing collisions before copying, and never overwrites or deletes existing Mano artifacts. Spec, stories, and development contracts require this guarded path instead of moving `_mano` / `_mano_output` away or hand-merging generated files.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 72 out of 74 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/scripts/stories.js:280
set-statusnow fails atomically when any requested story row is missing, but it still treats malformed--storyinputs the same as a genuinely missing row. This produces a misleading "no matching row" error for inputs that don't match the supported story-number format (e.g.3or3a). Consider validating missing entries againstSTORY_NUMand failing with a dedicated invalid-input message first.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 77 out of 79 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/scripts/scaffold.js:138
- collectTree() only skips
.gitwhen it’s the top-level path segment. A generator that creates a nested.git/directory (or.gitfile) under another folder would currently have that copied into the project, which is an unnecessary risk and can confuse tooling.
Consider skipping any entry whose relative path contains a .git segment at any depth (while keeping the reserved top-level check for _mano*).
Add
mode auto. When enabled, it automatically runs the required skills and implements all stories.