@phuthuycoding/kanban-flow 0.3.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/LICENSE +21 -0
- package/README.md +173 -0
- package/dist/cli/args.js +219 -0
- package/dist/cli/commands/approve.js +44 -0
- package/dist/cli/commands/archive.js +245 -0
- package/dist/cli/commands/artifacts.js +100 -0
- package/dist/cli/commands/autoconfig.js +180 -0
- package/dist/cli/commands/cancel.js +129 -0
- package/dist/cli/commands/contexts.js +101 -0
- package/dist/cli/commands/doctor.js +35 -0
- package/dist/cli/commands/harness.js +60 -0
- package/dist/cli/commands/helpers.js +22 -0
- package/dist/cli/commands/init.js +119 -0
- package/dist/cli/commands/inspect.js +141 -0
- package/dist/cli/commands/new.js +80 -0
- package/dist/cli/commands/rules.js +69 -0
- package/dist/cli/commands/run.js +156 -0
- package/dist/cli/commands/stage.js +186 -0
- package/dist/cli/result.js +1 -0
- package/dist/dashboard/dashboard-view.js +238 -0
- package/dist/dashboard/dashboard.js +206 -0
- package/dist/harness/chain.js +41 -0
- package/dist/harness/config.js +168 -0
- package/dist/harness/prompt.js +105 -0
- package/dist/harness/run.js +245 -0
- package/dist/harness/session.js +78 -0
- package/dist/harness/supervise.js +65 -0
- package/dist/index.js +123 -0
- package/dist/integrations/agents.js +67 -0
- package/dist/integrations/hooks.js +59 -0
- package/dist/integrations/install.js +193 -0
- package/dist/project/bootstrap.js +358 -0
- package/dist/project/config.js +111 -0
- package/dist/project/contexts.js +98 -0
- package/dist/project/doctor.js +163 -0
- package/dist/shared/frontmatter.js +54 -0
- package/dist/shared/paths.js +78 -0
- package/dist/shared/time.js +5 -0
- package/dist/workflow/direction.js +56 -0
- package/dist/workflow/features.js +198 -0
- package/dist/workflow/findings.js +3 -0
- package/dist/workflow/schema.js +148 -0
- package/dist/workflow/secrets.js +52 -0
- package/dist/workflow/status.js +188 -0
- package/dist/workflow/validate-approval.js +25 -0
- package/dist/workflow/validate-artifacts.js +89 -0
- package/dist/workflow/validate-cancel.js +14 -0
- package/dist/workflow/validate-reports.js +121 -0
- package/dist/workflow/validate-traceability.js +91 -0
- package/dist/workflow/validate.js +73 -0
- package/docs/workflow/README.md +67 -0
- package/docs/workflow/artifacts.md +60 -0
- package/docs/workflow/cli-reference.md +78 -0
- package/docs/workflow/dashboard.md +35 -0
- package/docs/workflow/gates.md +103 -0
- package/docs/workflow/harness.md +144 -0
- package/docs/workflow/lifecycle.md +107 -0
- package/docs/workflow/skills.md +52 -0
- package/docs/workflow/source-layout.md +47 -0
- package/docs/workflow/state-machine.md +83 -0
- package/kanban-flow/review/rules/README.md +30 -0
- package/kanban-flow/review/rules/general.md +41 -0
- package/kanban-flow/review/rules/performance.md +29 -0
- package/kanban-flow/review/rules/security.md +32 -0
- package/kanban-flow/review/stacks/go.md +33 -0
- package/kanban-flow/review/stacks/java.md +38 -0
- package/kanban-flow/review/stacks/node.md +28 -0
- package/kanban-flow/review/stacks/php.md +30 -0
- package/kanban-flow/review/stacks/python.md +34 -0
- package/kanban-flow/review/stacks/ruby.md +32 -0
- package/kanban-flow/review/stacks/rust.md +33 -0
- package/kanban-flow/templates/phase-1-bug-report.md +76 -0
- package/kanban-flow/templates/phase-1-spec-requirement.md +67 -0
- package/kanban-flow/templates/phase-2-implementation-plan.md +85 -0
- package/kanban-flow/templates/phase-2-test-case.md +68 -0
- package/kanban-flow/templates/phase-2-use-case-diagram.md +18 -0
- package/kanban-flow/templates/phase-2-use-case-specification.md +33 -0
- package/kanban-flow/templates/phase-2-use-case.md +60 -0
- package/kanban-flow/templates/phase-4-testing-result.md +63 -0
- package/kanban-flow/templates/phase-5-review-report.md +68 -0
- package/kanban-flow/templates/phase-6-feature-report.md +78 -0
- package/package.json +63 -0
- package/skills/kanban-archive/SKILL.md +78 -0
- package/skills/kanban-brainstorm/SKILL.md +310 -0
- package/skills/kanban-bug/SKILL.md +55 -0
- package/skills/kanban-flow/SKILL.md +136 -0
- package/skills/kanban-implement/SKILL.md +72 -0
- package/skills/kanban-plan/SKILL.md +102 -0
- package/skills/kanban-review/SKILL.md +90 -0
- package/skills/kanban-test/SKILL.md +76 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Quyen (phuthuycoding)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# kanban-flow
|
|
2
|
+
|
|
3
|
+
An AI coding agent will tell you the tests passed, the plan was followed, the
|
|
4
|
+
edge cases are covered. Sometimes it is right, and you cannot tell which time
|
|
5
|
+
from the transcript, because the transcript is written by the same thing you are
|
|
6
|
+
checking. kanban-flow moves the proof into files on disk: the gates do not read
|
|
7
|
+
the agent's summary, they read `.works/`.
|
|
8
|
+
|
|
9
|
+
## How it works
|
|
10
|
+
|
|
11
|
+
Every work item walks one pipeline, and only the CLI moves it between stages:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
brainstorm → planning → implementation → testing → review → dones
|
|
15
|
+
↘ backlog ↗ ↺ FAIL loops back
|
|
16
|
+
any stage → cancelled, with a reason on the record
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```mermaid
|
|
20
|
+
flowchart LR
|
|
21
|
+
B([brainstorm]) -->|requirement confirmed| P([planning])
|
|
22
|
+
P -->|contract approved + fingerprint| I([implementation])
|
|
23
|
+
P -.->|hold| BL([backlog])
|
|
24
|
+
BL -.->|start| I
|
|
25
|
+
I -->|tasks done| T([testing])
|
|
26
|
+
T -->|report PASS + current execution id| R([review])
|
|
27
|
+
R -->|report PASS + feature report| D([dones])
|
|
28
|
+
T -.->|FAIL| I
|
|
29
|
+
R -.->|FAIL| I
|
|
30
|
+
I -.->|kf cancel --reason| X([cancelled])
|
|
31
|
+
X -.->|reopen where it stopped| I
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Solid arrows are the happy path, and every label on one is a gate the CLI checks
|
|
35
|
+
before the folder moves. Dotted arrows are the ways out: hold it in backlog,
|
|
36
|
+
loop back on a FAIL, or stop it for good with a reason on the record.
|
|
37
|
+
|
|
38
|
+
Most stages owe an artifact. A transition is refused when that artifact is
|
|
39
|
+
missing, empty, still full of template placeholders, or carrying a real secret.
|
|
40
|
+
A testing report that does not say `PASS` does not reach review; a review report
|
|
41
|
+
that does not say `PASS` does not archive. `--force` overrides a gate and is
|
|
42
|
+
recorded in `.kfw.json` where a reviewer will find it.
|
|
43
|
+
|
|
44
|
+
Three decisions belong to a human: marking the requirement `status: confirmed`,
|
|
45
|
+
approving the execution contract, and choosing whether to start now or hold it
|
|
46
|
+
in backlog. The approval is bound to a SHA-256 fingerprint of the contract, so
|
|
47
|
+
editing the plan invalidates it, and no stage further forward accepts the item
|
|
48
|
+
until it returns to planning and is approved again.
|
|
49
|
+
|
|
50
|
+
## Install
|
|
51
|
+
|
|
52
|
+
Needs Node 20 or newer.
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm install -g @phuthuycoding/kanban-flow
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
That puts `kf` on your PATH. To work from source instead:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
git clone https://github.com/phuthuycoding/kanban-flow.git
|
|
62
|
+
cd kanban-flow && npm install && npm run build && npm link
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## A run, end to end
|
|
66
|
+
|
|
67
|
+
The agent runs the commands and writes the artifacts between them, taking every
|
|
68
|
+
template and path from `kf instruct`. `kf status` shows the artifact checklist;
|
|
69
|
+
`kf validate` reports what is actually blocking a gate, traceability included.
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
cd your-project
|
|
73
|
+
kf init # asks a few questions, seeds .kf/, installs the skills
|
|
74
|
+
kf new user-login --context auth # opens Phase 1 in brainstorm
|
|
75
|
+
kf instruct spec-requirement --change user-login
|
|
76
|
+
# write the requirement, set its frontmatter to status: confirmed — decision one
|
|
77
|
+
kf stage user-login planning
|
|
78
|
+
# write the plan, the use-case index, one file per UC, the diagram, the test plan
|
|
79
|
+
kf approve user-login # decision two; fingerprints all of it
|
|
80
|
+
kf stage user-login implementation # or backlog — decision three
|
|
81
|
+
kf stage user-login testing # mints a fresh execution id
|
|
82
|
+
# write the testing report, carrying that id and real exit codes
|
|
83
|
+
kf stage user-login review # refused unless that report says PASS
|
|
84
|
+
# write the review report, then the feature report
|
|
85
|
+
kf archive user-login # refused unless the review says PASS
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## What is actually different
|
|
89
|
+
|
|
90
|
+
Most of the mechanics here exist elsewhere: requirement-to-test traceability as
|
|
91
|
+
a CI gate, role-to-runner configuration, hash-bound plan approval, a cancelled
|
|
92
|
+
state with a mandatory reason, blocking placeholders. No claim to inventing them.
|
|
93
|
+
|
|
94
|
+
One mechanic I have not found anywhere else: **every entry into testing mints a
|
|
95
|
+
fresh execution id**, and a report is accepted only when its `execution:` field
|
|
96
|
+
matches the current one. Fix a failure, go round again, and yesterday's green
|
|
97
|
+
report is inert. Stale test evidence stops being a way to pass.
|
|
98
|
+
|
|
99
|
+
```mermaid
|
|
100
|
+
sequenceDiagram
|
|
101
|
+
participant A as Agent
|
|
102
|
+
participant K as kf
|
|
103
|
+
participant F as .works/
|
|
104
|
+
|
|
105
|
+
A->>K: kf stage x testing
|
|
106
|
+
K->>F: mint execution id run-1
|
|
107
|
+
A->>F: testing report, execution run-1
|
|
108
|
+
A->>K: kf stage x review
|
|
109
|
+
K-->>A: PASS and id matches, allowed
|
|
110
|
+
|
|
111
|
+
Note over A,F: review returns FAIL, the code changes
|
|
112
|
+
|
|
113
|
+
A->>K: kf stage x implementation
|
|
114
|
+
A->>K: kf stage x testing
|
|
115
|
+
K->>F: mint execution id run-2
|
|
116
|
+
A->>K: kf stage x review
|
|
117
|
+
K-->>A: refused, the report still says run-1
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The old report is not deleted, argued with, or trusted less. It simply stops
|
|
121
|
+
matching, so passing again costs exactly one honest test run. The rest of the
|
|
122
|
+
case is the combination: a gate reading files instead of claims, an approval
|
|
123
|
+
bound to the bytes it approved, evidence that expires.
|
|
124
|
+
|
|
125
|
+
## Multi-agent harness
|
|
126
|
+
|
|
127
|
+
Stages route to **roles**, roles point at **runners**. A runner is one way to
|
|
128
|
+
invoke a CLI: its argv, its permission flags, how its session resumes. A role is
|
|
129
|
+
a job such as researcher or tester. Pointing a role at an existing runner is one
|
|
130
|
+
line; a runner nobody has declared yet is a few more.
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
"harness": {
|
|
134
|
+
"main": "architect",
|
|
135
|
+
"roles": { "architect": "claude", "researcher": "codex", "writer": "gemini", "coder": "claude" },
|
|
136
|
+
"stages": { "brainstorm": ["researcher", "writer"], "implementation": "coder" },
|
|
137
|
+
"runners": {
|
|
138
|
+
"claude": { "start": ["claude", "-p", "{prompt}"] },
|
|
139
|
+
"codex": { "start": ["codex", "exec", "{prompt}"] },
|
|
140
|
+
"gemini": { "start": ["gemini", "-p", "{prompt}"] }
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
```mermaid
|
|
146
|
+
flowchart LR
|
|
147
|
+
S1[stage: brainstorm] --> R1[role: researcher] --> N2[runner: codex]
|
|
148
|
+
S1 --> R2[role: writer] --> N3[runner: gemini]
|
|
149
|
+
S2[stage: implementation] --> R3[role: coder] --> N1[runner: claude]
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
A stage runs its roles in order, and a role that declares an `output` file hands
|
|
153
|
+
it to the next one. A role reporting neither `DONE` nor `DONE_WITH_CONCERNS`
|
|
154
|
+
stops the chain. Sessions are kept per work item and per role, so two roles on
|
|
155
|
+
one CLI never share context.
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
kf harness # stage → role chain, role → runner, which CLIs are on PATH
|
|
159
|
+
kf run user-login --detach # run the current stage's chain; poll with kf runs
|
|
160
|
+
kf runs user-login --json # each run: role, runner, status, usage where reported
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Presets ship for claude, codex, devin, gemini and opencode. Assign no stages and the harness stays out of the way.
|
|
164
|
+
|
|
165
|
+
## Documentation
|
|
166
|
+
|
|
167
|
+
The full reference lives in [docs/workflow](docs/workflow/README.md): the [state
|
|
168
|
+
machine](docs/workflow/state-machine.md), every [gate](docs/workflow/gates.md), the
|
|
169
|
+
[artifacts](docs/workflow/artifacts.md), the [CLI reference](docs/workflow/cli-reference.md),
|
|
170
|
+
the [harness](docs/workflow/harness.md), the [dashboard](docs/workflow/dashboard.md). Release
|
|
171
|
+
notes: [CHANGELOG.md](CHANGELOG.md).
|
|
172
|
+
|
|
173
|
+
## License — MIT
|
package/dist/cli/args.js
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
const COMMANDS = {
|
|
3
|
+
init: {
|
|
4
|
+
help: "Usage: kf init [path] [--defaults] [--minimal] [--context <ctx>] [--agent <id> ...] — onboarding: asks setup questions on a TTY (defaults when non-TTY or --defaults), seeds .kf config + installs skills; --minimal skips the questions, not the scaffolding (still writes .kf config, skills and AGENTS.md; only the template/hook/rule files are left out)",
|
|
5
|
+
allowPositionals: true,
|
|
6
|
+
options: {
|
|
7
|
+
context: { type: "string", short: "c" },
|
|
8
|
+
interactive: { type: "boolean", short: "i" },
|
|
9
|
+
defaults: { type: "boolean" },
|
|
10
|
+
minimal: { type: "boolean" },
|
|
11
|
+
agent: { type: "string", multiple: true },
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
new: {
|
|
15
|
+
help: "Usage: kf new <feature> [--context <ctx>] [--type feature|bug] — create a work item in .works/brainstorm",
|
|
16
|
+
allowPositionals: true,
|
|
17
|
+
options: {
|
|
18
|
+
context: { type: "string", short: "c" },
|
|
19
|
+
goal: { type: "string", short: "g" },
|
|
20
|
+
type: { type: "string", short: "t" },
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
list: {
|
|
24
|
+
help: "Usage: kf list [--json]",
|
|
25
|
+
options: {
|
|
26
|
+
json: { type: "boolean" },
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
show: {
|
|
30
|
+
help: "Usage: kf show <feature> [--json]",
|
|
31
|
+
allowPositionals: true,
|
|
32
|
+
options: {
|
|
33
|
+
json: { type: "boolean" },
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
view: {
|
|
37
|
+
help: "Usage: kf view [--json] — workflow metrics by stage, kind, context and approval",
|
|
38
|
+
options: {
|
|
39
|
+
json: { type: "boolean" },
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
dashboard: {
|
|
43
|
+
help: "Usage: kf dashboard [--port <n>] — start a local analytics dashboard with metrics and charts (default port 8787)",
|
|
44
|
+
options: {
|
|
45
|
+
port: { type: "string", short: "p" },
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
status: {
|
|
49
|
+
help: "Usage: kf status [--change <feature>] [--all] [--json] — artifact checklist, Next step, approval state and recorded bypasses",
|
|
50
|
+
options: {
|
|
51
|
+
change: { type: "string" },
|
|
52
|
+
all: { type: "boolean", short: "a" },
|
|
53
|
+
json: { type: "boolean" },
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
instruct: {
|
|
57
|
+
help: "Usage: kf instruct <artifact|use-case> [--change <feature>] [--id UC-###] — print the template, current execution id and exact output path",
|
|
58
|
+
allowPositionals: true,
|
|
59
|
+
options: {
|
|
60
|
+
change: { type: "string" },
|
|
61
|
+
id: { type: "string" },
|
|
62
|
+
json: { type: "boolean" },
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
templates: {
|
|
66
|
+
help: "Usage: kf templates [--json]",
|
|
67
|
+
options: {
|
|
68
|
+
json: { type: "boolean" },
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
validate: {
|
|
72
|
+
help: "Usage: kf validate [--change <feature>] [--all] [--strict] [--json] — report gate, traceability, secret and bypass issues (exit 1 on failure)",
|
|
73
|
+
options: {
|
|
74
|
+
change: { type: "string" },
|
|
75
|
+
all: { type: "boolean", short: "a" },
|
|
76
|
+
strict: { type: "boolean" },
|
|
77
|
+
json: { type: "boolean" },
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
stage: {
|
|
81
|
+
help: "Usage: kf stage <feature> <next-stage> [--skip-hooks] — move feature to next stage",
|
|
82
|
+
allowPositionals: true,
|
|
83
|
+
options: {
|
|
84
|
+
force: { type: "boolean", short: "f" },
|
|
85
|
+
"skip-hooks": { type: "boolean" },
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
approve: {
|
|
89
|
+
help: "Usage: kf approve <feature> [--by <name>] — approve Phase 2 execution contract (Human gate)",
|
|
90
|
+
allowPositionals: true,
|
|
91
|
+
options: {
|
|
92
|
+
by: { type: "string" },
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
archive: {
|
|
96
|
+
help: "Usage: kf archive <feature> [--skip-hooks] — close a work item in dones; features sync canonical docs, bugs retain related docs",
|
|
97
|
+
allowPositionals: true,
|
|
98
|
+
options: {
|
|
99
|
+
force: { type: "boolean", short: "f" },
|
|
100
|
+
"skip-specs": { type: "boolean" },
|
|
101
|
+
"skip-hooks": { type: "boolean" },
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
rules: {
|
|
105
|
+
help: "Usage: kf rules [--stack <id> ...] [--list] [--force] — copy stack best-practice review rules into .kf/review/rules (auto-detects stack; packs: node, go, rust, python, php, ruby, java)",
|
|
106
|
+
options: {
|
|
107
|
+
stack: { type: "string", multiple: true },
|
|
108
|
+
list: { type: "boolean" },
|
|
109
|
+
force: { type: "boolean", short: "f" },
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
autoconfig: {
|
|
113
|
+
help: "Usage: kf autoconfig — print a briefing for an agent to configure this project: context, setup checklist, effective review rules and the workflow guide",
|
|
114
|
+
options: {},
|
|
115
|
+
},
|
|
116
|
+
doctor: {
|
|
117
|
+
help: "Usage: kf doctor [--json] — diagnose the project: stage dirs, config, work item metadata, installed skills; exits 1 when something is broken",
|
|
118
|
+
options: {
|
|
119
|
+
json: { type: "boolean" },
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
install: {
|
|
123
|
+
help: "Usage: kf install [--agent <id> ...] — copy the 8 kanban skills into project-level agent skill dirs {root}/.<agent>/skills (default: claude). Requires a kanban project (.works/). Agents: claude, codex, gemini, kiro, cursor, opencode",
|
|
124
|
+
options: {
|
|
125
|
+
agent: { type: "string", multiple: true },
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
uninstall: {
|
|
129
|
+
help: "Usage: kf uninstall [--agent <id> ...] [--purge] [--force] — remove the 8 kanban skills from project-level agent skill dirs {root}/.<agent>/skills (default: claude). --purge also deletes .works/, .kf/ and kanban doc dirs (asks first; --force skips the prompt)",
|
|
130
|
+
options: {
|
|
131
|
+
agent: { type: "string", multiple: true },
|
|
132
|
+
purge: { type: "boolean" },
|
|
133
|
+
force: { type: "boolean" },
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
cancel: {
|
|
137
|
+
help: 'Usage: kf cancel <feature> --reason "<why>" [--by <name>] [--purge-docs] [--force] [--skip-hooks] — stop a work item for good, recording who dropped it and why; reopen later with kf stage <feature> <its old stage>',
|
|
138
|
+
allowPositionals: true,
|
|
139
|
+
options: {
|
|
140
|
+
reason: { type: "string" },
|
|
141
|
+
by: { type: "string" },
|
|
142
|
+
"purge-docs": { type: "boolean" },
|
|
143
|
+
force: { type: "boolean", short: "f" },
|
|
144
|
+
"skip-hooks": { type: "boolean" },
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
run: {
|
|
148
|
+
help: "Usage: kf run <feature> [--stage <s>] [--role <r>] [--fresh] [--detach] [--timeout <min>] [--dry-run] — run the roles assigned to the work item's stage (harness.stages) as worker agents, in order, and record each run",
|
|
149
|
+
allowPositionals: true,
|
|
150
|
+
options: {
|
|
151
|
+
stage: { type: "string" },
|
|
152
|
+
role: { type: "string" },
|
|
153
|
+
agent: { type: "string" },
|
|
154
|
+
fresh: { type: "boolean" },
|
|
155
|
+
detach: { type: "boolean" },
|
|
156
|
+
timeout: { type: "string" },
|
|
157
|
+
"dry-run": { type: "boolean" },
|
|
158
|
+
supervise: { type: "string" },
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
runs: {
|
|
162
|
+
help: "Usage: kf runs [<feature>] [--json] — list worker runs (role, runner, stage, status, STATUS line) for one or all open work items",
|
|
163
|
+
allowPositionals: true,
|
|
164
|
+
options: {
|
|
165
|
+
json: { type: "boolean" },
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
contexts: {
|
|
169
|
+
help: "Usage: kf contexts [--json] — list the declared contexts and the ones work items actually use; prints a survey brief when none are declared",
|
|
170
|
+
options: {
|
|
171
|
+
json: { type: "boolean" },
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
harness: {
|
|
175
|
+
help: "Usage: kf harness [--json] — show the multi-agent harness: stage to role chains, role to runner, and whether each runner CLI is on PATH",
|
|
176
|
+
options: {
|
|
177
|
+
json: { type: "boolean" },
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
help: {
|
|
181
|
+
help: "Usage: kf help [command]",
|
|
182
|
+
allowPositionals: true,
|
|
183
|
+
},
|
|
184
|
+
version: {},
|
|
185
|
+
};
|
|
186
|
+
export function parseArgsCli(argv) {
|
|
187
|
+
const command = argv[0] ?? "help";
|
|
188
|
+
const spec = COMMANDS[command];
|
|
189
|
+
if (!spec)
|
|
190
|
+
return { command, positionals: argv.slice(1), options: {} };
|
|
191
|
+
const opts = {};
|
|
192
|
+
for (const [k, v] of Object.entries(spec.options ?? {})) {
|
|
193
|
+
const d = { type: v.type };
|
|
194
|
+
if (v.short !== undefined)
|
|
195
|
+
d.short = v.short;
|
|
196
|
+
if (v.default !== undefined)
|
|
197
|
+
d.default = v.default;
|
|
198
|
+
if (v.multiple !== undefined)
|
|
199
|
+
d.multiple = v.multiple;
|
|
200
|
+
opts[k] = d;
|
|
201
|
+
}
|
|
202
|
+
opts.help = { type: "boolean", short: "h" };
|
|
203
|
+
const { values, positionals } = parseArgs({
|
|
204
|
+
args: argv.slice(1),
|
|
205
|
+
options: opts,
|
|
206
|
+
allowPositionals: spec.allowPositionals ?? false,
|
|
207
|
+
strict: true,
|
|
208
|
+
});
|
|
209
|
+
return { command, positionals, options: values };
|
|
210
|
+
}
|
|
211
|
+
export function commandHelp(command) {
|
|
212
|
+
const spec = COMMANDS[command];
|
|
213
|
+
if (!spec)
|
|
214
|
+
return `Unknown command: ${command}. Use "kf help".`;
|
|
215
|
+
return spec.help ?? `kf ${command}`;
|
|
216
|
+
}
|
|
217
|
+
export function allCommands() {
|
|
218
|
+
return Object.keys(COMMANDS);
|
|
219
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { findFeature, writeFeatureMeta, executionContractHash } from "../../workflow/features.js";
|
|
2
|
+
import { validateFeature, renderValidateText } from "../../workflow/validate.js";
|
|
3
|
+
import { readProjectConfig } from "../../project/config.js";
|
|
4
|
+
import { nowTimestamp } from "../../shared/time.js";
|
|
5
|
+
import { findRoot } from "./helpers.js";
|
|
6
|
+
/**
|
|
7
|
+
* Human-in-the-Loop gate for Phase 2: the execution contract (implementation
|
|
8
|
+
* plan + use cases + test cases) must be approved before autonomous execution.
|
|
9
|
+
*/
|
|
10
|
+
export async function cmdApprove(args, cwd) {
|
|
11
|
+
const name = args.positionals[0];
|
|
12
|
+
if (!name)
|
|
13
|
+
return { code: 1, stdout: "Usage: kf approve <feature> [--by <name>]", stderr: "missing feature" };
|
|
14
|
+
const root = await findRoot(cwd);
|
|
15
|
+
if (!root.ok)
|
|
16
|
+
return { code: 1, stdout: root.err, stderr: "no works" };
|
|
17
|
+
const f = findFeature(root.root, name);
|
|
18
|
+
if (!f)
|
|
19
|
+
return { code: 1, stdout: `Unknown feature '${name}'. Run: kf list`, stderr: "unknown feature" };
|
|
20
|
+
if (f.stage !== "planning") {
|
|
21
|
+
return {
|
|
22
|
+
code: 1,
|
|
23
|
+
stdout: `Cannot approve '${name}': feature is in stage "${f.stage}". Approval only applies during Phase 2 (planning).`,
|
|
24
|
+
stderr: "wrong stage",
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const check = validateFeature(f, false, false);
|
|
28
|
+
if (!check.valid) {
|
|
29
|
+
return { code: 1, stdout: `Cannot approve an incomplete execution contract:\n${renderValidateText(check)}`, stderr: "invalid contract" };
|
|
30
|
+
}
|
|
31
|
+
const contractHash = executionContractHash(f.dir, f.meta?.kind === "bug" ? "bug" : "feature");
|
|
32
|
+
if (!contractHash || !f.meta)
|
|
33
|
+
return { code: 1, stdout: "Execution contract or metadata is missing.", stderr: "invalid contract" };
|
|
34
|
+
const cfg = readProjectConfig(root.root);
|
|
35
|
+
const by = typeof args.options.by === "string" ? args.options.by : (cfg.reviewer ?? "human");
|
|
36
|
+
if (!by.trim())
|
|
37
|
+
return { code: 1, stdout: "Approver name must not be empty.", stderr: "missing approver" };
|
|
38
|
+
const approval = { status: "approved", by, at: nowTimestamp(), contractHash };
|
|
39
|
+
await writeFeatureMeta(f.dir, { ...f.meta, approval, executionId: undefined });
|
|
40
|
+
return {
|
|
41
|
+
code: 0,
|
|
42
|
+
stdout: `✓ Approved '${name}' (by ${by} at ${approval.at})\n Execution contract is now the binding scope for autonomous phases.`,
|
|
43
|
+
};
|
|
44
|
+
}
|