@ecc-hgy/ae 0.2.0 → 0.4.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/README.md CHANGED
@@ -5,12 +5,34 @@
5
5
 
6
6
  Agentic Engineering is a lightweight personal software lifecycle method: SDD records what to build, TDD drives how to prove it works. It is delivered as a zero-dependency npm CLI plus agent skills for Claude Code and Codex.
7
7
 
8
+ ## How It Works
9
+
10
+ ```text
11
+ (one-time) ─────▶ S0 Bootstrap · ae setup → ae init
12
+
13
+ (each request) ──▶ Router · is this request a *need*?
14
+
15
+ ┌──── no ────┴──── yes ────┐
16
+ ▼ ▼
17
+ just do it enter S1 Main Loop
18
+ (Q&A / quick fix / │
19
+ throwaway script) ├─ A. Need: align → PRD → design → todo → TDD → verify
20
+ └─ B. Accept: accept → debug → fix → reverify → sediment
21
+
22
+ ▼ (rules proven useful)
23
+ S2 Evolution
24
+
25
+ Legend: SDD = align→PRD→design→todo · TDD = TDD→verify, fix→reverify
26
+ State: spec/ = what to build (persistent) · INDEX.md = need@node · handoff.md = session snapshot
27
+ ```
28
+
29
+ A router (the `using-agentic-engineering` skill) gates each non-trivial request: a *need* enters the SDD+TDD loop, everything else is just done. Questions, quick fixes, and throwaway scripts never pay the ceremony.
30
+
8
31
  ## Quick Start
9
32
 
10
33
  ```bash
11
34
  cd /your/project
12
35
  npx @ecc-hgy/ae setup
13
- # Optional: edit config/ae-rules.md
14
36
  npx @ecc-hgy/ae init "one-line project goal"
15
37
  ```
16
38
 
@@ -18,23 +40,27 @@ npx @ecc-hgy/ae init "one-line project goal"
18
40
 
19
41
  - `skills/` -> `.claude/skills/`
20
42
  - `skills/` -> `.codex/skills/`
21
- - `templates/ae-rules.md` -> `config/ae-rules.md`
22
43
 
23
- `ae init` creates the platform-neutral project skeleton, renders entry files, and syncs the contents of `config/ae-rules.md` into the managed `AE:RULES` block in `AGENTS.md` and `CLAUDE.md`.
44
+ `ae init` creates the platform-neutral project skeleton and renders entry files. Project-specific rules live directly in `AGENTS.md`.
24
45
 
25
46
  ## CLI
26
47
 
27
48
  ```bash
28
49
  ae setup
29
50
  ae init "one-line project goal"
30
- ae init "goal" --rules /path/to/rules.md
31
51
  ae --help
32
52
  ae --version
33
53
  ```
34
54
 
35
- Both commands are idempotent. They create missing files, skip existing files, and never overwrite user edits outside the managed `AE:RULES` block. There is no `--force` mode.
55
+ Both commands are idempotent. They create missing files, skip existing files, and never overwrite existing entry files. There is no `--force` mode.
36
56
 
37
- `ae init` requires `ae setup` to have run first. This keeps the two-step workflow explicit so you can edit `config/ae-rules.md` before it is injected.
57
+ `ae init` requires `ae setup` to have run first. This keeps asset installation explicit before skeleton creation.
58
+
59
+ ## Single Source Of Truth
60
+
61
+ - `AGENTS.md` is the canonical project instructions file.
62
+ - `CLAUDE.md` is a short pointer to `AGENTS.md`; do not maintain a separate copy there.
63
+ - `ae init` renders `AGENTS.md` nearly blank (title + goal); add your own rules and sections as the project grows — no imposed format.
38
64
 
39
65
  ## Platform Scope
40
66
 
@@ -63,6 +89,7 @@ The two hard gates are:
63
89
 
64
90
  | Skill | Role |
65
91
  |-------|------|
92
+ | `using-agentic-engineering` | Router: at the start of a non-trivial change, decides whether it enters the SDD+TDD loop and dispatches to the right node skill. |
66
93
  | `brainstorming` | Coarse requirement alignment before writing PRD. |
67
94
  | `grill-me` | Fine-grained questioning for interface, field, parameter, or expected-state ambiguity. |
68
95
  | `to-prd` | Writes `spec/needs/<need-name>/prd.md`. |
@@ -75,6 +102,7 @@ The two hard gates are:
75
102
  | `handoff` | Writes the latest session snapshot to `handoff.md`. |
76
103
  | `improve-codebase-architecture` | User-triggered architecture deepening review. |
77
104
  | `zoom-out` | User-triggered higher-level codebase map. |
105
+ | `karpathy-guidelines` | Always-on coding discipline during A5/B5: think before coding, simplicity first, surgical changes, goal-driven execution. |
78
106
 
79
107
  ## Documentation
80
108
 
@@ -90,7 +118,7 @@ The two hard gates are:
90
118
  bin/ npm executable entry
91
119
  src/ zero-dependency CLI implementation
92
120
  skills/ Selected Agentic Engineering skills
93
- templates/ Entry file templates and the ae-rules.md starter
121
+ templates/ Entry file templates
94
122
  docs/ User-facing methodology docs
95
123
  design/ Design records for this repository
96
124
  tests/ node:test coverage for CLI behavior
@@ -98,10 +126,16 @@ tests/ node:test coverage for CLI behavior
98
126
 
99
127
  ## Roadmap
100
128
 
101
- 1. Stage 2: npm CLI asset distribution with `init` and `ingest-mother`. Superseded by v0.2.
102
- 2. v0.2: split CLI into `setup` + `init`, remove slash command assets, and move rule sync into `ae init`.
103
- 3. Stage 3: design `ae update` for skill/template upgrades and implement `ae index-rebuild`.
104
- 4. Add CI and Windows path validation before broader distribution.
129
+ Completed:
130
+
131
+ - v0.2: split CLI into `setup` + `init` and remove slash command assets.
132
+ - v0.3: remove rules injection; make `AGENTS.md` the single source of truth and `CLAUDE.md` a pointer.
133
+
134
+ Next:
135
+
136
+ 1. Design `ae update` for skill/template upgrades.
137
+ 2. Implement `ae index-rebuild`.
138
+ 3. Add CI and Windows path validation before broader distribution.
105
139
 
106
140
  ## Limits
107
141
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ecc-hgy/ae",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Agentic Engineering is a lightweight personal software lifecycle method: SDD records what to build, TDD drives how to prove it works.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -18,7 +18,7 @@ If B2 has NOT been completed (the expected behavior is still ambiguous), STOP an
18
18
 
19
19
  ## Exit Contract (hand-off to B4)
20
20
 
21
- After Phase 6, do NOT write the issue file inline - that is B4's job. Instead, hand off a structured summary so B4 can write `spec/needs/<need-name>/issues/<topic>.md` in one pass, using the 7-section format in [assets/issue-7-sections.md](assets/issue-7-sections.md).
21
+ After Phase 6, do NOT write the issue file inline - that is B4's job. Instead, hand off a structured summary so B4 can write `spec/needs/<need-name>/issues/<topic>.md` (`<topic>` is kebab-case) in one pass, using the 7-section format in [assets/issue-7-sections.md](assets/issue-7-sections.md).
22
22
 
23
23
  Sections this skill is expected to populate:
24
24
 
@@ -0,0 +1,64 @@
1
+ ---
2
+ name: karpathy-guidelines
3
+ description: Behavioral guidelines to reduce common LLM coding mistakes. Use when writing, reviewing, or refactoring code to avoid overcomplication, make surgical changes, surface assumptions, and define verifiable success criteria.
4
+ license: MIT
5
+ ---
6
+
7
+ # Karpathy Guidelines
8
+ **Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment.
9
+
10
+ ## 1. Think Before Coding
11
+
12
+ **Don't assume. Don't hide confusion. Surface tradeoffs.**
13
+
14
+ Before implementing:
15
+ - State your assumptions explicitly. If uncertain, ask.
16
+ - If multiple interpretations exist, present them - don't pick silently.
17
+ - If a simpler approach exists, say so. Push back when warranted.
18
+ - If something is unclear, stop. Name what's confusing. Ask.
19
+
20
+ ## 2. Simplicity First
21
+
22
+ **Minimum code that solves the problem. Nothing speculative.**
23
+
24
+ - No features beyond what was asked.
25
+ - No abstractions for single-use code.
26
+ - No "flexibility" or "configurability" that wasn't requested.
27
+ - No error handling for impossible scenarios.
28
+ - If you write 200 lines and it could be 50, rewrite it.
29
+
30
+ Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
31
+
32
+ ## 3. Surgical Changes
33
+
34
+ **Touch only what you must. Clean up only your own mess.**
35
+
36
+ When editing existing code:
37
+ - Don't "improve" adjacent code, comments, or formatting.
38
+ - Don't refactor things that aren't broken.
39
+ - Match existing style, even if you'd do it differently.
40
+ - If you notice unrelated dead code, mention it - don't delete it.
41
+
42
+ When your changes create orphans:
43
+ - Remove imports/variables/functions that YOUR changes made unused.
44
+ - Don't remove pre-existing dead code unless asked.
45
+
46
+ The test: Every changed line should trace directly to the user's request.
47
+
48
+ ## 4. Goal-Driven Execution
49
+
50
+ **Define success criteria. Loop until verified.**
51
+
52
+ Transform tasks into verifiable goals:
53
+ - "Add validation" → "Write tests for invalid inputs, then make them pass"
54
+ - "Fix the bug" → "Write a test that reproduces it, then make it pass"
55
+ - "Refactor X" → "Ensure tests pass before and after"
56
+
57
+ For multi-step tasks, state a brief plan:
58
+ ```
59
+ 1. [Step] → verify: [check]
60
+ 2. [Step] → verify: [check]
61
+ 3. [Step] → verify: [check]
62
+ ```
63
+
64
+ Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: review
3
- description: Two-axis review (Standards / Spec) of the changes for a need that is about to close, followed by sedimentation routing - review findings flow into prd.md / design.md / spec/ADR/ / S2 candidates per `spec-framework.md`. Used at S1 node B7.
3
+ description: Two-axis review (Standards / Spec) of the changes for a need that is about to close, followed by sedimentation routing - review findings flow into prd.md / design.md / spec/ADR/ / S2 candidates per `spec/AGENTS.md`. Used at S1 node B7.
4
4
  ---
5
5
 
6
6
  # Review
@@ -96,7 +96,7 @@ After routing:
96
96
  - Set every `issues/*.md` referenced in this close to "已验收"
97
97
  - If any `prd.md` / `design.md` was patched, leave `status: active` and refresh `last-aligned`
98
98
  - If a new ADR was created, add a row under `## ADR` with `status: proposed`
99
- - If unsure, run `/ae-index-rebuild`
99
+ - If unsure, run `ae index-rebuild`
100
100
  2. Print a one-block summary to the user:
101
101
  - Findings routed to prd / design / ADR / S2-candidates with counts
102
102
  - Files modified (path list)
@@ -135,8 +135,8 @@ After all tests pass, look for [refactor candidates](refactoring.md):
135
135
  1. Tick the corresponding `- [ ]` -> `- [x]` in `spec/needs/<need-name>/todo.md`
136
136
  2. Update `spec/INDEX.md`:
137
137
  - Bump the `todo` column counter (e.g. `2/8` -> `3/8`)
138
- - If all `## 实施` items are now checked, set `当前节点` to `A6 verify` (per `spec-framework.md` INDEX rules)
139
- - If unsure, run `/ae-index-rebuild`
138
+ - If all `## 实施` items are now checked, set `当前节点` to `A6 verify` (per `spec/AGENTS.md` INDEX rules)
139
+ - If unsure, run `ae index-rebuild`
140
140
  3. Commit. Suggested message: `feat(<need-name>): T<n> <title>`.
141
141
 
142
142
  ## After All Slices Checked (A5 only)
@@ -68,8 +68,8 @@ Format summary (full rules live in [`todo-template.md`](todo-template.md)):
68
68
 
69
69
  1. Update `spec/INDEX.md`:
70
70
  - Set the `todo` column to `0/N` (where N = total tasks in `## 实施`)
71
- - Recompute the `当前节点` column per the rules in `spec-framework.md` §INDEX 推导规则 (likely now `A5 执行`)
72
- - If unsure, run `/ae-index-rebuild` for an idempotent rescan
71
+ - Recompute the `当前节点` column per the rules in `spec/AGENTS.md` §INDEX 推导规则 (likely now `A5 执行`)
72
+ - If unsure, run `ae index-rebuild` for an idempotent rescan
73
73
  2. Hand off to the next S1 node: A5 `tdd` will read this `todo.md` (plus `design.md`) and drive the red-green-refactor loop. Tell the user the task list is ready and recommend invoking `tdd` next.
74
74
 
75
75
  ## Boundaries
@@ -13,13 +13,13 @@
13
13
  - B1 <blocker description, link back to the design section that needs sharpening>
14
14
 
15
15
  <!--
16
- Rules for maintaining this file (see also `spec-framework.md` §frontmatter / todo.md):
16
+ Rules for maintaining this file:
17
17
 
18
18
  - NO frontmatter — this is a rolling working artifact, not a stateful spec document.
19
19
  - Use `- [ ]` for unfinished, `- [x]` for finished. Never delete completed items — they are visible history.
20
20
  - Sort by dependency order (blockers first); within the same level, sort by suggested execution order.
21
21
  - If a slice depends on a design decision that is still open, put it in `## 阻塞 / 待澄清` instead of `## 实施`.
22
- - Each slice MUST be traceable to a section in `design.md`. If a new slice has no traceable design section, that itself is a finding — go back and patch `design.md` rather than smuggling new scope into `todo.md` (matches `spec-framework.md` §边界规则: "todo 不应该出现 design 里没提的事").
22
+ - Each slice MUST be traceable to a section in `design.md`. If a new slice has no traceable design section, that itself is a finding — go back and patch `design.md` rather than smuggling new scope into `todo.md`.
23
23
  - Slice identifiers: `T<n>` for execution tasks, `B<n>` for blockers. Stable across the life of the need; do not renumber.
24
24
  - Acceptance criteria: a single observable behavior that proves the slice is done. If it needs multiple lines, the slice is probably too coarse — split it.
25
25
  -->
@@ -15,7 +15,7 @@ Check with the user that these seams match their expectations.
15
15
 
16
16
  2.5. Align the `need-name` (kebab-case) with the user. This is the slug used to create `spec/needs/<need-name>/`. Surface a concrete suggestion derived from the PRD topic and confirm before writing.
17
17
 
18
- 3. Write the PRD using the template below. Save it to `spec/needs/<need-name>/prd.md` with the frontmatter block shown below the template. After saving, update `spec/INDEX.md` (add or update the row for this need) — or run `/ae-index-rebuild` to recompute.
18
+ 3. Write the PRD using the template below. Save it to `spec/needs/<need-name>/prd.md` with the frontmatter block shown below the template. After saving, update `spec/INDEX.md` (add or update the row for this need) — or run `ae index-rebuild` to recompute.
19
19
 
20
20
  <prd-template>
21
21
 
@@ -97,8 +97,8 @@ State transitions:
97
97
  1. Update `spec/INDEX.md`:
98
98
  - If the need is new: add a row under `## 需求`
99
99
  - If updating: set the `prd` column to `active`
100
- - Recompute the `当前节点` column per the rules in `spec-framework.md` §INDEX 推导规则
101
- - If unsure, run `/ae-index-rebuild` for an idempotent rescan
100
+ - Recompute the `当前节点` column per the rules in `spec/AGENTS.md` §INDEX 推导规则
101
+ - If unsure, run `ae index-rebuild` for an idempotent rescan
102
102
  2. Hand off to the next S1 node: A3 `writing-plans` will read this `prd.md` and produce `spec/needs/<need-name>/design.md`. Tell the user the PRD is ready and recommend invoking `writing-plans` next.
103
103
 
104
104
  ## Boundaries
@@ -0,0 +1,62 @@
1
+ ---
2
+ name: using-agentic-engineering
3
+ description: Router for projects that use Agentic Engineering. Use at the start of a feature, bug fix, or other non-trivial change to decide whether it should enter the SDD+TDD loop and which node/skill to start from. Skip for quick fixes, questions, and throwaway scripts.
4
+ ---
5
+
6
+ # Using Agentic Engineering
7
+
8
+ This project follows the **Agentic Engineering** method: SDD records *what to build* (in `spec/`), TDD proves *it works*. This skill is a **router** — it decides whether the current request enters that loop and, if so, hands off to the right node skill. It does not carry the method itself; each node has its own skill.
9
+
10
+ ## Instruction priority
11
+
12
+ 1. **The user's explicit request this turn** — highest. If they say "just do X" / "skip the process," do exactly that.
13
+ 2. **`AGENTS.md`** — the project's own rules (whatever the project declares there).
14
+ 3. **Agentic Engineering defaults (below)** — lowest.
15
+
16
+ AE never blocks something you were explicitly asked to do. These are defaults, not laws.
17
+
18
+ ## Step 0 — Orient (only when needed)
19
+
20
+ Read `handoff.md` (latest session snapshot) and `spec/INDEX.md` (needs + current node) **only when you lack context** — at the start of a fresh session, or when you can't tell whether this request continues existing work or starts something new. If you already have that context from the conversation, skip straight to routing. Don't re-read them every turn.
21
+
22
+ ## Step 1 — Route: is this a *need*?
23
+
24
+ The one question: **does this request create or change a *need* — durable, product-facing behavior worth recording in `spec/`?**
25
+
26
+ **Does NOT enter the loop — just do it, no ceremony:**
27
+ - Questions / explanations ("what does this do?", "why is it slow?")
28
+ - Quick fixes, one-line changes, typos
29
+ - Throwaway / one-off scripts, spikes, experiments
30
+ - Chores: rename, format, dependency bump, run tests, git
31
+ - Anything the user explicitly asked to do directly
32
+
33
+ **Enters the loop:**
34
+ - A new feature or non-trivial capability → go to **A1**
35
+ - A bug / wrong behavior on an existing need → go to **B2**
36
+ - Continuing an existing need → resume at its **current node** (from `spec/INDEX.md`)
37
+
38
+ **Unsure?** Default to *not* entering: do what was asked, then add one line — "This looks like it might be a need; want me to capture it in `spec/` / align first?" — and hand the decision back to the user. Don't gate.
39
+
40
+ ## Step 2 — Dispatch (only when it enters the loop)
41
+
42
+ Hand off to the node skill below. Two hard gates are rigid:
43
+ - **A1 not aligned → do not write `prd.md`.**
44
+ - **B2 expected behavior not aligned → do not start fixing.**
45
+
46
+ | Node | Purpose | Skill |
47
+ |------|---------|-------|
48
+ | A1 | Align the requirement | `brainstorming` (+ `grill-me` for detail) |
49
+ | A2 | Write `prd.md` | `to-prd` |
50
+ | A3 | Write `design.md` | `writing-plans` |
51
+ | A4 | Write `todo.md` | `to-issues` |
52
+ | A5 | Implement (TDD) | `tdd` |
53
+ | A6 | Verify on the real path | `verification-before-completion` |
54
+ | B2 | Align expected behavior | `grill-me` |
55
+ | B3 | Find root cause | `diagnose` |
56
+ | B4 | Write the issue file | (7-section format) |
57
+ | B5 | Fix (TDD) | `tdd` |
58
+ | B7 | Review & sediment findings | `review` |
59
+
60
+ `karpathy-guidelines` is always-on whenever you write or change code (no node).
61
+
62
+ Spec file mechanics — INDEX derivation, frontmatter, state machine, R1 — live in `spec/AGENTS.md`.
@@ -135,8 +135,8 @@ This is non-negotiable.
135
135
  If verification passes:
136
136
 
137
137
  1. Update `spec/INDEX.md`:
138
- - Recompute `当前节点` per `spec-framework.md` INDEX rules - for a fresh need this becomes "B1 user acceptance" (the next node is user-driven, not skill-driven)
139
- - If unsure, run `/ae-index-rebuild`
138
+ - Recompute `当前节点` per `spec/AGENTS.md` INDEX rules - for a fresh need this becomes "B1 user acceptance" (the next node is user-driven, not skill-driven)
139
+ - If unsure, run `ae index-rebuild`
140
140
  2. Hand off to B1: tell the user the need is ready for their hands-on acceptance test. Do NOT mark anything `archived` - `archived` is reserved for needs that get superseded, not completed.
141
141
 
142
142
  If verification fails:
@@ -103,8 +103,8 @@ If you find issues, fix them inline. No need to re-review — just fix and move
103
103
 
104
104
  1. Update `spec/INDEX.md`:
105
105
  - Set the `design` column to `active` (or `draft` if key trade-offs still need user approval)
106
- - Recompute the `当前节点` column per the rules in `spec-framework.md` §INDEX 推导规则
107
- - If unsure, run `/ae-index-rebuild` for an idempotent rescan
106
+ - Recompute the `当前节点` column per the rules in `spec/AGENTS.md` §INDEX 推导规则
107
+ - If unsure, run `ae index-rebuild` for an idempotent rescan
108
108
  2. If you promoted any decision to `spec/ADR/`, also add a row under `## ADR` in `INDEX.md`.
109
109
  3. Hand off to the next S1 node: A4 `to-issues` will read this `design.md` and produce `spec/needs/<need-name>/todo.md`. Tell the user the design is ready and recommend invoking `to-issues` next.
110
110
 
package/src/cli.js CHANGED
@@ -5,9 +5,9 @@ import { packageRoot } from './utils/paths.js';
5
5
  const HELP = `Usage: ae <command> [options]
6
6
 
7
7
  Commands:
8
- setup Install skills to .claude/.codex and drop a config/ae-rules.md template.
9
- init [goal] Create spec/ skeleton, render entry files, sync AE:RULES block from
10
- config/ae-rules.md. Requires \`ae setup\` to have run.
8
+ setup Install skills to .claude/.codex.
9
+ init [goal] Create spec/ skeleton and render entry files.
10
+ Requires \`ae setup\` to have run.
11
11
 
12
12
  Options:
13
13
  -h, --help Show help
@@ -15,7 +15,6 @@ Options:
15
15
 
16
16
  Typical workflow:
17
17
  ae setup
18
- [optional] edit config/ae-rules.md
19
18
  ae init "<one-line project goal>"`;
20
19
 
21
20
  export async function run(argv = []) {
@@ -1,6 +1,6 @@
1
- import { mkdir, readFile, stat } from 'node:fs/promises';
1
+ import { mkdir, stat } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
- import { createDirectories, renderEntryFiles, syncRulesBlock, RulesMarkerError } from '../skeleton.js';
3
+ import { createDirectories, renderEntryFiles } from '../skeleton.js';
4
4
  import { templatesPath } from '../utils/paths.js';
5
5
  import { formatInitReport } from '../utils/report.js';
6
6
 
@@ -10,9 +10,7 @@ const HELP = `Usage: ae init [goal] [options]
10
10
 
11
11
  Options:
12
12
  --target <path> Initialize this project directory. Defaults to cwd.
13
- --rules <path> Read AE:RULES content from this markdown file.
14
- Defaults to <target>/config/ae-rules.md when present.
15
- --dry-run Show what would be created or synced without writing files.
13
+ --dry-run Show what would be created without writing files.
16
14
  -h, --help Show help`;
17
15
 
18
16
  export async function run(argv = []) {
@@ -51,16 +49,10 @@ export async function run(argv = []) {
51
49
  created.push(...entries.created);
52
50
  skipped.push(...entries.skipped);
53
51
 
54
- const rules = await syncRules(target, options);
55
-
56
- console.log(formatInitReport({ created, skipped, target, rules, dryRun: options.dryRun }));
52
+ console.log(formatInitReport({ created, skipped, target, dryRun: options.dryRun }));
57
53
  return 0;
58
54
  } catch (error) {
59
- if (error instanceof RulesMarkerError) {
60
- console.error(`AE init failed: ${error.message}`);
61
- } else {
62
- console.error(`AE init failed: ${error instanceof Error ? error.message : String(error)}`);
63
- }
55
+ console.error(`AE init failed: ${error instanceof Error ? error.message : String(error)}`);
64
56
  process.exitCode = 1;
65
57
  return 1;
66
58
  }
@@ -69,7 +61,6 @@ export async function run(argv = []) {
69
61
  function parseArgs(argv) {
70
62
  const options = {
71
63
  target: undefined,
72
- rules: undefined,
73
64
  goalParts: [],
74
65
  dryRun: false,
75
66
  help: false,
@@ -88,13 +79,6 @@ function parseArgs(argv) {
88
79
  }
89
80
  options.target = value;
90
81
  index += 1;
91
- } else if (arg === '--rules') {
92
- const value = argv[index + 1];
93
- if (!value) {
94
- throw new Error('--rules requires a path');
95
- }
96
- options.rules = value;
97
- index += 1;
98
82
  } else if (arg.startsWith('-')) {
99
83
  throw new Error(`Unknown option for init: ${arg}`);
100
84
  } else {
@@ -104,7 +88,6 @@ function parseArgs(argv) {
104
88
 
105
89
  return {
106
90
  target: options.target,
107
- rules: options.rules,
108
91
  dryRun: options.dryRun,
109
92
  help: options.help,
110
93
  goal: options.goalParts.length > 0 ? options.goalParts.join(' ') : undefined,
@@ -134,41 +117,6 @@ async function hasInstalledAssets(target) {
134
117
  );
135
118
  }
136
119
 
137
- async function syncRules(target, options) {
138
- const rulesPath = options.rules
139
- ? path.resolve(process.cwd(), options.rules)
140
- : path.join(target, 'config', 'ae-rules.md');
141
-
142
- const rulesInfo = await statMaybe(rulesPath);
143
- if (!rulesInfo) {
144
- if (options.rules) {
145
- throw new Error(`rules file does not exist: ${rulesPath}`);
146
- }
147
- return 'skipped (no rules file)';
148
- }
149
-
150
- if (rulesInfo.isDirectory()) {
151
- throw new Error(`expected a file, got directory: ${rulesPath}`);
152
- }
153
- if (!rulesInfo.isFile()) {
154
- throw new Error(`expected a file: ${rulesPath}`);
155
- }
156
-
157
- const rulesContent = await readFile(rulesPath, 'utf8');
158
- const agents = path.join(target, 'AGENTS.md');
159
- const claude = path.join(target, 'CLAUDE.md');
160
- const agentsExists = await exists(agents);
161
- const claudeExists = await exists(claude);
162
-
163
- if (options.dryRun && (!agentsExists || !claudeExists)) {
164
- return 'would sync';
165
- }
166
-
167
- await syncRulesBlock(agents, rulesContent, { dryRun: options.dryRun });
168
- await syncRulesBlock(claude, rulesContent, { dryRun: options.dryRun });
169
- return options.dryRun ? 'would sync' : 'synced';
170
- }
171
-
172
120
  async function statMaybe(value) {
173
121
  try {
174
122
  return await stat(value);
@@ -180,10 +128,6 @@ async function statMaybe(value) {
180
128
  }
181
129
  }
182
130
 
183
- async function exists(value) {
184
- return Boolean(await statMaybe(value));
185
- }
186
-
187
131
  async function isDirectory(value) {
188
132
  const current = await statMaybe(value);
189
133
  return Boolean(current?.isDirectory());
@@ -1,7 +1,7 @@
1
1
  import { mkdir, stat } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
- import { copyFileIdempotent, copyTreeIdempotent } from '../utils/copy.js';
4
- import { skillsPath, templatesPath } from '../utils/paths.js';
3
+ import { copyTreeIdempotent } from '../utils/copy.js';
4
+ import { skillsPath } from '../utils/paths.js';
5
5
  import { formatSetupReport } from '../utils/report.js';
6
6
 
7
7
  const HELP = `Usage: ae setup [options]
@@ -45,14 +45,6 @@ export async function run(argv = []) {
45
45
  skipped.push(...result.skipped.map((item) => toDisplayPath(path.join(group.prefix, item))));
46
46
  }
47
47
 
48
- const rulesResult = await copyFileIdempotent(
49
- templatesPath('ae-rules.md'),
50
- path.join(target, 'config', 'ae-rules.md'),
51
- { dryRun: options.dryRun },
52
- );
53
- created.push(...rulesResult.created.map((item) => toDisplayPath(path.join('config', item))));
54
- skipped.push(...rulesResult.skipped.map((item) => toDisplayPath(path.join('config', item))));
55
-
56
48
  console.log(formatSetupReport({ created, skipped, target, dryRun: options.dryRun }));
57
49
  return 0;
58
50
  } catch (error) {
package/src/skeleton.js CHANGED
@@ -1,9 +1,6 @@
1
1
  import { mkdir, readFile, stat, writeFile } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
 
4
- export const RULES_BEGIN = '<!-- AE:RULES:BEGIN -->';
5
- export const RULES_END = '<!-- AE:RULES:END -->';
6
- const RULES_COMMENT = '<!-- 由 ae init 从 config/ae-rules.md 或 --rules 指定文件同步,勿手改 -->';
7
4
  const DEFAULT_DRY_RUN = false;
8
5
 
9
6
  const SKELETON_DIRS = [
@@ -30,15 +27,12 @@ const ENTRY_FILES = [
30
27
  'handoff.md',
31
28
  path.join('spec', 'README.md'),
32
29
  path.join('spec', 'INDEX.md'),
30
+ path.join('spec', 'AGENTS.md'),
31
+ path.join('spec', 'CLAUDE.md'),
32
+ path.join('spec', 'ADR', 'AGENTS.md'),
33
+ path.join('spec', 'ADR', 'CLAUDE.md'),
33
34
  ];
34
35
 
35
- export class RulesMarkerError extends Error {
36
- constructor(message) {
37
- super(message);
38
- this.name = 'RulesMarkerError';
39
- }
40
- }
41
-
42
36
  export async function createDirectories(target, options = {}) {
43
37
  const dryRun = Boolean(options.dryRun ?? DEFAULT_DRY_RUN);
44
38
  const created = [];
@@ -112,82 +106,12 @@ export async function renderEntryFiles(target, templateRoot, options = {}) {
112
106
  return { created, skipped, updated };
113
107
  }
114
108
 
115
- export async function syncRulesBlock(targetFile, rulesContent, options = {}) {
116
- const dryRun = Boolean(options.dryRun ?? DEFAULT_DRY_RUN);
117
- const content = await readFile(targetFile, 'utf8');
118
- const ranges = findRulesRanges(content, targetFile);
119
- const block = buildRulesBlock(rulesContent);
120
- const created = [];
121
- const skipped = [];
122
- const updated = [];
123
- const display = path.basename(targetFile);
124
-
125
- if (ranges.length === 0) {
126
- const next = content.endsWith('\n') ? `${content}\n${block}` : `${content}\n\n${block}`;
127
- if (next === content) {
128
- skipped.push(display);
129
- return { created, skipped, updated };
130
- }
131
- created.push(`${display}#AE:RULES`);
132
- if (!dryRun) {
133
- await writeFile(targetFile, next);
134
- }
135
- return { created, skipped, updated };
136
- }
137
-
138
- const [{ start, end }] = ranges;
139
- const next = `${content.slice(0, start)}${block}${content.slice(end)}`;
140
-
141
- if (next === content) {
142
- skipped.push(`${display}#AE:RULES`);
143
- return { created, skipped, updated };
144
- }
145
-
146
- updated.push(`${display}#AE:RULES`);
147
- if (!dryRun) {
148
- await writeFile(targetFile, next);
149
- }
150
-
151
- return { created, skipped, updated };
152
- }
153
-
154
- export function buildRulesBlock(rulesContent) {
155
- const normalized = rulesContent.endsWith('\n') ? rulesContent : `${rulesContent}\n`;
156
- return `${RULES_BEGIN}\n${RULES_COMMENT}\n${normalized}${RULES_END}\n`;
157
- }
158
-
159
109
  function renderTemplate(template, replacements) {
160
110
  return template
161
111
  .replaceAll('{{PROJECT_NAME}}', replacements.projectName)
162
112
  .replaceAll('{{PROJECT_GOAL}}', replacements.projectGoal);
163
113
  }
164
114
 
165
- function findRulesRanges(content, targetFile) {
166
- const beginMatches = [...content.matchAll(new RegExp(escapeRegExp(RULES_BEGIN), 'g'))];
167
- const endMatches = [...content.matchAll(new RegExp(escapeRegExp(RULES_END), 'g'))];
168
-
169
- if (beginMatches.length !== endMatches.length || beginMatches.length > 1) {
170
- throw new RulesMarkerError(`malformed AE:RULES markers in ${targetFile}`);
171
- }
172
-
173
- if (beginMatches.length === 0) {
174
- return [];
175
- }
176
-
177
- const start = beginMatches[0].index;
178
- const end = endMatches[0].index + RULES_END.length;
179
- if (start > endMatches[0].index) {
180
- throw new RulesMarkerError(`malformed AE:RULES markers in ${targetFile}`);
181
- }
182
-
183
- let rangeEnd = end;
184
- if (content.slice(rangeEnd, rangeEnd + 1) === '\n') {
185
- rangeEnd += 1;
186
- }
187
-
188
- return [{ start, end: rangeEnd }];
189
- }
190
-
191
115
  async function exists(value) {
192
116
  try {
193
117
  await stat(value);
@@ -203,7 +127,3 @@ async function exists(value) {
203
127
  function normalizeRelative(value) {
204
128
  return value.split(path.sep).join('/');
205
129
  }
206
-
207
- function escapeRegExp(value) {
208
- return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
209
- }
@@ -5,17 +5,16 @@ export function formatSetupReport({ created, skipped, target, dryRun }) {
5
5
  `- ${installedLabel}: ${created.length} (${summarize(created)})`,
6
6
  `- Skipped: ${skipped.length} (${summarize(skipped)})`,
7
7
  `- Target: ${target}`,
8
- `- Next: edit config/ae-rules.md (optional), then run \`ae init "<goal>"\`.`,
8
+ `- Next: run \`ae init "<goal>"\`.`,
9
9
  ].join('\n');
10
10
  }
11
11
 
12
- export function formatInitReport({ created, skipped, target, rules, dryRun }) {
12
+ export function formatInitReport({ created, skipped, target, dryRun }) {
13
13
  const createdLabel = dryRun ? 'Would create' : 'Created';
14
14
  return [
15
15
  dryRun ? 'AE init dry run complete' : 'AE init complete',
16
16
  `- ${createdLabel}: ${created.length} (${summarize(created)})`,
17
17
  `- Skipped: ${skipped.length} (${summarize(skipped)})`,
18
- `- Rules: ${rules}`,
19
18
  `- Target: ${target}`,
20
19
  ].join('\n');
21
20
  }
@@ -1,21 +1,3 @@
1
- # Project Goal
1
+ # {{PROJECT_NAME}}
2
2
 
3
- {{PROJECT_GOAL}}
4
-
5
- ## R1 Progressive Loading
6
-
7
- Keep this file short because every agent session loads it. Do trivial work directly. For non-trivial product, architecture, implementation, or debug work, first load the relevant local guidance or skill, then proceed.
8
-
9
- ## Spec Landing Rules
10
-
11
- - SDD owns what to build; TDD owns how to prove it works.
12
- - After writing or changing anything under `spec/needs/<need-name>/`, update `spec/INDEX.md`.
13
- - If `spec/INDEX.md` cannot be updated confidently, run the future `index-rebuild` command or leave an explicit handoff note.
14
- - Do not write `prd.md` before requirement alignment.
15
- - Do not fix a bug before expected behavior is aligned.
16
-
17
- ## Project Specific Rules
18
-
19
- <!-- AE:PROJECT:BEGIN -->
20
- <!-- Add project-specific rules here. `ae init` manages AE:RULES separately. -->
21
- <!-- AE:PROJECT:END -->
3
+ > {{PROJECT_GOAL}}
@@ -1,21 +1,5 @@
1
- # Project Goal
1
+ # {{PROJECT_NAME}}
2
2
 
3
- {{PROJECT_GOAL}}
3
+ **Always read [AGENTS.md](./AGENTS.md) at the start of every session before doing any work.**
4
4
 
5
- ## R1 Progressive Loading
6
-
7
- Keep this file short because every agent session loads it. Do trivial work directly. For non-trivial product, architecture, implementation, or debug work, first load the relevant local guidance or skill, then proceed.
8
-
9
- ## Spec Landing Rules
10
-
11
- - SDD owns what to build; TDD owns how to prove it works.
12
- - After writing or changing anything under `spec/needs/<need-name>/`, update `spec/INDEX.md`.
13
- - If `spec/INDEX.md` cannot be updated confidently, run the future `index-rebuild` command or leave an explicit handoff note.
14
- - Do not write `prd.md` before requirement alignment.
15
- - Do not fix a bug before expected behavior is aligned.
16
-
17
- ## Project Specific Rules
18
-
19
- <!-- AE:PROJECT:BEGIN -->
20
- <!-- Add project-specific rules here. `ae init` manages AE:RULES separately. -->
21
- <!-- AE:PROJECT:END -->
5
+ This project's instructions, rules, structure, and operating guidelines are all defined in `AGENTS.md`.
@@ -1,18 +1,32 @@
1
1
  # {{PROJECT_NAME}}
2
2
 
3
- {{PROJECT_GOAL}}
3
+ > {{PROJECT_GOAL}}
4
4
 
5
- ## Setup
5
+ <!--
6
+ 根 README 的核心:让别人 30 秒搞清「为什么有用、能做什么、怎么用」。
7
+ 下面是建议骨架,按需增删、不必都填,也不必拘泥小节名:
8
+ - 它是什么 + 一句话价值 → 上面的标题 + 一行(已占位)
9
+ - 为什么 / 给谁 → 解决什么问题、面向谁
10
+ - Quick Start → 最快见效的一段命令 / 步骤(装好 + 第一个能见效的操作)
11
+ - 使用示例 → 典型场景(必要时再贴一段真实用法)
12
+ - 目录地图 / 文档入口 → 关键目录 + 深入文档的链接
13
+ -->
6
14
 
7
- TODO: 记录安装和启动方式。
15
+ ## 这是什么
8
16
 
9
- ## Usage
17
+ TODO: 一段话说清它解决什么问题、给谁用、用它能做什么。
10
18
 
11
- TODO: 记录常用操作。
19
+ ## Quick Start
12
20
 
13
- ## Project Map
21
+ TODO: 最快跑起来的命令或步骤。
14
22
 
15
- - `reference/`: 原始素材,只读心态。
16
- - `spec/`: SDD/TDD 规格产物。
17
- - `data/`: 运行产物、导出和缓存。
18
- - `scripts/`: 辅助脚本。
23
+ <!-- ## 使用示例 —— 有典型场景时再加,贴一段真实用法 -->
24
+
25
+ ## 目录地图
26
+
27
+ - `spec/`:SDD/TDD 规格产物——需求索引看 `spec/INDEX.md`,项目地图看 `spec/README.md`。
28
+ - `reference/`:原始素材,只读心态。
29
+ - `data/`:运行产物、导出、缓存。
30
+ - `scripts/`:辅助脚本。
31
+
32
+ <!-- 文档入口:AGENTS.md(项目指令)· handoff.md(当前态快照)· spec/INDEX.md(需求索引) -->
@@ -0,0 +1,30 @@
1
+ # spec/ADR/ 规则
2
+
3
+ > 架构决策记录(ADR)规则。在 `spec/ADR/` 下创建或修改 ADR 时遵守本文件。
4
+
5
+ ## 命名
6
+
7
+ `NNNN-<标题>.md`,**4 位序号**,kebab-case 标题。例:`0001-postgres-as-primary-store.md`。
8
+
9
+ ## frontmatter
10
+
11
+ ```yaml
12
+ ---
13
+ status: accepted # proposed | accepted | superseded
14
+ date: 2026-06-14
15
+ supersedes: 0000-xxx.md # 仅当取代旧 ADR 时填
16
+ ---
17
+ ```
18
+
19
+ 正文按具体决策自然组织(背景 / 决策 / 理由 / 影响),不强加重模板。
20
+
21
+ ## 状态机
22
+
23
+ ```text
24
+ proposed ─(评审接受)─► accepted ─(新 ADR 取代)─► superseded
25
+ ```
26
+
27
+ - `proposed`:新提案,未拍板(由 writing-plans / review / improve-codebase-architecture 创建时默认)。
28
+ - `accepted`:已评审接受;视为**约束**,其他需求不得违背。
29
+ - `superseded`:被新 ADR 取代;新 ADR 的 `supersedes` 指回旧编号,**不删旧文件**。
30
+
@@ -0,0 +1,5 @@
1
+ # spec/ADR/
2
+
3
+ **Always read [AGENTS.md](./AGENTS.md) in this directory before creating or editing an ADR.**
4
+
5
+ `spec/ADR/AGENTS.md` defines ADR naming, frontmatter, and the proposed/accepted/superseded state machine.
@@ -0,0 +1,35 @@
1
+ # spec/ 规则
2
+
3
+ > 本目录(`spec/`)的工作规则。在 `spec/` 下读写文件时遵守本文件。
4
+
5
+ ## 总领
6
+
7
+ S1 节点 → 产物 → skill 的路由总览,见随包的 `using-agentic-engineering` skill——它判定"进不进 AE 流程"并分发到各节点。
8
+
9
+ 两道硬门禁:**A1 未对齐不写 prd**;**B2 期望态未对齐不修复**。
10
+
11
+
12
+ ## R1:落盘后同步 INDEX
13
+ 落盘 `spec/needs/<需求名>/` 下任何文件后,**必须同步更新 `spec/INDEX.md`** 对应行。若不确定如何更新,按上面「INDEX 推导规则」手动重算(未来可用 `ae index-rebuild` 幂等重扫)。
14
+
15
+ ### INDEX 推导规则
16
+
17
+ `spec/INDEX.md` 给模型看:一次扫描看到所有需求 + 状态 + 进度。`当前节点` 列**不存储**在任何 frontmatter,由该需求下文件状态**实时推导**:
18
+
19
+ | 条件 | 当前节点 |
20
+ |------|---------|
21
+ | prd 不存在 或 status=draft | A1 / A2 |
22
+ | prd active + design 不存在/draft | A3 设计 |
23
+ | prd+design active + todo 不存在 | A4 拆解 |
24
+ | prd+design active + todo 有未完成项 | A5 执行 |
25
+ | todo 全勾 + 未端到端验证 | A6 verify |
26
+ | 所有 issues 已验收 + 已交付 | 已完成 |
27
+ | 存在 active 的 issues | 进 B 子路径,按 issues 状态推 B2…B7 |
28
+ | prd / design 任一 archived | 已归档 |
29
+
30
+ - INDEX 是**推导态**:文件状态变就重新推导,**不要手编 `当前节点` 列**。
31
+
32
+
33
+ ## 何时升 ADR
34
+
35
+ 决策影响**多个需求**或属项目级不变量时,从 `design.md` 升到`spec/ADR`(判断:推翻它会改动 >1 个需求)。单需求的技术决策留在该需求的 `design.md`。
@@ -0,0 +1,5 @@
1
+ # spec/
2
+
3
+ **Always read [AGENTS.md](./AGENTS.md) in this directory before working under `spec/`.**
4
+
5
+ `spec/AGENTS.md` defines the S1 node map, the INDEX derivation table, and the post-write INDEX sync rule (R1).
@@ -2,14 +2,27 @@
2
2
 
3
3
  ## 需求
4
4
 
5
+ <!--
6
+ 各列怎么填:
7
+ - 需求名:`spec/needs/<需求名>/` 的 kebab 目录名
8
+ - prd / design:对应文件 frontmatter 的 status(draft/active/archived);文件不存在填 -
9
+ - todo:todo.md 的 已勾数/总数(如 5/8,即拆解任务的完成进度);无 todo.md 填 -。这是 A5 内部子进度,不是节点位次(节点看「当前节点」列)
10
+ - issues:该需求 issues/ 下文件数 + 是否有未结(如 0 / 1 active);无则 -
11
+ - 当前节点:由文件状态推导得出,不手编(推导规则见 spec/AGENTS.md「INDEX 推导规则」)
12
+ -->
13
+
5
14
  | 需求名 | prd | design | todo | issues | 当前节点 |
6
15
  |--------|-----|--------|------|--------|----------|
7
16
 
8
17
  ## ADR
9
18
 
19
+ <!-- 编号 4 位 / 状态 proposed|accepted|superseded / 日期,均取自各 ADR frontmatter(详见 spec/ADR/AGENTS.md) -->
20
+
10
21
  | 编号 | 标题 | 状态 | 日期 |
11
22
  |------|------|------|------|
12
23
 
13
24
  ## 跨需求引用
14
25
 
26
+ <!-- 从各 prd/design frontmatter 的 related-needs 聚合 -->
27
+
15
28
  - 暂无
@@ -1,5 +1,7 @@
1
1
  # Spec Map
2
2
 
3
+ > 给人看:回忆"项目长什么样"。以 ASCII 图为主,可省细节、突出全貌。**README ≠ INDEX 镜像**——INDEX 给模型看进度,这里给人看全貌。
4
+
3
5
  ## Needs
4
6
 
5
7
  ```text
@@ -12,6 +14,8 @@ TODO: 用 ASCII 图画出需求地图。
12
14
  TODO: 用 ASCII 图画出核心业务流程。
13
15
  ```
14
16
 
17
+ > 全局架构总览画在这里(而非写进某个需求的 design.md)。
18
+
15
19
  ## Relationships
16
20
 
17
21
  ```text
@@ -1,17 +0,0 @@
1
- # Project-Specific Rules
2
-
3
- <!-- 这个文件在 `ae init` 时会被读取,内容会注入到 AGENTS.md 与 CLAUDE.md 的
4
- AE:RULES block 中。可以在 `ae setup` 之后、`ae init` 之前编辑。 -->
5
-
6
- ## 通用约束
7
-
8
- - 例如:所有代码注释使用中文
9
- - 例如:提交信息遵循 Conventional Commits
10
-
11
- ## 项目栈
12
-
13
- - 例如:Node.js 18+,TypeScript strict mode
14
-
15
- ## 协作偏好
16
-
17
- - 例如:小步提交,每个 commit 必须包含测试