@uoyo/mvtt 2.0.0-beta.3 → 2.0.0-beta.6
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 +299 -64
- package/README.zh-CN.md +419 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +27 -2
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/uninstall.d.ts.map +1 -1
- package/dist/commands/uninstall.js +19 -7
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +4 -2
- package/dist/commands/update.js.map +1 -1
- package/dist/fs/install-manifest.d.ts +4 -1
- package/dist/fs/install-manifest.d.ts.map +1 -1
- package/dist/fs/install-manifest.js +13 -1
- package/dist/fs/install-manifest.js.map +1 -1
- package/dist/fs/materialize.d.ts +2 -0
- package/dist/fs/materialize.d.ts.map +1 -1
- package/dist/fs/materialize.js +46 -13
- package/dist/fs/materialize.js.map +1 -1
- package/dist/fs/registry-merge.d.ts +19 -0
- package/dist/fs/registry-merge.d.ts.map +1 -0
- package/dist/fs/registry-merge.js +220 -0
- package/dist/fs/registry-merge.js.map +1 -0
- package/dist/scripts/epic-update.cjs +7670 -0
- package/dist/scripts/plan-update.cjs +7736 -0
- package/dist/scripts/session-update.cjs +84 -6
- package/dist/types/platform.d.ts +12 -0
- package/dist/types/platform.d.ts.map +1 -0
- package/dist/types/platform.js +24 -0
- package/dist/types/platform.js.map +1 -0
- package/dist/types/registry.d.ts +3 -24
- package/dist/types/registry.d.ts.map +1 -1
- package/install-manifest.yaml +10 -2
- package/package.json +1 -1
- package/registry.yaml +72 -198
- package/sources/defaults/config.yaml +8 -13
- package/sources/defaults/project-context.yaml +2 -5
- package/sources/defaults/session.yaml +14 -2
- package/sources/knowledge/core/manifest.yaml +1 -4
- package/sources/scripts/epic-update.js +512 -0
- package/sources/scripts/plan-update.js +614 -0
- package/sources/scripts/session-update.js +102 -2
- package/sources/sections/activation-load-config.md +1 -1
- package/sources/sections/activation-load-context.md +42 -13
- package/sources/sections/activation-preflight.md +1 -1
- package/sources/sections/footer-next-steps.md +3 -2
- package/sources/sections/output-format-constraint.md +14 -0
- package/sources/sections/project-context-profile.md +29 -0
- package/sources/sections/session-update.md +41 -1
- package/sources/skills/mvt-analyze/business.md +46 -8
- package/sources/skills/mvt-analyze/manifest.yaml +8 -1
- package/sources/skills/mvt-analyze-code/business.md +18 -17
- package/sources/skills/mvt-analyze-code/manifest.yaml +9 -6
- package/sources/skills/mvt-check-context/business.md +13 -6
- package/sources/skills/mvt-check-context/manifest.yaml +0 -5
- package/sources/skills/mvt-cleanup/business.md +17 -2
- package/sources/skills/mvt-cleanup/manifest.yaml +3 -0
- package/sources/skills/mvt-config/business.md +5 -5
- package/sources/skills/mvt-config/manifest.yaml +3 -6
- package/sources/skills/mvt-create-skill/business.md +2 -14
- package/sources/skills/mvt-create-skill/manifest.yaml +2 -4
- package/sources/skills/mvt-decompose/business.md +94 -0
- package/sources/skills/mvt-decompose/manifest.yaml +121 -0
- package/sources/skills/mvt-design/manifest.yaml +3 -0
- package/sources/skills/mvt-fix/business.md +21 -6
- package/sources/skills/mvt-fix/manifest.yaml +4 -1
- package/sources/skills/mvt-help/business.md +11 -9
- package/sources/skills/mvt-help/manifest.yaml +0 -5
- package/sources/skills/mvt-implement/business.md +57 -10
- package/sources/skills/mvt-implement/manifest.yaml +3 -0
- package/sources/skills/mvt-init/business.md +23 -13
- package/sources/skills/mvt-init/manifest.yaml +4 -2
- package/sources/skills/mvt-manage-context/business.md +41 -14
- package/sources/skills/mvt-manage-context/manifest.yaml +7 -5
- package/sources/skills/mvt-plan-dev/business.md +17 -9
- package/sources/skills/mvt-plan-dev/manifest.yaml +3 -0
- package/sources/skills/mvt-quick-dev/business.md +22 -7
- package/sources/skills/mvt-quick-dev/manifest.yaml +3 -1
- package/sources/skills/mvt-refactor/business.md +32 -17
- package/sources/skills/mvt-refactor/manifest.yaml +2 -4
- package/sources/skills/mvt-resume/business.md +32 -12
- package/sources/skills/mvt-resume/manifest.yaml +3 -3
- package/sources/skills/mvt-review/business.md +24 -9
- package/sources/skills/mvt-review/manifest.yaml +3 -0
- package/sources/skills/mvt-status/business.md +37 -9
- package/sources/skills/mvt-status/manifest.yaml +2 -2
- package/sources/skills/mvt-sync-context/business.md +77 -34
- package/sources/skills/mvt-sync-context/manifest.yaml +6 -0
- package/sources/skills/mvt-template/business.md +1 -1
- package/sources/skills/mvt-template/manifest.yaml +0 -5
- package/sources/skills/mvt-test/business.md +30 -15
- package/sources/skills/mvt-test/manifest.yaml +3 -0
- package/sources/skills/mvt-update-plan/business.md +64 -33
- package/sources/skills/mvt-update-plan/manifest.yaml +10 -7
- package/sources/templates/decompose-output/body.md +13 -0
- package/sources/templates/decompose-output/manifest.yaml +11 -0
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
## Execution Flow
|
|
2
2
|
|
|
3
|
-
### Step 1:
|
|
3
|
+
### Step 1: Per-Project Routing (4-Level Fallback Chain)
|
|
4
|
+
|
|
5
|
+
Before processing any change, determine which project(s) the sync targets. Use this 4-level fallback chain:
|
|
6
|
+
|
|
7
|
+
1. **`task.project` exists** (when syncing within a plan-driven context): route to that project for per-project technical knowledge lookups (project-context.md always uses the flat path). If the task has multiple projects, route to each independently.
|
|
8
|
+
2. **Artifact file paths match** a unique project's `source_paths` or `path` from `project-context.yaml`: route to that project.
|
|
9
|
+
3. **Current operation's file path reverse-lookup**: match the file path against `projects[].path` and `projects[].source_paths` -> route to that project.
|
|
10
|
+
4. **List candidate projects for user selection**: if none of the above resolved a unique project, list the project names and ask the user.
|
|
11
|
+
|
|
12
|
+
**Cross-project changes** (task spanning multiple projects): route to each project for per-project technical knowledge lookups. The merge target for `project-context.md` is always the single flat file; per-project knowledge (quadrant 3/4) is routed per project.
|
|
13
|
+
|
|
14
|
+
### Step 2: Identify Completed Changes
|
|
4
15
|
- **What**: produce a candidate list of change-ids whose artifacts will be aggregated.
|
|
5
16
|
- **How**:
|
|
6
|
-
1. Read
|
|
7
|
-
2. For each candidate, verify `.ai-agents/workspace/artifacts/{change-id}/` exists AND contains at least one of `analysis.md` or `
|
|
8
|
-
3. (Fallback) If `changes[]` is empty, scan `.ai-agents/workspace/artifacts/*/` directly; offer those with `analysis.md` or `
|
|
17
|
+
1. Read `.ai-agents/workspace/session.yaml`. Collect `changes[]` entries with `status: done`.
|
|
18
|
+
2. For each candidate, verify `.ai-agents/workspace/artifacts/{change-id}/` exists AND contains at least one of `analysis.md` or `implementation.md`. Drop entries with only `plan.yaml`, or with only `design.md` (design artifacts are not aggregated -- see Step 3).
|
|
19
|
+
3. (Fallback) If `changes[]` is empty, scan `.ai-agents/workspace/artifacts/*/` directly; offer those with `analysis.md` or `implementation.md`, marked `unindexed`.
|
|
9
20
|
4. Exclude already-archived or irrelevant changes:
|
|
10
21
|
- **Indexed changes**: exclude any `changes[]` entry with `status: abandoned`. For `status: done` entries, Step 1.2's directory existence check already filters out those whose artifacts have been moved to `artifacts/_archived/` by `/mvt-cleanup`.
|
|
11
22
|
- **Fallback scan**: when scanning `artifacts/*/` directly, skip any path under `artifacts/_archived/` (the unified archive directory managed by `/mvt-cleanup`).
|
|
@@ -23,66 +34,95 @@
|
|
|
23
34
|
|
|
24
35
|
- Cancel / empty selection -> stop with "no changes applied".
|
|
25
36
|
|
|
26
|
-
### Step
|
|
37
|
+
### Step 3: Read Current Project Context (Adaptive Structure Discovery)
|
|
27
38
|
|
|
28
39
|
This step establishes the **target structure** that aggregated content must fit into. The structure is NOT assumed -- it is derived from the current document.
|
|
29
40
|
|
|
30
|
-
1. Read `.ai-agents/knowledge/project/_generated/project-context.md
|
|
31
|
-
-
|
|
41
|
+
1. Read the project-context file: always read `.ai-agents/knowledge/project/_generated/project-context.md` (flat path, regardless of project count).
|
|
42
|
+
- **Multi-project**: the file contains `# Project: {name}` sections; use the routing result from Step 1 to identify which project section(s) are relevant for the current sync operation.
|
|
43
|
+
- If the file does not exist, STOP and recommend `/mvt-analyze-code`.
|
|
32
44
|
2. Parse the current `.md` into a section map:
|
|
33
45
|
- Each top-level `##` heading -> one section anchor.
|
|
34
46
|
- Record: section title (verbatim), byte range, and a 1-line semantic summary derived from the section's content (e.g., "lists domain terms with definitions" or "describes module dependencies").
|
|
35
|
-
- The summary is what enables matching in Step
|
|
47
|
+
- The summary is what enables matching in Step 5 -- section titles may be in any language and may not match conventional names (Terms / Modules / etc.).
|
|
36
48
|
3. If the document has zero `##` sections (single block) -> STOP. Recommend `/mvt-analyze-code` to establish a sectioned baseline first.
|
|
37
|
-
4. Read `.ai-agents/workspace/project-context.yaml`. Record current `projects[].source_paths`, `modules`, and `tech_stack` for diff comparison in Step
|
|
49
|
+
4. Read `.ai-agents/workspace/project-context.yaml`. Record current `projects[].source_paths`, `modules`, and `tech_stack` for diff comparison in Step 5d.
|
|
38
50
|
|
|
39
|
-
### Step
|
|
51
|
+
### Step 4: Extract Artifact Content
|
|
40
52
|
|
|
41
|
-
- **What**: from each selected change-id, extract atomic knowledge items
|
|
53
|
+
- **What**: from each selected change-id, extract atomic knowledge items (do not classify yet).
|
|
42
54
|
- **How**:
|
|
43
|
-
1. For each selected change-id, read available artifacts (`analysis.md`, `implementation.md`).
|
|
55
|
+
1. For each selected change-id, read available artifacts (`analysis.md`, `implementation.md`). Do NOT read `design.md` -- design artifacts are not aggregated by this skill.
|
|
44
56
|
2. Extract atomic items. Typical sources:
|
|
45
57
|
- `analysis.md` -> domain terms, actors, business rules, constraints
|
|
46
58
|
- `implementation.md` -> files added/changed (informs `.yaml` source_paths), realized vs deviated design points
|
|
47
|
-
|
|
59
|
+
|
|
60
|
+
### Step 5: Normalize Extracted Content
|
|
61
|
+
|
|
62
|
+
Before classifying extracted items against the section map, normalize each item per the **Document Profile: project-context.md** section loaded above. This step strips intra-artifact cross-references -- meaningful in their source document but noise in project-context.md -- before they enter the merge pipeline.
|
|
63
|
+
|
|
64
|
+
1. For each extracted item, apply the normalization rules below (the governing principle lives in the Document Profile; this table lists concrete patterns, non-exhaustive):
|
|
65
|
+
|
|
66
|
+
| Pattern | Example | Normalization |
|
|
67
|
+
|---------|---------|---------------|
|
|
68
|
+
| ADR reference with section number | `(ADR-06, §12.4)` | Remove the reference; keep the substantive content it annotates |
|
|
69
|
+
| Bare ADR reference | `per ADR-06`, `(ADR-06)` | Remove entirely |
|
|
70
|
+
| Section number reference | `§12.4`, `§3.2.1` | Remove entirely |
|
|
71
|
+
| Design rule label prefix | `B-1:`, `D-7:`, `C-3:` | Remove the prefix; keep the rule text |
|
|
72
|
+
| Parenthesized design label | `(D-7)`, `(B-4)` | Remove entirely |
|
|
73
|
+
| Cross-artifact link phrase | `see §X`, `refer to ADR-N` | Remove the link phrase |
|
|
74
|
+
| Other reference pointing outside project-context.md | Any pattern not listed above | Apply the governing principle: if understanding requires an external document, strip the reference marker |
|
|
75
|
+
|
|
76
|
+
**Critical**: strip only the *reference marker*, never the *substantive content* it annotates.
|
|
77
|
+
|
|
78
|
+
2. After normalization, re-evaluate each item:
|
|
79
|
+
- Still contains substantive content -> keep for classification in Step 5.
|
|
80
|
+
- Was entirely a cross-reference with no independent semantic value -> drop it (it is a pointer, not knowledge).
|
|
81
|
+
3. Any normalization that removes content from a `modify` item (where the item modifies an existing entry) must be flagged in the update plan (Step 6, Table 6b) so the user can verify the substantive meaning was preserved.
|
|
82
|
+
|
|
83
|
+
### Step 6: Classify Artifact Content
|
|
84
|
+
|
|
85
|
+
- **What**: classify each normalized item against the section map from Step 2.
|
|
86
|
+
- **How**:
|
|
87
|
+
1. For each item, match to a section from the Step 2 map:
|
|
48
88
|
- Match by semantic similarity to **section title + 1-line summary**, not by exact string.
|
|
49
89
|
- Confidence levels:
|
|
50
90
|
- **mapped**: exactly one section matches with high confidence
|
|
51
91
|
- **ambiguous**: 2+ sections plausibly match
|
|
52
92
|
- **orphan**: no section matches; propose a new section name
|
|
53
|
-
|
|
93
|
+
2. For each item, also detect change type relative to current section content:
|
|
54
94
|
- `new` -- target section does not contain this entity
|
|
55
95
|
- `modify` -- target section mentions the entity but artifact provides a different value
|
|
56
96
|
- `redundant` -- already present, no change (will be filtered out, not shown to user)
|
|
57
97
|
|
|
58
|
-
### Step
|
|
98
|
+
### Step 7: Render the Update Plan (Four Tables)
|
|
59
99
|
|
|
60
|
-
####
|
|
100
|
+
#### 6a. Section-mapped items
|
|
61
101
|
| # | change-id | item | type | target section | classification |
|
|
62
102
|
|---|-----------|------|------|----------------|----------------|
|
|
63
103
|
|
|
64
|
-
####
|
|
104
|
+
#### 6b. Conflicts requiring resolution (every `modify` item)
|
|
65
105
|
| # | item | section | current value | proposed value (from {change-id}) |
|
|
66
106
|
|---|------|---------|---------------|-----------------------------------|
|
|
67
107
|
|
|
68
|
-
####
|
|
108
|
+
#### 6c. Ambiguous and orphan items
|
|
69
109
|
| # | item | reason | candidate sections (or proposed new section) |
|
|
70
110
|
|---|------|--------|----------------------------------------------|
|
|
71
111
|
|
|
72
|
-
####
|
|
112
|
+
#### 6d. Implied yaml changes
|
|
73
113
|
| # | yaml field | current | proposed |
|
|
74
114
|
|---|------------|---------|----------|
|
|
75
115
|
|
|
76
|
-
### Step
|
|
116
|
+
### Step 8: User Confirmation (Per-Table)
|
|
77
117
|
|
|
78
|
-
- **
|
|
79
|
-
- **
|
|
80
|
-
- **
|
|
81
|
-
- **
|
|
118
|
+
- **6a**: default = accept all. User input: indices to drop, or `e <n>` to edit a single item's target section.
|
|
119
|
+
- **6b**: **explicit per-row decision required**. Format `<index>:<keep|replace|edit>`. Example: `1:replace,2:keep,3:edit`. No default.
|
|
120
|
+
- **6c**: per row, user picks an existing section, types a new section name, or `skip`.
|
|
121
|
+
- **6d**: default = accept; user can drop indices.
|
|
82
122
|
|
|
83
123
|
Then ask: **"Run optional read-only code verification before applying? (y/n)"**
|
|
84
124
|
|
|
85
|
-
### Step
|
|
125
|
+
### Step 9: (Optional) Read-only Code Verification
|
|
86
126
|
|
|
87
127
|
This step catches artifacts claiming entities never actually delivered. It is **read-only** -- it never writes anything to `.md` or `.yaml`.
|
|
88
128
|
|
|
@@ -101,9 +141,9 @@ If user opts in:
|
|
|
101
141
|
|
|
102
142
|
3. Re-render the apply list with `verified` / `unverified` markers; final confirmation.
|
|
103
143
|
|
|
104
|
-
If user skips verification: proceed directly to Step
|
|
144
|
+
If user skips verification: proceed directly to Step 10 with Step 7 selections.
|
|
105
145
|
|
|
106
|
-
### Step
|
|
146
|
+
### Step 10: Apply Updates (Merge Mode)
|
|
107
147
|
|
|
108
148
|
- **Pre-write**:
|
|
109
149
|
1. Backup: `project-context.md` -> `project-context.md.bak`; `project-context.yaml` -> `project-context.yaml.bak`. Overwrite any prior `.bak`.
|
|
@@ -114,15 +154,17 @@ If user skips verification: proceed directly to Step 7 with Step 5 selections.
|
|
|
114
154
|
2. Each `modify` item with `replace`: replace the matching line in place. Smallest possible diff.
|
|
115
155
|
3. Each `orphan` item with new-section choice: append a new `##` section at end of file.
|
|
116
156
|
4. **Never delete** any existing line. **Never reorder** existing sections.
|
|
157
|
+
5. **Multi-project files**: use `# Project: {name}` headings to scope merges to the correct project section. New items for project X go into its `# Project: X` section; do not mix cross-project content.
|
|
158
|
+
6. All merged content must already be normalized per Step 4 rules. Do not re-introduce stripped references during inline replacement or append operations.
|
|
117
159
|
|
|
118
160
|
- **Update `project-context.yaml`** (structured merge):
|
|
119
|
-
1. Apply accepted entries from Table
|
|
161
|
+
1. Apply accepted entries from Table 6d.
|
|
120
162
|
2. Add new `source_paths` to matching project entry; add new modules to `modules[]`.
|
|
121
163
|
3. **Never delete** an existing yaml entry in this skill.
|
|
122
164
|
|
|
123
165
|
- **Atomicity**: temp + rename per file. If `.md` write succeeds but `.yaml` fails (or vice versa) -> restore the failed one from `.bak`, keep the other; report partial success.
|
|
124
166
|
|
|
125
|
-
### Step
|
|
167
|
+
### Step 11: Report
|
|
126
168
|
|
|
127
169
|
1. **Applied summary** -- counts: items added / modified / skipped / orphaned-into-new-section
|
|
128
170
|
2. **Files changed** -- paths + byte deltas
|
|
@@ -136,9 +178,10 @@ If user skips verification: proceed directly to Step 7 with Step 5 selections.
|
|
|
136
178
|
- Aggregated >= 1 change -> "Run `/mvt-cleanup` to archive these completed changes."
|
|
137
179
|
- Verification flagged code-only entities -> "Run `/mvt-analyze-code` to capture missing entities."
|
|
138
180
|
|
|
139
|
-
### Step
|
|
181
|
+
### Step 12: State Update
|
|
140
182
|
Apply the State Update rules defined in the **State Update** section below.
|
|
141
183
|
- The `--set-synced` parameter updates `session.last_synced_at`.
|
|
184
|
+
- Pass `--projects` to plan-update.cjs when updating a plan that has project attribution.
|
|
142
185
|
|
|
143
186
|
## Edge Cases & Errors
|
|
144
187
|
|
|
@@ -149,7 +192,7 @@ Apply the State Update rules defined in the **State Update** section below.
|
|
|
149
192
|
| Selected change-id has only `plan.yaml` | Filtered in Step 1; will not appear |
|
|
150
193
|
| `modify` with `replace` but the existing line cannot be located deterministically | Fall back to append + flag as duplicate-needs-manual-edit; do NOT silently overwrite the wrong line |
|
|
151
194
|
| `.md.bak` already exists | Overwrite (only the most recent backup matters) |
|
|
152
|
-
| User aborts at Step
|
|
153
|
-
| Step
|
|
154
|
-
| Two artifacts contradict each other (
|
|
155
|
-
| change-id was archived between Step 1 and Step
|
|
195
|
+
| User aborts at Step 7 | Do not write; report "no changes applied" |
|
|
196
|
+
| Step 8 verification finds zero matches for everything | Strong warning; require explicit confirm before proceeding (artifacts likely describe planned, not delivered, work) |
|
|
197
|
+
| Two artifacts contradict each other (analysis claims rule X, implementation realizes rule Y) | Surface in Table 6b as cross-artifact conflict; user picks |
|
|
198
|
+
| change-id was archived between Step 1 and Step 9 | Skip with note; do not error the run |
|
|
@@ -60,6 +60,9 @@ sections:
|
|
|
60
60
|
- type: shared
|
|
61
61
|
source: sections/output-language-constraint.md
|
|
62
62
|
|
|
63
|
+
- type: shared
|
|
64
|
+
source: sections/output-format-constraint.md
|
|
65
|
+
|
|
63
66
|
- type: shared
|
|
64
67
|
source: sections/activation-preflight.md
|
|
65
68
|
params:
|
|
@@ -73,6 +76,9 @@ sections:
|
|
|
73
76
|
level: "BLOCK"
|
|
74
77
|
message: "project-context.md not found. Run `/mvt-analyze-code` to create the initial document; this skill only handles incremental updates."
|
|
75
78
|
|
|
79
|
+
- type: shared
|
|
80
|
+
source: sections/project-context-profile.md
|
|
81
|
+
|
|
76
82
|
- type: file
|
|
77
83
|
source: ./business.md
|
|
78
84
|
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
|------|----------|
|
|
89
89
|
| User selects a `#` that doesn't exist in inventory | Re-display the table, ask again |
|
|
90
90
|
| `customize` validation fails repeatedly | After two failed attempts, suggest user export to a file and edit manually, then re-import via `customize` with `free-form patch` |
|
|
91
|
-
| Custom file exists but registry no longer references the template (`Orphan-custom`) | Allow `view` and `reset`; refuse `customize` (stale target); recommend running `/mvt-init
|
|
91
|
+
| Custom file exists but registry no longer references the template (`Orphan-custom`) | Allow `view` and `reset`; refuse `customize` (stale target); recommend running `/mvt-init` (interactive refresh) or removing the file manually |
|
|
92
92
|
| Default file is missing (`Missing`) | Refuse all actions for that row; suggest reinstall (`mvtt install`) |
|
|
93
93
|
| User aborts at any confirmation prompt | Do not modify any file; report "no changes" |
|
|
94
94
|
| External process modified the file between preview and write | Detect via mtime check just before write; abort and re-run preview |
|
|
@@ -22,7 +22,22 @@
|
|
|
22
22
|
|
|
23
23
|
- For each target file, locate or plan its corresponding test file path using the project's test layout convention (mirror under `tests/`, sibling `*.test.ts`, etc.).
|
|
24
24
|
|
|
25
|
-
### Step 3: Identify
|
|
25
|
+
### Step 3: Identify Project Scope and Load Project-Specific Knowledge
|
|
26
|
+
|
|
27
|
+
This step applies only when the workspace has multiple projects (`projects.length > 1` in `project-context.yaml`). In single-project workspaces, all relevant knowledge was loaded at activation; skip this step entirely.
|
|
28
|
+
|
|
29
|
+
- **Project identification**: match the file paths resolved in Step 2 against `projects[].path` and `projects[].source_paths`:
|
|
30
|
+
- A file whose path starts with a project's `path` prefix belongs to that project.
|
|
31
|
+
- A file under a project's `source_paths` entry also belongs to that project.
|
|
32
|
+
- Collect the set of unique project names from all matched files. This is the **active project scope** for this invocation.
|
|
33
|
+
- **On-demand knowledge loading**: for each project P in the active project scope, read `.ai-agents/registry.yaml` and load:
|
|
34
|
+
1. Every entry under `knowledge.{P}` -- load each entry's referenced files (resolve relative to `.ai-agents/{source}`).
|
|
35
|
+
2. Every entry under `skills.mvt-test.knowledge.{P}` -- load each entry's referenced files.
|
|
36
|
+
3. Skip any key absent from the registry (no project-specific knowledge is valid; do not warn).
|
|
37
|
+
- **Multi-project scenario**: if files span multiple projects, load each project's knowledge sequentially. The skill operates with the union of all loaded project-specific knowledge plus the `_all` knowledge already loaded at activation.
|
|
38
|
+
- **Unmatched files**: if a file path does not match any project's `path` or `source_paths`, surface a note and treat it as belonging to the first project in `projects[]` (fallback). This may indicate a configuration gap in `project-context.yaml`.
|
|
39
|
+
|
|
40
|
+
### Step 4: Identify Test Scenarios
|
|
26
41
|
- **What**: produce a Scenario Table covering happy path, edge, negative, and security cases.
|
|
27
42
|
- **How**:
|
|
28
43
|
1. For each public function / endpoint in scope, list at least: 1 happy path, 1 boundary, 1 invalid input.
|
|
@@ -33,7 +48,7 @@
|
|
|
33
48
|
- Security -> include only when requirements mention auth, data sensitivity, or external input boundaries.
|
|
34
49
|
- Performance -> include only when requirements explicitly state SLAs.
|
|
35
50
|
|
|
36
|
-
### Step
|
|
51
|
+
### Step 5: Choose Test Granularity
|
|
37
52
|
- **What**: assign each scenario to unit / integration / E2E.
|
|
38
53
|
- **How**: use the rule below; one scenario maps to one granularity.
|
|
39
54
|
|
|
@@ -46,49 +61,49 @@
|
|
|
46
61
|
- A single scenario should not be tested at multiple granularities unless explicitly required (avoid wasteful duplication).
|
|
47
62
|
- Flag scenarios that need integration but the project lacks an integration test setup -> note in artifact, suggest setup, do not invent a fixture.
|
|
48
63
|
|
|
49
|
-
### Step
|
|
64
|
+
### Step 6: Design Test Cases
|
|
50
65
|
- **What**: turn each scenario into a concrete test case row.
|
|
51
66
|
- **How**: each row must include `id | scenario | granularity | preconditions | inputs | actions | expected | rule-traced-to`.
|
|
52
67
|
- Prioritize: every business rule trace must be present; happy paths first, then edges, then negatives, then security/performance.
|
|
53
68
|
- For external dependencies, decide mock/stub/fake per project conventions; document the choice.
|
|
54
69
|
|
|
55
|
-
### Step
|
|
70
|
+
### Step 7: Write Test Code
|
|
56
71
|
- **What**: emit test files using project conventions.
|
|
57
72
|
- **How**:
|
|
58
73
|
1. Match the project's existing test framework, file layout, and naming.
|
|
59
74
|
2. Test names describe the scenario in business language ("rejects login when password is expired"), not the function name.
|
|
60
75
|
3. Each test follows arrange / act / assert structure with no hidden setup.
|
|
61
|
-
4. Use mocks/stubs only at boundaries identified in Step
|
|
62
|
-
5. Do not modify the production code being tested -- if implementation has a bug, surface it (Step
|
|
76
|
+
4. Use mocks/stubs only at boundaries identified in Step 5; do NOT mock the unit under test.
|
|
77
|
+
5. Do not modify the production code being tested -- if implementation has a bug, surface it (Step 9) and recommend `/mvt-fix`.
|
|
63
78
|
6. Avoid `skip` / `only` / commented-out tests in the final output.
|
|
64
79
|
|
|
65
|
-
### Step
|
|
80
|
+
### Step 8: Coverage Analysis (only when `--coverage` flag set)
|
|
66
81
|
- **What**: produce a coverage map and gap list.
|
|
67
82
|
- **How**:
|
|
68
|
-
1. Map each test case (Step
|
|
83
|
+
1. Map each test case (Step 6) back to: a target file/function, and (if available) a business rule from `project-context.md`.
|
|
69
84
|
2. Identify gaps: target functions with no test, business rules with no test, error paths from `design.md` with no test.
|
|
70
85
|
3. Read coverage thresholds from `.ai-agents/config.yaml` if present; otherwise default targets: line >= 80%, branch >= 70%, business-rule == 100%.
|
|
71
86
|
4. Recommend additional test cases for each gap; do not auto-generate them in this run unless user confirms.
|
|
72
87
|
|
|
73
|
-
### Step
|
|
88
|
+
### Step 9: Surface Implementation Issues (if any)
|
|
74
89
|
- During scenario design or test writing you may discover the implementation is wrong (failing test reveals a real bug, not a test bug).
|
|
75
90
|
- **Do not** modify production code from this skill.
|
|
76
91
|
- Record each finding with: scenario id, expected vs observed, severity (Critical / Warning), and recommend `/mvt-fix`.
|
|
77
92
|
|
|
78
|
-
### Step
|
|
93
|
+
### Step 10: Write Artifact
|
|
79
94
|
- **Path and template**: as defined in the **Artifact Structure** section below.
|
|
80
95
|
- **Required content** (mapped to template headings):
|
|
81
96
|
- `Scope` -- target files, fallbacks applied.
|
|
82
97
|
- `Test Framework & Layout` -- chosen framework, file layout convention.
|
|
83
|
-
- `Test Scenarios` -- the Scenario Table from Step
|
|
84
|
-
- `Test Cases` -- the row-level table from Step
|
|
85
|
-
- `Granularity Decisions` -- summary from Step
|
|
98
|
+
- `Test Scenarios` -- the Scenario Table from Step 4.
|
|
99
|
+
- `Test Cases` -- the row-level table from Step 6.
|
|
100
|
+
- `Granularity Decisions` -- summary from Step 5, including any "needs setup" gaps.
|
|
86
101
|
- `Coverage Analysis` -- only when `--coverage`; otherwise omit the heading.
|
|
87
|
-
- `Implementation Issues Found` -- from Step
|
|
102
|
+
- `Implementation Issues Found` -- from Step 9; empty list is fine.
|
|
88
103
|
- `Suggested Run Commands` -- one or two commands the user can copy-paste.
|
|
89
104
|
- The actual test files go to the project tree; the artifact is a record.
|
|
90
105
|
|
|
91
|
-
### Step
|
|
106
|
+
### Step 11: State Update
|
|
92
107
|
Apply the State Update rules defined in the **State Update** section below.
|
|
93
108
|
|
|
94
109
|
## Edge Cases & Errors
|
|
@@ -14,8 +14,8 @@ Resolution rules:
|
|
|
14
14
|
- If `task_id` is omitted AND exactly one task currently has status `in_progress` -> default to that task.
|
|
15
15
|
- If `task_id` is omitted AND zero or multiple tasks are in_progress -> ask the user to specify.
|
|
16
16
|
- If the user reply is the natural-language form `done` / `blocked: <reason>` (from a workflow skill's soft-prompt) -> map to:
|
|
17
|
-
- `done` -> task = plan.
|
|
18
|
-
- `blocked: <reason>` -> task = plan.
|
|
17
|
+
- `done` -> task = the entry in `plan.current_tasks` matching the current project (or the sole entry if single-project), new_status = done
|
|
18
|
+
- `blocked: <reason>` -> task = the entry in `plan.current_tasks` matching the current project (or the sole entry if single-project), new_status = blocked, notes = `<reason>`
|
|
19
19
|
|
|
20
20
|
### Step 2: Load and Validate Existing Plan
|
|
21
21
|
|
|
@@ -23,54 +23,85 @@ Resolution rules:
|
|
|
23
23
|
2. Parse YAML; if parse fails or schema is invalid -> stop and report. Do not attempt to repair silently.
|
|
24
24
|
3. Verify the target `task_id` exists in `tasks[]`. If not, list valid ids and stop.
|
|
25
25
|
|
|
26
|
-
### Step 3: Apply the Update
|
|
26
|
+
### Step 3: Apply the Update, Recompute, Validate, and Write (via script)
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
The mechanical work — mutating the task, recomputing `current_tasks` via the per-project DAG
|
|
29
|
+
rules, validating the result, and writing back atomically — is performed by a
|
|
30
|
+
deterministic script. Do NOT hand-edit `plan.yaml` or reason through the
|
|
31
|
+
`current_tasks` selection yourself; call the script with the resolved arguments
|
|
32
|
+
from Step 1–2:
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
4. If `notes` provided -> overwrite `tasks[i].notes`.
|
|
34
|
-
5. Update `plan.updated_at` to current ISO 8601 timestamp.
|
|
34
|
+
```bash
|
|
35
|
+
node .ai-agents/scripts/plan-update.cjs --plan "<active_change.plan_path>" --task <task_id> --status <new_status> --projects "<comma,separated,project,names>" [--artifacts "<comma,separated,paths>"] [--notes "<note text>"]
|
|
36
|
+
```
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
Include `--artifacts` only if artifacts were provided, and `--notes` only if a note was provided; omit each flag otherwise.
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
| Argument | Value source |
|
|
41
|
+
|----------|-------------|
|
|
42
|
+
| `--plan` | `active_change.plan_path` resolved from session.yaml |
|
|
43
|
+
| `--task` | the `task_id` resolved in Step 1 |
|
|
44
|
+
| `--status` | the `new_status` resolved in Step 1 (`pending`/`in_progress`/`done`/`blocked`/`skipped`) |
|
|
45
|
+
| `--projects` | comma-separated project names read from `project-context.yaml > projects[].name` |
|
|
46
|
+
| `--artifacts` | optional; comma-separated paths to append (the script de-duplicates) |
|
|
47
|
+
| `--notes` | optional; overwrites the task's `notes` |
|
|
39
48
|
|
|
40
|
-
|
|
41
|
-
2. Otherwise pick the first task (by array order) where:
|
|
42
|
-
- `status == pending`
|
|
43
|
-
- All ids in `depends_on` reference tasks with status `done`
|
|
44
|
-
3. If no such task exists AND every task is `done` -> set `plan.status = done`, `current_task = null`.
|
|
45
|
-
4. If no such task exists but some tasks are still `pending` (because their dependencies are not done -- e.g., everything reachable is blocked) -> set `current_task = null`, leave `plan.status = in_progress`. Surface a warning in the output ("All remaining tasks are blocked by dependencies; resolve a blocker before continuing").
|
|
49
|
+
The script performs, deterministically:
|
|
46
50
|
|
|
47
|
-
|
|
51
|
+
1. **Apply**: sets the task status; appends + de-duplicates `--artifacts` (handles `artifacts: null`); overwrites `--notes`; sets `completed_at` to now when status is `done`, else `null`; refreshes `plan.updated_at`.
|
|
52
|
+
2. **Recompute `current_tasks`** (per-project independent advancement): for each project, finds the `in_progress` task or advances the first `pending` task whose `depends_on` are all in `resolvedIds` (done + skipped; blocked does NOT satisfy). Detects `project_switch` when advancement crosses a project boundary. Plan done -> `current_tasks = {}`.
|
|
53
|
+
3. **Validate** the mutated plan (unique ids, valid `depends_on` references, DAG/no-cycle per project, one `in_progress` per project, every task has acceptance, `completed_at` consistency, `current_tasks` validity, project naming constraint, task project membership).
|
|
54
|
+
4. **Write atomically** (temp + rename) only if validation passes.
|
|
48
55
|
|
|
49
|
-
|
|
56
|
+
**Interpreting the result:**
|
|
50
57
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
58
|
+
- **Exit 0**: success. stdout is a single-line JSON object:
|
|
59
|
+
```json
|
|
60
|
+
{"ok":true,"task":{"id":"t1","title":"...","old_status":"in_progress","new_status":"done"},"current_tasks":{"default":"t2"},"plan_status":"in_progress","progress":{"done":1,"total":4},"warning":null,"project_switch":null}
|
|
61
|
+
```
|
|
62
|
+
Use these fields directly to render the Output Format block. The file is already written — do NOT read it back to verify. If `warning` is non-null, surface it. If `project_switch` is non-null, note the project boundary crossing.
|
|
63
|
+
- **Exit 1**: failure. stderr carries the error (invalid status, task not found, validation failure, parse/write error). The file was **not** modified. Report the error to the user and do not fabricate a success summary.
|
|
54
64
|
|
|
55
|
-
### Step
|
|
56
|
-
|
|
57
|
-
Apply the State Update rules defined in the **State Update** section below, AND the update-plan-specific updates:
|
|
58
|
-
|
|
59
|
-
- Refresh the matching entry in `changes[]`: `updated_at` -> current ISO 8601 timestamp.
|
|
60
|
-
- Do NOT touch `active_change.plan_path`.
|
|
61
|
-
|
|
62
|
-
### Step 7: Output
|
|
65
|
+
### Step 4: Output
|
|
63
66
|
|
|
64
67
|
Emit the Plan Update summary block defined in the Output Format section. Include:
|
|
65
68
|
|
|
66
69
|
- The task that changed (id, title, old -> new status).
|
|
67
70
|
- A compact table of all tasks with their current status.
|
|
68
|
-
- The new `
|
|
71
|
+
- The new `current_tasks` map (or "(plan complete)" if `plan.status == done`).
|
|
72
|
+
- If `project_switch` was emitted in the script output, note: "Project switch: {from} -> {to}".
|
|
69
73
|
- A one-line "Next" hint:
|
|
70
|
-
- If
|
|
74
|
+
- If `current_tasks` has entries -> recommend the skill matching the relevant task's `skill_hint`.
|
|
71
75
|
- If plan complete -> recommend `/mvt-cleanup` or starting a new change via `/mvt-analyze`.
|
|
72
76
|
- If all remaining tasks are blocked -> recommend resolving the blocker (point at the `notes` of the blocked task).
|
|
73
77
|
|
|
78
|
+
### Step 5: Epic Advancement Check
|
|
79
|
+
|
|
80
|
+
After the Step 3 script reports `plan_status: "done"`:
|
|
81
|
+
|
|
82
|
+
1. Read `session.active_change.epic_id` from session.yaml.
|
|
83
|
+
2. If empty -> skip this step (standard change, no epic context).
|
|
84
|
+
3. If non-empty -> prompt user:
|
|
85
|
+
|
|
86
|
+
> This change belongs to epic: **{epic_title}** ({epic_id}).
|
|
87
|
+
> All plan tasks are complete.
|
|
88
|
+
>
|
|
89
|
+
> - **(y)** Mark child done and advance to next sub-change
|
|
90
|
+
> - **(n)** Keep change open (continue review/test/sync)
|
|
91
|
+
> - **(defer)** Mark child done but don't advance yet
|
|
92
|
+
|
|
93
|
+
4. On **y**:
|
|
94
|
+
- `epic-update.cjs --epic <active_epic.epic_path> --complete-child <active_change.id>`
|
|
95
|
+
- `session-update.cjs --skill mvt-update-plan --summary "..." --close-change`
|
|
96
|
+
- Display: next child info from epic-update stdout. Suggest `/mvt-analyze` to start the next sub-change.
|
|
97
|
+
|
|
98
|
+
5. On **n**: No action. Display reminder: "Change remains open. Run other skills (e.g., `/mvt-review`, `/mvt-test`, `/mvt-fix`) as needed; run `/mvt-update-plan` again when ready to advance the epic."
|
|
99
|
+
|
|
100
|
+
6. On **defer**:
|
|
101
|
+
- `epic-update.cjs --epic <active_epic.epic_path> --set-child-status <active_change.id> done`
|
|
102
|
+
- `session-update.cjs --skill mvt-update-plan --summary "..." --close-change`
|
|
103
|
+
- Display: "Child marked done, current_change unchanged."
|
|
104
|
+
|
|
74
105
|
## Edge Cases & Errors
|
|
75
106
|
|
|
76
107
|
| Case | Handling |
|
|
@@ -79,5 +110,5 @@ Emit the Plan Update summary block defined in the Output Format section. Include
|
|
|
79
110
|
| Task id provided does not exist in `plan.yaml` | Abort with error listing valid task ids |
|
|
80
111
|
| Transition to `done` but `depends_on` tasks are not all `done` | Warn but allow: "Task marked done despite unfinished dependencies — verify correctness" |
|
|
81
112
|
| All tasks are `done` but user marks another as `in_progress` | Reject: plan is already complete; suggest creating a new change |
|
|
82
|
-
| Circular dependency detected in `depends_on` | Report the cycle and refuse to auto-advance `
|
|
113
|
+
| Circular dependency detected in `depends_on` | Report the cycle and refuse to auto-advance `current_tasks`; suggest manual fix |
|
|
83
114
|
| `plan.yaml` write fails (permission denied, invalid YAML state) | Abort; do not update session; report the write error |
|
|
@@ -3,7 +3,7 @@ output: .claude/skills/mvt-update-plan/SKILL.md
|
|
|
3
3
|
|
|
4
4
|
frontmatter:
|
|
5
5
|
name: mvt-update-plan
|
|
6
|
-
description: "Update a single task in the active change's plan.yaml: change status, attach artifacts, leave notes, and auto-advance
|
|
6
|
+
description: "Update a single task in the active change's plan.yaml: change status, attach artifacts, leave notes, and auto-advance current_tasks. This skill should be used after a workflow skill finishes work that maps to a plan task, or whenever the user wants to mark a task as done, blocked, or skipped."
|
|
7
7
|
|
|
8
8
|
sections:
|
|
9
9
|
- type: inline
|
|
@@ -12,7 +12,7 @@ sections:
|
|
|
12
12
|
|
|
13
13
|
## Purpose
|
|
14
14
|
|
|
15
|
-
Apply incremental updates to the active plan.yaml: mark a task done/blocked/skipped, attach the artifacts produced, and let the skill auto-advance `
|
|
15
|
+
Apply incremental updates to the active plan.yaml: mark a task done/blocked/skipped, attach the artifacts produced, and let the skill auto-advance `current_tasks` to the next executable task. AI may invoke this skill on the user's behalf when the user replies to a soft-prompt with `done` / `blocked: <reason>`.
|
|
16
16
|
|
|
17
17
|
- type: shared
|
|
18
18
|
source: sections/role-header.md
|
|
@@ -20,10 +20,10 @@ sections:
|
|
|
20
20
|
role: Architect
|
|
21
21
|
role_desc: "a Development Planner"
|
|
22
22
|
decision_rules:
|
|
23
|
-
- rule: "Task id provided AND target status valid -> Apply update, advance
|
|
23
|
+
- rule: "Task id provided AND target status valid -> Apply update, advance current_tasks, write back"
|
|
24
24
|
- rule: "Task id missing AND only one task is in_progress -> Default to that task"
|
|
25
|
-
- rule: "Target status would create an invalid
|
|
26
|
-
- rule: "All tasks become done -> Set plan.status = done,
|
|
25
|
+
- rule: "Target status would create an invalid current_tasks -> Recompute current_tasks automatically"
|
|
26
|
+
- rule: "All tasks become done -> Set plan.status = done, current_tasks = {}"
|
|
27
27
|
- rule: "active_change.plan_path is empty -> Stop and suggest /mvt-plan-dev"
|
|
28
28
|
|
|
29
29
|
boundaries:
|
|
@@ -46,6 +46,9 @@ sections:
|
|
|
46
46
|
- type: shared
|
|
47
47
|
source: sections/output-language-constraint.md
|
|
48
48
|
|
|
49
|
+
- type: shared
|
|
50
|
+
source: sections/output-format-constraint.md
|
|
51
|
+
|
|
49
52
|
- type: shared
|
|
50
53
|
source: sections/activation-preflight.md
|
|
51
54
|
params:
|
|
@@ -91,7 +94,7 @@ sections:
|
|
|
91
94
|
| ... |
|
|
92
95
|
|
|
93
96
|
Progress: {done_count}/{total_count}
|
|
94
|
-
Current
|
|
97
|
+
Current tasks: {new_current_tasks_map_or_"(plan complete)"}
|
|
95
98
|
|
|
96
99
|
### Next
|
|
97
100
|
{one-line guidance: continue to next task, resolve blocker, or run /mvt-cleanup}
|
|
@@ -116,7 +119,7 @@ sections:
|
|
|
116
119
|
primary_desc: "All tasks complete -- clean up artifacts and prepare to start the next change"
|
|
117
120
|
- condition: "default"
|
|
118
121
|
primary: mvt-implement
|
|
119
|
-
primary_desc: "Continue with the next
|
|
122
|
+
primary_desc: "Continue with the next task from current_tasks"
|
|
120
123
|
alternatives:
|
|
121
124
|
- skill: mvt-resume
|
|
122
125
|
desc: "Refresh context after task transitions"
|