@sabaiway/agent-workflow-engine 1.0.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/CHANGELOG.md +29 -0
- package/LICENSE +21 -0
- package/README.md +55 -0
- package/SKILL.md +44 -0
- package/bin/install.mjs +179 -0
- package/capability.json +23 -0
- package/package.json +48 -0
- package/references/methodology-slot.md +1 -0
- package/references/planning.md +105 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog — @sabaiway/agent-workflow-engine
|
|
2
|
+
|
|
3
|
+
All notable changes to the methodology engine. Versions are this **package's** npm versions;
|
|
4
|
+
they are distinct from the **deployment-lineage** stamp written into a project's `docs/ai/`
|
|
5
|
+
(which tracks the shared `agent-workflow` lineage, head `1.3.0`).
|
|
6
|
+
|
|
7
|
+
## 1.0.0
|
|
8
|
+
|
|
9
|
+
First publish. The canonical home of the `agent-workflow` planning methodology is now an
|
|
10
|
+
installable, `available:true` npm package — no longer a declared, content-only stub.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Standalone npm package + `bin/install.mjs` installer targeting
|
|
14
|
+
`~/.claude/skills/agent-workflow-engine` (`AGENT_WORKFLOW_ENGINE_DIR`), with a
|
|
15
|
+
symlink-traversal guard — the installer never writes *through* a destination symlink
|
|
16
|
+
(root / intermediate / leaf), and never copies the npm wrapper into the skill dir.
|
|
17
|
+
- `capability.json` flipped to `available:true` with `detect.installed` +
|
|
18
|
+
`install.npm` (`@sabaiway/agent-workflow-engine`). It still only `provides: ["plan"]`
|
|
19
|
+
(the methodology text) with no callable command — it mutates nothing.
|
|
20
|
+
|
|
21
|
+
### Notes
|
|
22
|
+
- The canon itself — `references/planning.md` (the full methodology) and
|
|
23
|
+
`references/methodology-slot.md` (the bounded slot fragment) — is unchanged; this release
|
|
24
|
+
packages it for npm.
|
|
25
|
+
- The composition root (`agent-workflow-kit`) still consumes a **byte-identical,
|
|
26
|
+
drift-guarded mirror** of this canon bundled inside the kit. The live `kit → engine` read
|
|
27
|
+
and retiring that mirror land in the next slice.
|
|
28
|
+
- The deployment-lineage head stays **`1.3.0`** — packaging the engine changes only the npm
|
|
29
|
+
axis, not any deployed project's `docs/ai` structure.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 sabaiway
|
|
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,55 @@
|
|
|
1
|
+
# @sabaiway/agent-workflow-engine
|
|
2
|
+
|
|
3
|
+
**The canonical home of the `agent-workflow` planning methodology.** It owns the
|
|
4
|
+
methodology *text* — the Plan → Phase → Step vocabulary, the plan-file lifecycle
|
|
5
|
+
(`docs/plans/*.md`, ephemeral, never committed), the `queue.md` series index, the mandatory
|
|
6
|
+
final **Phase: Cleanup**, and the bounded methodology slot fragment the family kit injects
|
|
7
|
+
into a deployed project's `AGENTS.md`.
|
|
8
|
+
|
|
9
|
+
This is the **methodology engine** of the `agent-workflow` family — the canonical source the
|
|
10
|
+
rest of the family builds on. It is **content**, not a runtime: it reads nothing, writes
|
|
11
|
+
nothing, and mutates no project file. It deliberately **knows nobody else** in the family —
|
|
12
|
+
it only *provides* the methodology; the family composition root (`agent-workflow-kit`) is the
|
|
13
|
+
one that injects it. The kit currently consumes a **byte-identical, drift-guarded mirror** of
|
|
14
|
+
this canon bundled inside the kit; the live `kit → engine` read (and retiring that mirror)
|
|
15
|
+
lands in the next slice.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx @sabaiway/agent-workflow-engine@latest init
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Installs/refreshes the canon at `~/.claude/skills/agent-workflow-engine` (override with
|
|
24
|
+
`--dir <path>` or `AGENT_WORKFLOW_ENGINE_DIR`). `init` is additive — it never deletes your
|
|
25
|
+
files and never writes through a symlink. Re-running with `@latest` is how you refresh the
|
|
26
|
+
installed canon to the current version.
|
|
27
|
+
|
|
28
|
+
This is a **content** skill (`disable-model-invocation`): it is not a project deploy and is
|
|
29
|
+
not model-invoked. There is nothing to "run" inside an agent — installing it places the
|
|
30
|
+
methodology canon on disk for the family to read.
|
|
31
|
+
|
|
32
|
+
## Use
|
|
33
|
+
|
|
34
|
+
The methodology is consumed by the family composition root, not invoked directly. Day to day
|
|
35
|
+
you install and use the **kit** (`@sabaiway/agent-workflow-kit`), which injects the
|
|
36
|
+
methodology slot into your project's `AGENTS.md`. Install the engine standalone when you want
|
|
37
|
+
the canonical methodology reference on disk:
|
|
38
|
+
|
|
39
|
+
- [`references/planning.md`](references/planning.md) — the **full methodology**: the
|
|
40
|
+
Plan → Phase → Step vocabulary, the plan-file lifecycle, the `queue.md` series index, the
|
|
41
|
+
mandatory final **Phase: Cleanup**, and the plan-then-execute split.
|
|
42
|
+
- [`references/methodology-slot.md`](references/methodology-slot.md) — the **bounded**
|
|
43
|
+
fragment the composition root injects into a deployed `AGENTS.md` (a short summary +
|
|
44
|
+
pointer, kept under the entry point's line cap).
|
|
45
|
+
|
|
46
|
+
## What this package ships
|
|
47
|
+
|
|
48
|
+
`SKILL.md` (the canon overview + ownership rule), `references/` (the full methodology
|
|
49
|
+
reference + the bounded slot fragment), `capability.json` (the family manifest), and this
|
|
50
|
+
installer. It ships **no** family-wide tooling (the schema/validator/injection live in the
|
|
51
|
+
composition root) and mutates nothing — preserving "knows nobody".
|
|
52
|
+
|
|
53
|
+
## License
|
|
54
|
+
|
|
55
|
+
MIT — see [LICENSE](./LICENSE).
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-workflow-engine
|
|
3
|
+
description: Canonical home of the agent-workflow planning methodology — the Plan→Phase→Step→Substep vocabulary, plan lifecycle, queue.md series index, mandatory Cleanup phase, and the bounded methodology slot fragment. A published, installable npm package (available:true) that *provides* the methodology text; it mutates nothing. The composition root (agent-workflow-kit) currently keeps byte-identical mirror copies of this text (drift-guarded) and injects the slot from its mirror; the live kit → engine read + mirror retirement land in the next slice.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
metadata:
|
|
6
|
+
version: '1.0.0'
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# agent-workflow-engine
|
|
10
|
+
|
|
11
|
+
The **canonical source of truth** for the `agent-workflow` planning methodology. It is a
|
|
12
|
+
**published, installable npm package** (`capability.json` → `available:true`): it holds the
|
|
13
|
+
methodology text and **provides** it, but it ships no runtime and mutates no files. The kit
|
|
14
|
+
currently keeps **byte-identical mirror copies** of these files so the live injection + fallback
|
|
15
|
+
keep working with no new dependency; a drift-guard test pins the mirrors to this canon. The live
|
|
16
|
+
`kit → engine` read (and retiring the mirror) lands in the next slice.
|
|
17
|
+
|
|
18
|
+
## What it provides (`provides: ["plan"]`)
|
|
19
|
+
|
|
20
|
+
- [`references/planning.md`](references/planning.md) — the **full methodology**: the
|
|
21
|
+
Plan→Phase→Step→Substep vocabulary, plan-file lifecycle (`docs/plans/*.md`, gitignored, never
|
|
22
|
+
committed), the `queue.md` series index, the mandatory final **Phase: Cleanup**, the
|
|
23
|
+
plan-then-execute split, and the session-continuity heuristic.
|
|
24
|
+
- [`references/methodology-slot.md`](references/methodology-slot.md) — the **bounded** fragment the
|
|
25
|
+
composition root injects into a deployed project's `AGENTS.md`, between the
|
|
26
|
+
`<!-- workflow:methodology:start -->` / `<!-- workflow:methodology:end -->` markers. A short
|
|
27
|
+
summary + pointer, not the full reference, so the entry point stays under its line cap.
|
|
28
|
+
|
|
29
|
+
## Ownership rule (the engine knows nobody)
|
|
30
|
+
|
|
31
|
+
The engine only **provides** text. It never reads, writes, or mutates any project file or any
|
|
32
|
+
sibling skill — in particular it never touches a deployed `AGENTS.md`. **Only the composition root
|
|
33
|
+
(`agent-workflow-kit`) injects the methodology slot.** This keeps the family a DAG: the engine has
|
|
34
|
+
no outbound edges.
|
|
35
|
+
|
|
36
|
+
## Status & roadmap
|
|
37
|
+
|
|
38
|
+
The engine is **no longer a stub**: it is a published, `available:true`, installable npm package
|
|
39
|
+
(`@sabaiway/agent-workflow-engine`). The kit currently keeps **byte-identical mirror copies** of
|
|
40
|
+
this canon (drift-guarded), so the live injection + fallback keep working with no new dependency.
|
|
41
|
+
The live `kit → engine` read (the kit reading this canon from the installed engine instead of its
|
|
42
|
+
bundled mirror) and **retiring that mirror** land in the next slice. See the kit's
|
|
43
|
+
`tools/inject-methodology.mjs` for the marker contract and the slot reconciliation the kit runs on
|
|
44
|
+
bootstrap + upgrade.
|
package/bin/install.mjs
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// One-shot installer for @sabaiway/agent-workflow-engine.
|
|
3
|
+
//
|
|
4
|
+
// npx @sabaiway/agent-workflow-engine init
|
|
5
|
+
//
|
|
6
|
+
// Copies the methodology canon into the canonical skill home
|
|
7
|
+
// (~/.claude/skills/agent-workflow-engine, override with --dir or
|
|
8
|
+
// AGENT_WORKFLOW_ENGINE_DIR). Re-running refreshes the canon to this package's
|
|
9
|
+
// version — that is how you update the installed canon:
|
|
10
|
+
//
|
|
11
|
+
// npx @sabaiway/agent-workflow-engine@latest init
|
|
12
|
+
//
|
|
13
|
+
// The engine is the methodology canon the family kit builds on; it is content,
|
|
14
|
+
// not a project deploy and not a model-invoked skill — there is nothing to "run"
|
|
15
|
+
// inside an agent.
|
|
16
|
+
//
|
|
17
|
+
// No telemetry, no phone-home. Dependency-free, Node >= 18.
|
|
18
|
+
|
|
19
|
+
import { readFile, mkdir, readdir, copyFile, lstat, readlink, symlink } from 'node:fs/promises';
|
|
20
|
+
import { existsSync, lstatSync } from 'node:fs';
|
|
21
|
+
import { dirname, join, resolve, relative, sep, isAbsolute } from 'node:path';
|
|
22
|
+
import { fileURLToPath } from 'node:url';
|
|
23
|
+
import { homedir } from 'node:os';
|
|
24
|
+
|
|
25
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
const PKG_ROOT = resolve(__dirname, '..');
|
|
27
|
+
|
|
28
|
+
// The deployable skill = everything except the npm wrapper (package.json, bin/).
|
|
29
|
+
// Enumerated explicitly (mirrors package.json "files") so a missing payload entry
|
|
30
|
+
// is a loud failure, not a silent partial install.
|
|
31
|
+
const PAYLOAD = [
|
|
32
|
+
'SKILL.md',
|
|
33
|
+
'README.md',
|
|
34
|
+
'CHANGELOG.md',
|
|
35
|
+
'LICENSE',
|
|
36
|
+
'capability.json',
|
|
37
|
+
'references',
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
const tildify = (path) => path.replace(homedir(), '~');
|
|
41
|
+
|
|
42
|
+
const readVersion = async () => {
|
|
43
|
+
try {
|
|
44
|
+
const pkg = JSON.parse(await readFile(resolve(PKG_ROOT, 'package.json'), 'utf8'));
|
|
45
|
+
return pkg.version ?? 'unknown';
|
|
46
|
+
} catch {
|
|
47
|
+
return 'unknown';
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// lstat without following symlinks; null when the path does not exist. Using lstat (not
|
|
52
|
+
// existsSync, which FOLLOWS symlinks and so reports a *dangling* symlink as absent) is what
|
|
53
|
+
// makes the guard below catch a dangling destination symlink too.
|
|
54
|
+
const lstatNoFollow = (path) => {
|
|
55
|
+
try {
|
|
56
|
+
return lstatSync(path);
|
|
57
|
+
} catch (err) {
|
|
58
|
+
if (err && err.code === 'ENOENT') return null;
|
|
59
|
+
throw err; // EACCES/EIO etc. must NOT fail open (be read as "not a symlink")
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// Symlink-traversal guard: refuse to write *through* any symlink at or above `dest`
|
|
64
|
+
// within `root`. Walks `root` plus each existing path component down to `dest`; if the
|
|
65
|
+
// root, an intermediate dir, or the leaf is a symlink (including a dangling one), a copy
|
|
66
|
+
// could escape the target — STOP rather than follow it. Also refuses a dest outside `root`.
|
|
67
|
+
const assertContainedRealPath = (root, dest) => {
|
|
68
|
+
const rel = relative(root, dest);
|
|
69
|
+
if (rel.startsWith('..') || isAbsolute(rel)) {
|
|
70
|
+
throw new Error(`[agent-workflow-engine] refusing to write outside the target dir: ${dest}`);
|
|
71
|
+
}
|
|
72
|
+
if (lstatNoFollow(root)?.isSymbolicLink()) {
|
|
73
|
+
throw new Error(`[agent-workflow-engine] refusing to install into a symlinked target dir: ${root}`);
|
|
74
|
+
}
|
|
75
|
+
const walk = (acc, part) => {
|
|
76
|
+
const cur = join(acc, part);
|
|
77
|
+
if (lstatNoFollow(cur)?.isSymbolicLink()) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`[agent-workflow-engine] refusing to write through a symlink at ${cur} (would escape ${root}).`,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
return cur;
|
|
83
|
+
};
|
|
84
|
+
rel.split(sep).filter(Boolean).reduce(walk, root);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const copyRecursive = async (src, dest, root) => {
|
|
88
|
+
assertContainedRealPath(root, dest); // never write through a dest symlink (root/intermediate/leaf)
|
|
89
|
+
const stat = await lstat(src);
|
|
90
|
+
if (stat.isSymbolicLink()) {
|
|
91
|
+
if (existsSync(dest)) return; // additive: never delete/replace an existing entry
|
|
92
|
+
const linkTarget = await readlink(src);
|
|
93
|
+
await symlink(linkTarget, dest);
|
|
94
|
+
} else if (stat.isDirectory()) {
|
|
95
|
+
await mkdir(dest, { recursive: true });
|
|
96
|
+
const entries = await readdir(src);
|
|
97
|
+
await Promise.all(entries.map((entry) => copyRecursive(join(src, entry), join(dest, entry), root)));
|
|
98
|
+
} else {
|
|
99
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
100
|
+
await copyFile(src, dest);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const parseArgs = (argv) => {
|
|
105
|
+
const dirFlag = argv.indexOf('--dir');
|
|
106
|
+
return {
|
|
107
|
+
help: argv.includes('--help') || argv.includes('-h'),
|
|
108
|
+
version: argv.includes('--version') || argv.includes('-v'),
|
|
109
|
+
dir: dirFlag >= 0 ? argv[dirFlag + 1] : undefined,
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const resolveTarget = (dirArg) => {
|
|
114
|
+
if (dirArg) return resolve(dirArg);
|
|
115
|
+
if (process.env.AGENT_WORKFLOW_ENGINE_DIR) return resolve(process.env.AGENT_WORKFLOW_ENGINE_DIR);
|
|
116
|
+
return resolve(homedir(), '.claude/skills/agent-workflow-engine');
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const printHelp = (version) => {
|
|
120
|
+
console.log(`agent-workflow-engine ${version}
|
|
121
|
+
|
|
122
|
+
Usage:
|
|
123
|
+
npx @sabaiway/agent-workflow-engine init [--dir <path>]
|
|
124
|
+
npx @sabaiway/agent-workflow-engine --version
|
|
125
|
+
npx @sabaiway/agent-workflow-engine --help
|
|
126
|
+
|
|
127
|
+
Installs/refreshes the methodology canon at ~/.claude/skills/agent-workflow-engine
|
|
128
|
+
(override with --dir <path> or AGENT_WORKFLOW_ENGINE_DIR). init is additive —
|
|
129
|
+
it never deletes your files and never writes through a symlink.
|
|
130
|
+
|
|
131
|
+
The engine is the methodology canon the family kit builds on — it is content, not a
|
|
132
|
+
project deploy and not a model-invoked skill, so there is nothing to run inside an agent.
|
|
133
|
+
Re-run this command to update the installed canon:
|
|
134
|
+
npx @sabaiway/agent-workflow-engine@latest init`);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const main = async () => {
|
|
138
|
+
const version = await readVersion();
|
|
139
|
+
const args = parseArgs(process.argv.slice(2));
|
|
140
|
+
|
|
141
|
+
if (args.help) return printHelp(version);
|
|
142
|
+
if (args.version) return console.log(version);
|
|
143
|
+
|
|
144
|
+
const missing = PAYLOAD.filter((entry) => !existsSync(resolve(PKG_ROOT, entry)));
|
|
145
|
+
if (missing.includes('SKILL.md')) {
|
|
146
|
+
console.error('[agent-workflow-engine] package payload missing (no SKILL.md) — corrupt install?');
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
if (missing.length > 0) {
|
|
150
|
+
console.error(`[agent-workflow-engine] package payload incomplete — missing: ${missing.join(', ')}`);
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const target = resolveTarget(args.dir);
|
|
155
|
+
const wasPresent = existsSync(resolve(target, 'SKILL.md'));
|
|
156
|
+
// If the target dir itself is a symlink (incl. dangling), refuse before writing through it.
|
|
157
|
+
// (copyRecursive re-checks per entry; this fails fast with a clear message.)
|
|
158
|
+
if (lstatNoFollow(target)?.isSymbolicLink()) {
|
|
159
|
+
console.error(`[agent-workflow-engine] target dir is a symlink — refusing to write through it: ${tildify(target)}`);
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
await mkdir(target, { recursive: true });
|
|
163
|
+
await Promise.all(
|
|
164
|
+
PAYLOAD.map((entry) => copyRecursive(resolve(PKG_ROOT, entry), resolve(target, entry), target)),
|
|
165
|
+
);
|
|
166
|
+
console.log(
|
|
167
|
+
`[agent-workflow-engine] ${wasPresent ? 'updated the canon to' : 'installed'} v${version} -> ${tildify(target)}`,
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
console.log(`
|
|
171
|
+
This installed the methodology canon at ${tildify(target)}. The engine is content the
|
|
172
|
+
family kit builds on — there is nothing to run inside an agent.
|
|
173
|
+
To update it later, re-run: npx @sabaiway/agent-workflow-engine@latest init`);
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
main().catch((err) => {
|
|
177
|
+
console.error(err);
|
|
178
|
+
process.exit(1);
|
|
179
|
+
});
|
package/capability.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"family": "agent-workflow",
|
|
3
|
+
"schema": 1,
|
|
4
|
+
"name": "agent-workflow-engine",
|
|
5
|
+
"kind": "methodology-engine",
|
|
6
|
+
"version": "1.0.0",
|
|
7
|
+
"available": true,
|
|
8
|
+
"provides": ["plan"],
|
|
9
|
+
"roles": {},
|
|
10
|
+
"detect": {
|
|
11
|
+
"installed": {
|
|
12
|
+
"env": "AGENT_WORKFLOW_ENGINE_DIR",
|
|
13
|
+
"default": "~/.claude/skills/agent-workflow-engine",
|
|
14
|
+
"file": "SKILL.md"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"install": { "npm": "@sabaiway/agent-workflow-engine" },
|
|
18
|
+
"uninstall": {
|
|
19
|
+
"removeResolved": "detect.installed",
|
|
20
|
+
"note": "init copies into the skill dir; uninstall removes the resolved detect.installed dir — not an npm dependency"
|
|
21
|
+
},
|
|
22
|
+
"provenance": { "author": "sabaiway", "source": "github:sabaiway/agent-workflow" }
|
|
23
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sabaiway/agent-workflow-engine",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Canonical home of the agent-workflow planning methodology — the Plan→Phase→Step vocabulary, plan lifecycle, queue.md series index, and mandatory Cleanup phase, consumed by the kit (composition root). The methodology engine of the agent-workflow family.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai-agents",
|
|
7
|
+
"ai-coding",
|
|
8
|
+
"coding-agent",
|
|
9
|
+
"llm",
|
|
10
|
+
"ai-tools",
|
|
11
|
+
"claude-code",
|
|
12
|
+
"agents-md",
|
|
13
|
+
"workflow",
|
|
14
|
+
"planning",
|
|
15
|
+
"methodology",
|
|
16
|
+
"developer-tools"
|
|
17
|
+
],
|
|
18
|
+
"homepage": "https://github.com/sabaiway/agent-workflow#readme",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/sabaiway/agent-workflow/issues"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/sabaiway/agent-workflow.git",
|
|
25
|
+
"directory": "agent-workflow-engine"
|
|
26
|
+
},
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"author": "sabaiway",
|
|
29
|
+
"type": "module",
|
|
30
|
+
"bin": {
|
|
31
|
+
"agent-workflow-engine": "bin/install.mjs"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"bin/",
|
|
35
|
+
"SKILL.md",
|
|
36
|
+
"README.md",
|
|
37
|
+
"CHANGELOG.md",
|
|
38
|
+
"LICENSE",
|
|
39
|
+
"capability.json",
|
|
40
|
+
"references/"
|
|
41
|
+
],
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=18"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
> **Workflow methodology** — plan → execute → review. Plans are ephemeral `docs/plans/*.md` (gitignored, **never committed**); every Plan ends with a mandatory **Phase: Cleanup**; series order lives in `docs/plans/queue.md`. Full vocabulary, lifecycle, and the plan-then-execute split live in the project's **planning skill** (it overrides the generic `writing-plans`); summary in `docs/ai/agent_rules.md` §5.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Planning Workflow
|
|
2
|
+
|
|
3
|
+
Source of truth for **how plans are written, stored, executed, and torn down**. Overrides the generic `writing-plans` skill — if both trigger, this one wins. Runtime series status (which plan is Current / Pending) lives in `docs/plans/queue.md`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Plan vocabulary
|
|
8
|
+
|
|
9
|
+
Strict four-level hierarchy, used in plan files (`docs/plans/*.md`) and in verbal summaries:
|
|
10
|
+
|
|
11
|
+
- **Plan** — top-level container = the plan file itself. One file = one Plan. A series of related plans is not grouped under any wrapper noun; refer to them as "Plan 1 of N", "the next plan". Series order lives in `queue.md` (§3).
|
|
12
|
+
- **Phase** — a large block inside the Plan. Exactly one execution session. Ends with its own verification block. `## Phase 1: …`, `## Phase 2: …`.
|
|
13
|
+
- **Step** — an atomic change inside a Phase. Numbered `<phase>.<step>`: `### 1.1. …`. One Step → one logical commit.
|
|
14
|
+
- **Substep** — optional split of a complex Step. Lettered: `**1.2.a**`, `**1.2.b**`. Use only when a Step cannot be one command.
|
|
15
|
+
|
|
16
|
+
Reserve the word "task" for the todo list and `active_plan.md` — not for plan structure.
|
|
17
|
+
|
|
18
|
+
## 2. Plan directory & lifecycle
|
|
19
|
+
|
|
20
|
+
Plan files are **ephemeral, machine-local scratch space**, gitignored (`.gitignore` contains `docs/plans/`).
|
|
21
|
+
|
|
22
|
+
**Lifecycle:** Creation (untracked file) → Execution (Phases 1..N-1) → mandatory **Phase N: Cleanup** (§4) → Post-deletion (only `changelog.md` + ADRs remain). Plans are **NEVER committed** — full stop. Even if a plan looks load-bearing (referenced by an ADR), inline the load-bearing content into a persistent doc and delete the plan file.
|
|
23
|
+
|
|
24
|
+
**Forbidden:** `git add` of any plan file; plan-file paths in committed docs; leaving plan files on disk after Cleanup. If the user says "commit the plan" — ask back: "the plan is ephemeral — what exactly should I inline into `decisions.md` / `changelog.md`?".
|
|
25
|
+
|
|
26
|
+
## 3. Series & queue.md
|
|
27
|
+
|
|
28
|
+
A **series** = 2+ related plans that share a roadmap. The index lives at `docs/plans/queue.md` (gitignored, machine-local):
|
|
29
|
+
|
|
30
|
+
```markdown
|
|
31
|
+
## Series: <name>
|
|
32
|
+
|
|
33
|
+
### Current
|
|
34
|
+
- **Plan N / M** — <slug> — <one-line description>
|
|
35
|
+
|
|
36
|
+
### Pending
|
|
37
|
+
- **Plan N+1 / M** — <slug or TBD> — <description>
|
|
38
|
+
|
|
39
|
+
### Done
|
|
40
|
+
- **Plan K / M** — <slug> — done YYYY-MM-DD. Outputs: <pointers>.
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`queue.md` is initialised when the **first** plan of a series is written, not during its Cleanup — without an upfront index the execution agent has no map of the series. Each plan's Cleanup then marks itself Done (with outputs) and promotes the next plan to Current. A single, unrelated plan does not need a series entry.
|
|
44
|
+
|
|
45
|
+
## 4. Required Cleanup phase
|
|
46
|
+
|
|
47
|
+
Every Plan MUST end with a final **Phase N: Cleanup** — the last numbered Phase. Without it the Plan is not done.
|
|
48
|
+
|
|
49
|
+
Minimum content:
|
|
50
|
+
|
|
51
|
+
- **Migrate outputs** → `docs/ai/decisions.md` (AD-XXX), `changelog.md`, `known_issues.md` (Issue-XXX), `current_state.md`, `pages/<page>.md`.
|
|
52
|
+
- **Inline cross-references** — `grep -rn "<plan-slug>" docs/` must be empty. Every pointer is rewritten inline or removed.
|
|
53
|
+
- **Update `queue.md`** — if part of a series, mark Done + promote next.
|
|
54
|
+
- **Delete the plan file** — `rm docs/plans/<slug>.md`.
|
|
55
|
+
- **Verification** — `grep -rn "<slug>" .` empty; `ls docs/plans/<slug>.md` → No such file; docs cap-validator green.
|
|
56
|
+
|
|
57
|
+
If a Plan is aborted mid-flight, Cleanup still runs — partial outputs land in `known_issues.md`, then the file is deleted.
|
|
58
|
+
|
|
59
|
+
## 5. All work in plans
|
|
60
|
+
|
|
61
|
+
Anything required for the task is a **Step inside the Plan**. Nothing "before the plan", "between plans", or "don't forget" — those evaporate at execution time because the execution agent reads only the plan file, not chat scrollback. Every dependency, check, and install is its own Step or Substep. The final "Next steps" section contains **only user-actionable** items.
|
|
62
|
+
|
|
63
|
+
## 6. Plan-then-execute split
|
|
64
|
+
|
|
65
|
+
Default workflow for non-trivial features (multi-file change, new service + hook + UI, architectural choices): write a **self-contained Plan** and stop. Implementation runs in a fresh session via the `executing-plans` skill.
|
|
66
|
+
|
|
67
|
+
- Triggers: any feature, refactor, or change touching more than ~1 file, or non-obvious architectural choices.
|
|
68
|
+
- Does NOT apply to typos, one-line fixes, doc-only edits, or pure "where is X" research — those run inline.
|
|
69
|
+
- The Plan must be readable cold by a fresh agent: file paths, contracts, execution order, verification, gotchas — all inside the file.
|
|
70
|
+
|
|
71
|
+
This split is a token-efficiency strategy: exploration context stays out of the execution window.
|
|
72
|
+
|
|
73
|
+
### Session-continuity heuristic (split vs continue)
|
|
74
|
+
|
|
75
|
+
The volume trigger above (files / LoC / tokens) is necessary but not sufficient. The deeper question is whether the planning context is the execution **payload** or **noise**:
|
|
76
|
+
|
|
77
|
+
- **Split** (fresh session) when planning exploration was *broad fan-out* — many files skimmed, sub-agent dumps, wide searches to *locate* things. That context is noise for execution; discard it.
|
|
78
|
+
- **Continue** in the current session when ALL hold: (1) exploration was *targeted-deep* — you read the exact files to be created/modified/copied, so execution would just re-read them; (2) no new heavy exploration is needed to execute; (3) the context budget is healthy (far from the window limit / Lost-in-the-Middle).
|
|
79
|
+
- When continuing, each Phase's Verification block is a natural checkpoint. If different Phases need different cold context, continue only through the warm Phases, then split.
|
|
80
|
+
|
|
81
|
+
## 7. Plan-document structure
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
# Plan: <human-readable title>
|
|
85
|
+
|
|
86
|
+
## Context ← why this Plan exists, current state, why now (reads cold)
|
|
87
|
+
## Approach ← chosen design + an explicit "What we are NOT doing"
|
|
88
|
+
## Phase 1: <name>
|
|
89
|
+
### 1.1. <step> ← exact paths + commands
|
|
90
|
+
## Phase 2: <name>
|
|
91
|
+
...
|
|
92
|
+
## Phase N: Cleanup ← mandatory (§4)
|
|
93
|
+
## Critical files ← table: file → change kind (new / modify / delete / move)
|
|
94
|
+
## Reuse ← pointers to existing patterns/snippets to copy, not re-derive
|
|
95
|
+
## Verification ← full check sequence (mechanical + behavioural)
|
|
96
|
+
## Next steps ← user-actionable only (§5)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## 8. Self-review checklist (before finalizing a Plan)
|
|
100
|
+
|
|
101
|
+
- Every Step has exact file paths and exact commands.
|
|
102
|
+
- Every recommendation that used to live outside the Plan is now a Step (§5).
|
|
103
|
+
- Vocabulary is strict (§1); the Plan ends with **Phase N: Cleanup** (§4).
|
|
104
|
+
- If part of a series: `queue.md` is initialised / updated (§3).
|
|
105
|
+
- No `git add <plan>` and no "commit the plan" wording in the final report.
|