@uoyo/mvtt 2.0.0-beta.4 → 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.
Files changed (86) hide show
  1. package/README.md +299 -64
  2. package/README.zh-CN.md +419 -0
  3. package/dist/commands/install.d.ts.map +1 -1
  4. package/dist/commands/install.js +27 -2
  5. package/dist/commands/install.js.map +1 -1
  6. package/dist/commands/uninstall.d.ts.map +1 -1
  7. package/dist/commands/uninstall.js +19 -7
  8. package/dist/commands/uninstall.js.map +1 -1
  9. package/dist/commands/update.d.ts.map +1 -1
  10. package/dist/commands/update.js +4 -2
  11. package/dist/commands/update.js.map +1 -1
  12. package/dist/fs/install-manifest.d.ts +4 -1
  13. package/dist/fs/install-manifest.d.ts.map +1 -1
  14. package/dist/fs/install-manifest.js +13 -1
  15. package/dist/fs/install-manifest.js.map +1 -1
  16. package/dist/fs/materialize.d.ts +2 -0
  17. package/dist/fs/materialize.d.ts.map +1 -1
  18. package/dist/fs/materialize.js +39 -9
  19. package/dist/fs/materialize.js.map +1 -1
  20. package/dist/fs/registry-merge.d.ts.map +1 -1
  21. package/dist/fs/registry-merge.js +72 -29
  22. package/dist/fs/registry-merge.js.map +1 -1
  23. package/dist/scripts/epic-update.cjs +7670 -0
  24. package/dist/scripts/plan-update.cjs +255 -82
  25. package/dist/scripts/session-update.cjs +84 -6
  26. package/dist/types/platform.d.ts +12 -0
  27. package/dist/types/platform.d.ts.map +1 -0
  28. package/dist/types/platform.js +24 -0
  29. package/dist/types/platform.js.map +1 -0
  30. package/dist/types/registry.d.ts +3 -24
  31. package/dist/types/registry.d.ts.map +1 -1
  32. package/install-manifest.yaml +4 -0
  33. package/package.json +1 -1
  34. package/registry.yaml +72 -198
  35. package/sources/defaults/config.yaml +8 -13
  36. package/sources/defaults/project-context.yaml +2 -5
  37. package/sources/defaults/session.yaml +14 -2
  38. package/sources/knowledge/core/manifest.yaml +1 -4
  39. package/sources/scripts/epic-update.js +512 -0
  40. package/sources/scripts/plan-update.js +614 -353
  41. package/sources/scripts/session-update.js +102 -2
  42. package/sources/sections/activation-load-config.md +1 -1
  43. package/sources/sections/activation-load-context.md +42 -13
  44. package/sources/sections/activation-preflight.md +1 -1
  45. package/sources/sections/footer-next-steps.md +3 -2
  46. package/sources/sections/session-update.md +41 -1
  47. package/sources/skills/mvt-analyze/business.md +46 -8
  48. package/sources/skills/mvt-analyze/manifest.yaml +5 -1
  49. package/sources/skills/mvt-analyze-code/business.md +18 -17
  50. package/sources/skills/mvt-analyze-code/manifest.yaml +3 -6
  51. package/sources/skills/mvt-check-context/business.md +13 -6
  52. package/sources/skills/mvt-check-context/manifest.yaml +0 -5
  53. package/sources/skills/mvt-cleanup/business.md +17 -2
  54. package/sources/skills/mvt-config/business.md +5 -5
  55. package/sources/skills/mvt-config/manifest.yaml +3 -6
  56. package/sources/skills/mvt-create-skill/business.md +2 -14
  57. package/sources/skills/mvt-create-skill/manifest.yaml +0 -5
  58. package/sources/skills/mvt-decompose/business.md +94 -0
  59. package/sources/skills/mvt-decompose/manifest.yaml +121 -0
  60. package/sources/skills/mvt-fix/business.md +21 -6
  61. package/sources/skills/mvt-fix/manifest.yaml +1 -1
  62. package/sources/skills/mvt-help/business.md +11 -9
  63. package/sources/skills/mvt-help/manifest.yaml +0 -5
  64. package/sources/skills/mvt-implement/business.md +51 -8
  65. package/sources/skills/mvt-init/business.md +23 -13
  66. package/sources/skills/mvt-init/manifest.yaml +1 -2
  67. package/sources/skills/mvt-manage-context/business.md +41 -14
  68. package/sources/skills/mvt-manage-context/manifest.yaml +2 -6
  69. package/sources/skills/mvt-plan-dev/business.md +17 -9
  70. package/sources/skills/mvt-quick-dev/business.md +22 -7
  71. package/sources/skills/mvt-quick-dev/manifest.yaml +0 -1
  72. package/sources/skills/mvt-refactor/business.md +32 -17
  73. package/sources/skills/mvt-refactor/manifest.yaml +0 -5
  74. package/sources/skills/mvt-resume/business.md +32 -12
  75. package/sources/skills/mvt-resume/manifest.yaml +3 -3
  76. package/sources/skills/mvt-review/business.md +24 -9
  77. package/sources/skills/mvt-status/business.md +37 -9
  78. package/sources/skills/mvt-status/manifest.yaml +2 -2
  79. package/sources/skills/mvt-sync-context/business.md +30 -16
  80. package/sources/skills/mvt-template/business.md +1 -1
  81. package/sources/skills/mvt-template/manifest.yaml +0 -5
  82. package/sources/skills/mvt-test/business.md +30 -15
  83. package/sources/skills/mvt-update-plan/business.md +41 -12
  84. package/sources/skills/mvt-update-plan/manifest.yaml +7 -7
  85. package/sources/templates/decompose-output/body.md +13 -0
  86. package/sources/templates/decompose-output/manifest.yaml +11 -0
@@ -89,6 +89,8 @@ For each project:
89
89
  - Name, path, type
90
90
  - Tech stack (language, framework, build tool, test framework)
91
91
 
92
+ **Project naming constraint**: each project name must match `[a-zA-Z0-9][a-zA-Z0-9_-]*` (no leading underscore). Validate all detected names against this constraint; if a name violates it (e.g., auto-detected as `_internal`), prompt the user to provide a valid alternative before proceeding.
93
+
92
94
  Wait for user to confirm or adjust:
93
95
  - `yes` -- Accept all
94
96
  - Provide corrections -- User specifies which fields to change
@@ -112,6 +114,7 @@ For each target file, check if it already exists:
112
114
  - name: "{project_name}"
113
115
  path: "{relative_path}"
114
116
  type: "{project_type}"
117
+ source_paths: []
115
118
  tech_stack:
116
119
  primary_language: "{language}"
117
120
  secondary_languages: [{...}]
@@ -119,6 +122,7 @@ For each target file, check if it already exists:
119
122
  build_tool: "{build_tool}"
120
123
  test_framework: "{test_framework}"
121
124
  ```
125
+ `source_paths` is populated by `/mvt-analyze-code` based on analyzed code structure. On initial `/mvt-init`, leave as empty array.
122
126
  For multi-project repos, include one entry per detected project.
123
127
 
124
128
  #### 5.3 Post-write validation
@@ -126,34 +130,40 @@ For each target file, check if it already exists:
126
130
  After writing all files, validate:
127
131
  - `project-context.yaml` is valid YAML with `projects[]` containing at least one entry
128
132
  - Each project entry has required fields: `name`, `path`, `type`, `tech_stack.primary_language`
129
- - `session.yaml` is structurally intact and contains: `session` (with `initialized_at`, `last_synced_at`), `active_change` (with `plan_path`), `changes` (array), `history`
130
133
 
131
134
  If any validation fails → report the specific error and offer to retry or skip.
132
135
 
133
- ### Step 6: Refresh Mode Handling (--refresh only)
136
+ ### Step 6: Refresh Mode Handling (Interactive)
137
+
138
+ When `mvt-init` is executed and existing MVTT artifacts are detected:
139
+
140
+ 1. **Prompt user**: "Existing MVTT configuration found. Refresh to re-scan project structure? (y/n)"
141
+ - If `n` -> stop, no changes made.
142
+ - If `y` -> proceed with refresh.
143
+
144
+ 2. **Re-scan** project structure using Steps 1-3 above.
134
145
 
135
- When `--refresh` is specified:
146
+ 3. **Compare** new vs existing `projects[]`. If project changes detected (added/removed/renamed sub-projects):
147
+ - Show diff: "+N added / -N removed / ~N renamed"
148
+ - Confirm before writing.
136
149
 
137
- 1. **Preserve** the following from existing files:
150
+ 4. **Preserve** the following from existing files:
138
151
  - `session.yaml` > `history`
139
152
  - `project-context.yaml` > any user-added custom fields (fields not in the standard schema)
140
153
  - `config.yaml` > `preferences` section
141
154
 
142
- 2. **Update** only auto-detectable fields:
155
+ 5. **Update** only auto-detectable fields:
143
156
  - `tech_stack` (re-scan and update)
144
157
  - `type` (re-infer)
158
+ - `source_paths` (re-scan)
145
159
 
146
- 3. **Diff and confirm**: Show a summary of what will change vs what will be preserved. Ask for confirmation before writing.
160
+ 6. **After writing** -> prompt: "Project structure updated. Recommend running `/mvt-analyze-code` to sync semantic context."
147
161
 
148
- 4. **Old format migration**: If existing `project-context.yaml` uses old format (has top-level `project`, `requirements`, `architecture`, `environment` keys):
149
- - Wrap `project.*` as `projects[0]` with `name="default"`, `path="."`
150
- - Discard `requirements`, `architecture` sections -- suggest running `/mvt-analyze-code` to regenerate
151
- - Discard `environment` section
152
- - Discard any `pattern` related fields
162
+ 7. **Orphan knowledge entries**: After refresh, if any knowledge entries in `registry.yaml` reference a project name not in the updated `projects[]`, prompt: "N orphan knowledge entries found for project(s) not in projects list: {names}. Consider `/mvt-manage-context remove` to clean up."
153
163
 
154
164
  ### Step 7: Determine Project State (drives next-step recommendation)
155
165
 
156
- After Step 5 writes are committed, classify the project state to select the appropriate next_suggestions branch from registry.yaml:
166
+ After Step 5 writes are committed, classify the project state to select the appropriate recommendation branch in the **Suggested Next Steps** section below:
157
167
 
158
168
  | Condition | Detection logic |
159
169
  |-----------|-----------------|
@@ -161,4 +171,4 @@ After Step 5 writes are committed, classify the project state to select the appr
161
171
  | `empty_project` | Step 1 found no source files AND no package manager file (truly empty or docs-only repo) -- the recommended next step is `/mvt-manage-context` to manually capture context |
162
172
  | `default` | Neither condition matched (rare -- fallback path) |
163
173
 
164
- Pass the resolved condition to the output template so the suggested next steps section renders the matching branch from `registry.yaml > skills.mvt-init.next_suggestions.conditional[]`.
174
+ Use the resolved condition to render the matching branch in the **Suggested Next Steps** section (Conditional Recommendations).
@@ -43,8 +43,7 @@ sections:
43
43
 
44
44
  | Variant | Description |
45
45
  |---------|-------------|
46
- | `/mvt-init` | Standard initialization (scan + detect + write index) |
47
- | `/mvt-init --refresh` | Re-scan existing project -- preserve user state, update auto-detectable fields, show diff before writing |
46
+ | `/mvt-init` | Standard initialization or interactive refresh (scan + detect + write index; re-scan on existing project with user confirmation) |
48
47
 
49
48
  - type: shared
50
49
  source: sections/activation-load-context.md
@@ -19,6 +19,21 @@ For interactive menu, present the five options and wait for user choice, then en
19
19
 
20
20
  Switch to the matching section below.
21
21
 
22
+ ### Map-Aware Knowledge Structure
23
+
24
+ The registry uses project-keyed knowledge maps. Every knowledge block (top-level `knowledge` and each `skills.<name>.knowledge`) is a map where keys are project names or the reserved `_all` key (all projects). All subcommands must operate on this map structure.
25
+
26
+ **Two-question routing table (add subcommand)**:
27
+
28
+ | Question 1: Scope | Question 2: Breadth | Registry key path |
29
+ |--------------------|---------------------|-------------------|
30
+ | global | all skills | `knowledge._all` |
31
+ | project-specific | all skills | `knowledge.{projectName}` |
32
+ | global | specific skill | `skills.{name}.knowledge._all` |
33
+ | project-specific | specific skill | `skills.{name}.knowledge.{projectName}` |
34
+
35
+ **`_all` promotion confirmation**: routing to `knowledge._all` or `skills.{name}.knowledge._all` means the entry will be loaded by every skill across every project (or every project for that skill). When the add flow routes to `_all`, prompt: "This knowledge will be loaded by ALL skills across ALL projects. Confirm? (y/n)" -- default to **n** for project-specific entries, default to **y** only when the user explicitly chose scope=global.
36
+
22
37
  ---
23
38
 
24
39
  ## Subcommand: add
@@ -36,24 +51,31 @@ Classify the content into one of:
36
51
 
37
52
  The skill should suggest a type based on content keywords; the user confirms or overrides.
38
53
 
39
- ### 2.3 AI Routing -- Score every skill
54
+ ### 2.3 AI Routing -- Two-question routing + skill scoring
40
55
 
41
- 1. Read `.ai-agents/registry.yaml` > `skills.*` -- collect every skill's `name` and `description`.
42
- 2. For each skill, score relevance to the content on a 0-100 scale:
56
+ 1. **Question 1: Scope** -- Ask: "Is this knowledge global (applies to all projects) or project-specific?"
57
+ - `global` -> keys under `_all`
58
+ - `project-specific` -> ask which project (list from `project-context.yaml > projects[].name`); key under `{projectName}`
59
+ 2. **Question 2: Breadth** -- Ask: "Should this knowledge be loaded by all skills or a specific skill?"
60
+ - `all skills` -> top-level `knowledge` map
61
+ - `specific skill` -> AI-score each skill for relevance (see below)
62
+ 3. Read `.ai-agents/registry.yaml` > `skills.*` -- collect every skill's `name` and `description`.
63
+ 4. For each skill, score relevance to the content on a 0-100 scale:
43
64
  - 90-100: directly aligned (e.g., review rules + `mvt-review`)
44
65
  - 70-89: strongly relevant
45
66
  - 50-69: tangentially relevant
46
67
  - 0-49: weak match
47
- 3. Read `.ai-agents/config.yaml` > `preferences.context_routing.relevance_threshold` (default 70 if missing).
48
- 4. Display **all** skills sorted by score descending. Do not truncate -- the user sees the full list with scores.
68
+ 5. Read `.ai-agents/config.yaml` > `preferences.context_routing.relevance_threshold` (default 70 if missing).
69
+ 6. Display **all** skills sorted by score descending. Do not truncate -- the user sees the full list with scores.
49
70
  - Skills at or above threshold: pre-checked, shown with `[High]` / `[Med]` markers (or stars in emoji mode).
50
71
  - Skills below threshold: collapsed under an "expand" prompt; not pre-checked.
72
+ 7. Combine the two questions with the scoring to determine the registry key path per the routing table above.
51
73
 
52
74
  ### 2.4 Accept user input
53
75
  Accept any of:
54
76
  - `Enter` (empty input) -- confirm pre-checked selection
55
77
  - Comma-separated indices (e.g. `1,3,5`) -- custom skill selection
56
- - `s` -- promote to **shared** (write to `registry.yaml > knowledge.shared`)
78
+ - `s` -- promote to **global** (write to `registry.yaml > knowledge._all`)
57
79
  - `c` -- promote to **core** (write to `.ai-agents/knowledge/core/user/{filename}` + append entry to `core/manifest.yaml` with `origin: user`)
58
80
  - `n` -- **none** (file-only; not auto-loaded)
59
81
  - `m` -- **manual** mode (display the full skill list including below-threshold for direct picking)
@@ -63,8 +85,8 @@ Accept any of:
63
85
 
64
86
  | User choice | File destination | Registry / manifest update |
65
87
  |------------|-----------------|----------------------------|
66
- | Per-skill (any subset) | `.ai-agents/knowledge/{type}/{filename}` (`type` = `principle` or `project`) | For each chosen skill: append entry to `registry.yaml > skills.{name}.knowledge[]` with `type: static`, `source: knowledge/{type}/`, `files: [{filename}]` |
67
- | `s` (shared) | `.ai-agents/knowledge/{type}/{filename}` | Append to `registry.yaml > knowledge.shared[]` with the same `type: static` shape |
88
+ | Per-skill (any subset) | `.ai-agents/knowledge/{type}/{filename}` (`type` = `principle` or `project`) | For each chosen skill: append entry to `registry.yaml > skills.{name}.knowledge.{projectKey}[]` with `type: static`, `source: knowledge/{type}/`, `files: [{filename}]`. `projectKey` = `_all` if scope=global, or `{projectName}` if project-specific. |
89
+ | `s` (shared / global + all skills) | `.ai-agents/knowledge/{type}/{filename}` | Append to `registry.yaml > knowledge._all[]` with the same `type: static` shape |
68
90
  | `c` (core) | `.ai-agents/knowledge/core/user/{filename}` | Append to `core/manifest.yaml > files[]` with `path: user/{filename}`, `origin: user`, `auto_load: true` |
69
91
  | `n` (none) | `.ai-agents/knowledge/{type}/{filename}` | No registry/manifest change |
70
92
 
@@ -93,8 +115,10 @@ Use the `add / move / rename` output format from the manifest. Show:
93
115
  Show the entry's file path, all binding references (shared / per-skill / core), and ask user to confirm.
94
116
 
95
117
  ### 3.3 Drop references
96
- - `registry.yaml > knowledge.shared[]` -- remove entries whose path matches
97
- - `registry.yaml > skills.*.knowledge[]` -- remove every per-skill entry whose path matches
118
+ - `registry.yaml > knowledge._all[]` -- remove entries whose path matches
119
+ - `registry.yaml > knowledge.{projectName}[]` -- traverse ALL project keys, remove entries whose path matches
120
+ - `registry.yaml > skills.*.knowledge._all[]` -- remove every per-skill _all entry whose path matches
121
+ - `registry.yaml > skills.*.knowledge.{projectName}[]` -- traverse ALL project keys for each skill, remove entries whose path matches
98
122
  - `core/manifest.yaml > files[]` -- if the file lives under `core/user/`, remove the matching entry
99
123
 
100
124
  ### 3.4 Delete file
@@ -115,7 +139,10 @@ Use the `remove` output format. Show every reference dropped.
115
139
  Display where the entry is currently bound (shared / per-skill / core / none).
116
140
 
117
141
  ### 4.3 Prompt for new binding
118
- Use the same UI as `add` step 2.4 (Enter / indices / `s` / `c` / `n`).
142
+ Use the same two-question routing as `add` step 2.3 (Scope + Breadth -> registry key path). Support cross-key movement:
143
+ - `_all` -> `{projectName}` (narrow from global to project-specific)
144
+ - `{projectName}` -> `_all` (promote to global; apply `_all` promotion confirmation)
145
+ - `{projectName1}` -> `{projectName2}` (move between projects)
119
146
 
120
147
  ### 4.4 Apply changes
121
148
  - Update registry / manifest references atomically:
@@ -151,14 +178,14 @@ Use the `add / move / rename` output format.
151
178
  ## Subcommand: list
152
179
 
153
180
  ### 6.1 Read sources
154
- - `.ai-agents/registry.yaml` > `knowledge.shared[]` and `skills.*.knowledge[]`
181
+ - `.ai-agents/registry.yaml` > `knowledge._all[]`, `knowledge.{projectName}[]`, `skills.*.knowledge._all[]`, `skills.*.knowledge.{projectName}[]` -- traverse ALL project keys
155
182
  - `.ai-agents/knowledge/core/manifest.yaml` > `files[]`
156
183
  - Walk `.ai-agents/knowledge/{principle,project}/` for files not referenced anywhere (Unbound)
157
184
 
158
185
  ### 6.2 Group and render
159
- Use the `list` output format. Each row should answer: where is the file, and which skills load it?
186
+ Use the `list` output format. Group by **project x skill** (3D table). Each row should answer: where is the file, which project(s) does it serve, and which skills load it?
160
187
 
161
- For Per-Skill rows, list every skill that binds to the file (a single file can be bound to multiple skills).
188
+ Flag **orphan entries** -- entries under a project key not in `projects[].name` from `project-context.yaml`.
162
189
 
163
190
  ### 6.3 Health hints
164
191
  At the bottom of the list, optionally surface:
@@ -52,11 +52,6 @@ sections:
52
52
  - type: shared
53
53
  source: sections/output-format-constraint.md
54
54
 
55
- - type: inline
56
- content: |
57
- ### Step 4: Pre-flight Checks
58
- - No blocking checks required.
59
-
60
55
  - type: file
61
56
  source: ./business.md
62
57
 
@@ -92,7 +87,8 @@ sections:
92
87
  ### Removed entry: `{id}`
93
88
  - File: `.ai-agents/knowledge/{path}` (deleted)
94
89
  - References dropped from:
95
- - `registry.yaml > knowledge.shared` (if applicable)
90
+ - `registry.yaml > knowledge._all` (if applicable)
91
+ - `registry.yaml > knowledge.{projectName}` (if applicable)
96
92
  - `registry.yaml > skills.{name}.knowledge` x N (if applicable)
97
93
  - `core/manifest.yaml > files[]` (if applicable)
98
94
  ```
@@ -15,7 +15,7 @@ If no analysis or design artifacts exist and the user provides no description, p
15
15
  If `active_change.plan_path is non-empty` AND `.ai-agents/workspace/artifacts/{active_change.id}/plan.yaml` already exists:
16
16
 
17
17
  - Read the existing plan.
18
- - Show a summary (task count, status counts, current_task).
18
+ - Show a summary (task count, status counts, current_tasks).
19
19
  - Ask: "A plan already exists. Choose: (1) regenerate from scratch (existing tasks discarded), (2) cancel and use `/mvt-update-plan` to evolve it, (3) abort."
20
20
  - Only continue with generation on choice (1).
21
21
 
@@ -31,6 +31,7 @@ Decompose the change with the following constraints. These constraints are AI-fr
31
31
  | Explicit dependencies | If task B requires output from task A, list `A` in B's `depends_on`. Avoid hidden ordering. Tasks that can run in parallel should have no dependency between them. |
32
32
  | No cycles | Dependency graph must be a DAG. Validation will reject cycles. |
33
33
  | Skill hint | Set `skill_hint` to the skill best suited to execute the task (without `/` prefix): `mvt-implement`, `mvt-test`, `mvt-fix`, `mvt-design`, `mvt-review`, `mvt-refactor`, etc. |
34
+ | Project attribution | Each task must have a `project` array listing which projects it belongs to. In a single-project workspace (`projects.length == 1`), set `project: ["default"]` (or the sole project's name). In a multi-project workspace, auto-infer from the task's file paths matching `projects[].path` and `projects[].source_paths`; if ambiguous, prompt the user. Cross-project tasks list multiple project names. |
34
35
 
35
36
  ### Step 4: Assemble plan.yaml
36
37
 
@@ -43,7 +44,8 @@ title: "Feature Name"
43
44
  created_at: "2026-05-31T11:30:00"
44
45
  updated_at: "2026-05-31T11:30:00"
45
46
  status: in_progress
46
- current_task: "t1-foundation-layer"
47
+ current_tasks:
48
+ default: "t1-foundation-layer"
47
49
 
48
50
  tasks:
49
51
  - id: "t1-foundation-layer"
@@ -51,6 +53,8 @@ tasks:
51
53
  status: in_progress
52
54
  completed_at: null
53
55
  depends_on: []
56
+ project:
57
+ - default
54
58
  skill_hint: mvt-implement
55
59
  artifacts:
56
60
  files:
@@ -68,6 +72,8 @@ tasks:
68
72
  status: pending
69
73
  completed_at: null
70
74
  depends_on: ["t1-foundation-layer"]
75
+ project:
76
+ - default
71
77
  skill_hint: mvt-implement
72
78
  artifacts: null
73
79
  notes: >
@@ -87,7 +93,7 @@ tasks:
87
93
  - `created_at`: current ISO 8601 timestamp
88
94
  - `updated_at`: same as `created_at` initially
89
95
  - `status: in_progress`
90
- - `current_task`: the `id` of the first executable task (a task with `depends_on: []`), set to `in_progress`
96
+ - `current_tasks`: a map of project name to task id. For single-project workspaces: `{ default: "<first_task_id>" }`. For multi-project: one key per project, each pointing to that project's first executable task.
91
97
 
92
98
  #### Task fields
93
99
 
@@ -98,6 +104,7 @@ For each task, populate:
98
104
  - **`status`**: first executable task → `in_progress`; all others → `pending`.
99
105
  - **`completed_at`**: `null` for all tasks on initial creation (set by `/mvt-update-plan` when marking `done`).
100
106
  - **`depends_on`**: array of task ids. Empty array `[]` means no dependencies.
107
+ - **`project`**: array of project names this task belongs to. In single-project workspaces, use `["default"]` (or the sole project's name). Cross-project tasks list multiple names. Auto-infer from file paths matching `projects[].path` and `projects[].source_paths`; if ambiguous, prompt the user.
101
108
  - **`skill_hint`**: the skill name (without `/`) that will execute this task.
102
109
  - **`artifacts`**: structured object. On initial plan creation, set to `null` or pre-populate with planned target files if known:
103
110
  ```yaml
@@ -118,11 +125,12 @@ Before writing, validate the assembled YAML:
118
125
 
119
126
  1. **Unique IDs** — no two tasks share the same `id`
120
127
  2. **Valid references** — every `depends_on` entry references an existing task `id`
121
- 3. **No cycles** — the dependency graph is a DAG
122
- 4. **current_task validity** — references a task with status `pending` or `in_progress`
128
+ 3. **No cycles** — the dependency graph is a DAG (per-project subgraph when multi-project)
129
+ 4. **current_tasks validity** — each value references a task with status `pending` or `in_progress`
123
130
  5. **Acceptance required** — every task has at least one acceptance criterion
124
- 6. **Single in_progress** — at most one task has status `in_progress`
131
+ 6. **Per-project in_progress** — at most one `in_progress` task per project (not globally)
125
132
  7. **completed_at consistency** — must be `null` for all non-done tasks
133
+ 8. **Project attribution** — every task has a `project` array with at least one valid project name
126
134
 
127
135
  If validation fails, revise the plan and re-validate (do NOT write a broken plan).
128
136
 
@@ -148,9 +156,9 @@ Render an inline summary (no external template). Structure:
148
156
 
149
157
  ### Task Breakdown
150
158
 
151
- | # | id | title | status | skill | depends_on |
152
- |---|----|----|--------|-------|------------|
153
- | 1 | {id} | {title} | {status} | {skill_hint} | {deps_or_"—"} |
159
+ | # | id | title | status | skill | project | depends_on |
160
+ |---|----|----|--------|-------|---------|------------|
161
+ | 1 | {id} | {title} | {status} | {skill_hint} | {project_list} | {deps_or_"—"} |
154
162
  | ... |
155
163
 
156
164
  ```
@@ -46,7 +46,22 @@
46
46
  5. Cross-reference `project-context.md` layer rules (if available) -- flag any change that would violate layer constraints.
47
47
  - **Output of this step**: a target list (`path | action | one-line intent`).
48
48
 
49
- ### Step 4: Plan the Change
49
+ ### Step 4: Identify Project Scope and Load Project-Specific Knowledge
50
+
51
+ 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.
52
+
53
+ - **Project identification**: match the file paths resolved in Step 3 against `projects[].path` and `projects[].source_paths`:
54
+ - A file whose path starts with a project's `path` prefix belongs to that project.
55
+ - A file under a project's `source_paths` entry also belongs to that project.
56
+ - Collect the set of unique project names from all matched files. This is the **active project scope** for this invocation.
57
+ - **On-demand knowledge loading**: for each project P in the active project scope, read `.ai-agents/registry.yaml` and load:
58
+ 1. Every entry under `knowledge.{P}` -- load each entry's referenced files (resolve relative to `.ai-agents/{source}`).
59
+ 2. Every entry under `skills.mvt-quick-dev.knowledge.{P}` -- load each entry's referenced files.
60
+ 3. Skip any key absent from the registry (no project-specific knowledge is valid; do not warn).
61
+ - **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.
62
+ - **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`.
63
+
64
+ ### Step 5: Plan the Change
50
65
  - **What**: produce an ordered file list before writing any code.
51
66
  - **How**:
52
67
  1. For each target from Step 3, decide: `create | modify | delete`, and write a one-line intent.
@@ -60,31 +75,31 @@
60
75
  | Plan exceeds 3 files | Escalate to Complex -- STOP, recommend standard workflow |
61
76
  | Plan introduces an unplanned module | Escalate to Complex -- STOP, recommend standard workflow |
62
77
 
63
- ### Step 5: Implement
78
+ ### Step 6: Implement
64
79
  - **What**: write/modify the planned files.
65
80
  - **How**:
66
- 1. Apply changes one file at a time, in the order determined by Step 4.
67
- 2. Follow `coding-standards.md` if available; match surrounding code style otherwise.
81
+ 1. Apply changes one file at a time, in the order determined by Step 5.
82
+ 2. Follow the coding standards loaded by activation (if any); match surrounding code style otherwise.
68
83
  3. Respect module/layer rules from `project-context.md`. Forbidden imports must NOT appear.
69
84
  4. Add error handling at system boundaries only (HTTP, DB, external API, file IO, message bus). Do NOT add try/catch around internal calls.
70
85
  5. Inline comments only for non-obvious algorithmic choices or deliberate workarounds with a reason.
71
86
  6. Do NOT introduce abstractions, helpers, or feature flags beyond what the task requires.
72
87
 
73
- ### Step 6: Quick Verify
88
+ ### Step 7: Quick Verify
74
89
  - **What**: light-weight verification before reporting completion.
75
90
  - **How**:
76
91
  1. If a type-checker is configured for the project (`tsc`, `mypy`, `cargo check`, etc.), run it on changed files only. Surface failures.
77
92
  2. If existing tests cover the changed code, suggest the test command but do not auto-run unless user explicitly approved.
78
93
  3. For frontend/UI changes, note that user should verify in browser; do NOT claim "tested" based on type-check alone.
79
94
 
80
- ### Step 7: Summarize in Conversation
95
+ ### Step 8: Summarize in Conversation
81
96
  - **What**: present the result without writing any artifact file.
82
97
  - **How**: output a brief summary containing:
83
98
  - Files touched: `path | action`
84
99
  - Verification status: type-check result, test suggestion
85
100
  - **No artifact is written. No document is generated.** This is a conversation-only skill.
86
101
 
87
- ### Step 8: State Update
102
+ ### Step 9: State Update
88
103
  Apply the State Update rules defined in the **State Update** section below.
89
104
 
90
105
  ## Edge Cases & Errors
@@ -39,7 +39,6 @@ sections:
39
39
  params:
40
40
  extended_context:
41
41
  - ".ai-agents/knowledge/project/_generated/project-context.md -- Module/layer map (optional)"
42
- - ".ai-agents/knowledge/principle/coding-standards.md -- Coding standards (optional)"
43
42
  - "Target source files (load based on change description)"
44
43
 
45
44
  - type: shared
@@ -16,12 +16,27 @@
16
16
  3. State the current behavior in plain language; include any non-obvious side effects or invariants you can see in the code.
17
17
  - **Output of this step**: a target table (`file | range | role`) and a "current behavior" paragraph; both are shown to user before continuing.
18
18
 
19
- ### Step 3: Classify Refactoring Type
19
+ ### Step 3: Identify Project Scope and Load Project-Specific Knowledge
20
+
21
+ 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.
22
+
23
+ - **Project identification**: match the file paths resolved in Step 2 against `projects[].path` and `projects[].source_paths`:
24
+ - A file whose path starts with a project's `path` prefix belongs to that project.
25
+ - A file under a project's `source_paths` entry also belongs to that project.
26
+ - Collect the set of unique project names from all matched files. This is the **active project scope** for this invocation.
27
+ - **On-demand knowledge loading**: for each project P in the active project scope, read `.ai-agents/registry.yaml` and load:
28
+ 1. Every entry under `knowledge.{P}` -- load each entry's referenced files (resolve relative to `.ai-agents/{source}`).
29
+ 2. Every entry under `skills.mvt-refactor.knowledge.{P}` -- load each entry's referenced files.
30
+ 3. Skip any key absent from the registry (no project-specific knowledge is valid; do not warn).
31
+ - **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.
32
+ - **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`.
33
+
34
+ ### Step 4: Classify Refactoring Type
20
35
  - **What**: pick the smallest type that covers the requested change. Use the Refactoring Types table above for risk levels.
21
36
  - **How**: assign one primary type per refactoring task. Multiple types in one run are allowed but each must be tracked separately in the artifact.
22
37
  - If the request requires `Change Interface/API` AND the symbol is exported beyond the project (public API, library entry point, IPC boundary): STOP -- this is no longer a refactoring task; recommend `/mvt-design`.
23
38
 
24
- ### Step 4: Risk Assessment
39
+ ### Step 5: Risk Assessment
25
40
  - **What**: assign a final risk score and decide whether explicit confirmation is needed.
26
41
  - **How**: combine refactoring type and impact factors.
27
42
 
@@ -34,11 +49,11 @@
34
49
  | User has uncommitted changes overlapping the target | +1 |
35
50
 
36
51
  - Final risk = type's base level + factors:
37
- - Low + 0..1 -> proceed silently in Step 7.
38
- - Medium OR Low + 2 -> require explicit confirmation in Step 6.
39
- - High OR (Medium + 2) -> require explicit confirmation AND a behavior-preservation strategy from Step 5.
52
+ - Low + 0..1 -> proceed silently in Step 8.
53
+ - Medium OR Low + 2 -> require explicit confirmation in Step 7.
54
+ - High OR (Medium + 2) -> require explicit confirmation AND a behavior-preservation strategy from Step 6.
40
55
 
41
- ### Step 5: Choose Behavior-Preservation Strategy
56
+ ### Step 6: Choose Behavior-Preservation Strategy
42
57
  - **What**: pick a verification path BEFORE editing.
43
58
  - **How**: choose the row that matches your test reality.
44
59
 
@@ -50,34 +65,34 @@
50
65
 
51
66
  - Document the chosen strategy in the artifact regardless of risk level.
52
67
 
53
- ### Step 6: Confirm with User (when required)
54
- - **Trigger**: per the Step 4 thresholds, or any High-risk type.
68
+ ### Step 7: Confirm with User (when required)
69
+ - **Trigger**: per the Step 5 thresholds, or any High-risk type.
55
70
  - **Format**: present a single screen with:
56
71
  - Target summary (Step 2's table, condensed to file count + symbol).
57
72
  - Refactoring type and risk level.
58
73
  - Number of callers and a list of the top 5 affected files.
59
- - Behavior-preservation strategy (Step 5).
74
+ - Behavior-preservation strategy (Step 6).
60
75
  - One yes/no prompt: `Proceed with this refactor? (y / n / show-plan)`.
61
76
 
62
- ### Step 7: Plan and Execute Incrementally
77
+ ### Step 8: Plan and Execute Incrementally
63
78
  - **What**: apply the change in the smallest reversible steps.
64
79
  - **How**:
65
80
  1. Break the refactor into ordered sub-steps (e.g., Rename: 1) update declaration, 2) update callers, 3) update tests, 4) update docs).
66
81
  2. After each sub-step:
67
82
  - Compile / type-check the affected files.
68
- - If a test command was identified in Step 5, run it (or surface it for user to run if running tests is not allowed in this environment).
83
+ - If a test command was identified in Step 6, run it (or surface it for user to run if running tests is not allowed in this environment).
69
84
  - On failure: revert the sub-step, surface the cause, do NOT continue.
70
85
  3. Do not interleave behavior changes (bug fixes, feature toggles) with the refactor. If you spot one, note it for follow-up; do not silently include it.
71
86
  4. Do not modify code outside the planned target unless required for compilation/type correctness; record any such "incidental" edits.
72
87
 
73
- ### Step 8: Verify Behavior Preservation
88
+ ### Step 9: Verify Behavior Preservation
74
89
  - **What**: prove (within the chosen strategy) that observable behavior is unchanged.
75
90
  - **How**:
76
91
  - With tests: all pre-existing tests pass; new characterization tests pass; assert pass count is unchanged or increased.
77
92
  - Without tests: list the call sites you visually verified, plus the manual behavior checks you recommend the user run.
78
- - If anything regresses: revert the most recent sub-step, surface the regression, return to Step 7. Do not declare success.
93
+ - If anything regresses: revert the most recent sub-step, surface the regression, return to Step 8. Do not declare success.
79
94
 
80
- ### Step 9: Write Refactor Notes
95
+ ### Step 10: Write Refactor Notes
81
96
  - **Path**: `.ai-agents/workspace/artifacts/{change-id}/refactor-notes.md` if `active_change` exists; otherwise inline summary in conversation only (shortcut mode).
82
97
  - **Required content**:
83
98
  - `Target` -- file/symbol list, current-behavior paragraph.
@@ -88,7 +103,7 @@
88
103
  - `Verification Result` -- tests run, pass/fail counts; or manual checks recommended.
89
104
  - `Follow-ups` -- deferred behavior changes spotted during refactoring.
90
105
 
91
- ### Step 10: State Update
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
@@ -98,8 +113,8 @@ Apply the State Update rules defined in the **State Update** section below.
98
113
  | Target spans multiple repos / submodules | STOP -- out of scope; recommend a coordinated change rather than a single refactor |
99
114
  | Refactor uncovers a real bug | Pause refactor, document the bug, recommend `/mvt-fix` -- do NOT fix during the refactor |
100
115
  | Refactor target is dead code | Confirm with user before deleting; offer alternative of marking deprecated first |
101
- | Symbol is referenced via reflection / dynamic dispatch / string lookup | Increase risk by +2; require strategy 5(a) (characterization test) before proceeding |
116
+ | Symbol is referenced via reflection / dynamic dispatch / string lookup | Increase risk by +2; require strategy 6(a) (characterization test) before proceeding |
102
117
  | User has uncommitted changes overlapping the target | Show diff, recommend committing/stashing first, ask for explicit confirmation if user wants to proceed anyway |
103
118
  | Type/test failures persist after revert | Surface a clear summary; suggest user re-run the original test baseline to detect a pre-existing failure unrelated to the refactor |
104
- | User aborts at Step 6 | Do not modify any file; report "no changes" |
119
+ | User aborts at Step 7 | Do not modify any file; report "no changes" |
105
120
  | Active change is mid-implementation (not yet `done`) | Warn that refactoring during implementation can confuse review/test phases; require explicit confirmation |
@@ -68,11 +68,6 @@ sections:
68
68
  - type: shared
69
69
  source: sections/output-format-constraint.md
70
70
 
71
- - type: inline
72
- content: |
73
- ### Step 4: Pre-flight Checks
74
- - No blocking checks required (shortcut operation).
75
-
76
71
  - type: inline
77
72
  content: |
78
73
  ## Operation Mode: Shortcut
@@ -2,12 +2,23 @@
2
2
 
3
3
  ### Step 1: Read Session State
4
4
 
5
- Extract from the already-loaded session context:
6
- - `active_change` -- the current change-id (if any), plan_path
5
+ Read `.ai-agents/workspace/session.yaml`. If the file is missing or empty, jump to Step 8 with the "no session" branch.
6
+
7
+ Extract:
8
+ - `active_change` -- the current change-id (if any), plan_path, epic_id
9
+ - `active_epic` -- the current epic (if any): id, title, epic_path
7
10
  - `changes` -- list of changes with active plans
8
11
  - `history` -- last 20 entries (skill name, timestamp, change_id)
9
12
 
10
- If session.yaml is missing or empty, jump to Step 8 with the "no session" branch.
13
+ ### Step 1a: Check Epic State
14
+
15
+ After extracting session data in Step 1, check for epic state:
16
+
17
+ | Condition | Action |
18
+ |-----------|--------|
19
+ | `active_change.id` non-empty AND `active_change.epic_id` non-empty | Set `within_epic = true`. Continue to Step 2 (normal plan-based resume). In Step 7, include an Epic Context section. |
20
+ | `active_change.id` empty AND `active_epic.id` non-empty (epic-pending) | Read `epic.yaml` via `active_epic.epic_path`. If unreadable, warn and jump to Step 8 with the "epic-pending but epic.yaml missing" edge case. Otherwise, identify the child referenced by `epic.yaml.current_change` as the resume target. Skip Steps 2-6 and go directly to Step 7 with a simplified report containing: (1) **Epic State** -- epic title, id, status, progress (done/total); (2) **Current Sub-change** -- title, scope, depends_on status of each dependency; (3) **Resume Point** -- "Resuming epic: {title}. Next sub-change: {current_change_title}. Run `/mvt-analyze` to start."; (4) **Recommended Next Step** -- `/mvt-analyze` -- Start the next sub-change in the epic. |
21
+ | Neither | Continue to Step 2 (normal flow). |
11
22
 
12
23
  ### Step 2: Discover Pending Plans
13
24
 
@@ -56,18 +67,23 @@ For each artifact, capture: file path, mtime, size (in tokens estimate = chars /
56
67
 
57
68
  ### Step 5: Determine Resume Point
58
69
 
59
- Read the plan's `current_task`. The resume point = that task. Next-step recommendation = the task's `skill_hint` (or infer from task title if skill_hint is absent).
70
+ Read the plan's `current_tasks` map. The resume point = the task(s) referenced by `current_tasks`. Next-step recommendation = the relevant task's `skill_hint` (or infer from task title if skill_hint is absent).
71
+
72
+ For multi-project workspaces, if `current_tasks` has entries for multiple projects, display each project's current task separately.
60
73
 
61
74
  Also filter `history` to entries matching `change_id == selected_change_id` (entries with empty change_id are excluded from this filtered view).
62
75
 
76
+ If the plan-update script output from a previous session included a `project_switch` notification, surface it: "Last session crossed from {from} to {to} project."
77
+
63
78
  ### Step 6: Load Plan Progress
64
79
 
65
80
  Generate the **Plan Progress** section:
66
81
 
67
82
  - Read all tasks from plan.yaml.
68
- - Build a compact status table: `| # | id | title | status | skill_hint |`
69
- - Highlight `current_task` row (prefix with `>>` or bold).
83
+ - Build a compact status table: `| # | id | title | status | project | skill_hint |`
84
+ - Highlight `current_tasks` rows (prefix with `>>` or bold).
70
85
  - Count summary: `Done: {d}, In Progress: {ip}, Pending: {p}, Blocked: {b}, Skipped: {s}`
86
+ - If any task has `deliverables.freshness == "stale"`, append a warning: "Stale deliverables: {task_ids} -- downstream tasks may be out of date. Run `/mvt-implement` to refresh."
71
87
 
72
88
  And the **Current Task Detail** section:
73
89
 
@@ -82,11 +98,12 @@ And the **Current Task Detail** section:
82
98
  Render via the `resume-output.md` template. Sections to fill:
83
99
 
84
100
  1. **Active Task** -- name, change-id, started_at (from selected plan)
85
- 2. **Plan Progress** -- task table + counts + current task detail
86
- 3. **Recent Skill History** -- last 5 entries from history (filtered to selected change if applicable)
87
- 4. **Recent Artifacts** -- the top 5 artifacts collected in Step 4 (path, mtime, size)
88
- 5. **Resume Point** -- a one-paragraph natural-language summary of "where we are"
89
- 6. **Recommended Next Step** -- the mapped next skill from Step 5, with justification
101
+ 2. **Epic Context** (if `within_epic` is true) -- epic title, id, progress (done/total children), current position within the epic. Resolve the parent epic path: compare `active_change.epic_id` to `active_epic.id`. If they match, use `active_epic.epic_path`. If they do not match, search `session.epics[]` for an entry with `id == active_change.epic_id` and use its `epic_path`. If neither path exists, render the plan resume and add a bounded warning: "Epic context could not be loaded (epic_id: {active_change.epic_id})." Read `epic.yaml` via the resolved path and render: "This change is part of epic: **{epic_title}** ({done}/{total} sub-changes done). Current: {active_child_title}."
102
+ 3. **Plan Progress** -- task table + counts + current task detail
103
+ 4. **Recent Skill History** -- last 5 entries from history (filtered to selected change if applicable)
104
+ 5. **Recent Artifacts** -- the top 5 artifacts collected in Step 4 (path, mtime, size)
105
+ 6. **Resume Point** -- a one-paragraph natural-language summary of "where we are"
106
+ 7. **Recommended Next Step** -- the mapped next skill from Step 5, with justification
90
107
 
91
108
  ### Step 8: Edge Cases
92
109
 
@@ -94,4 +111,7 @@ Render via the `resume-output.md` template. Sections to fill:
94
111
  - **No active plans**: report "No active plans found. Start a new change with `/mvt-analyze` or run `/mvt-status` to check project state."
95
112
  - **Selected change but referenced artifacts missing**: warn "Artifact directory `{path}` not found -- task state may be stale. Verify with `/mvt-status` or run `/mvt-cleanup`."
96
113
  - **Plan exists but plan.yaml is invalid** (parse error or schema violation): warn "plan.yaml is corrupted or invalid. Run `/mvt-plan-dev` to regenerate, or `/mvt-status` to inspect."
97
- - **Stale task warning**: If plan's `current_task` has status `in_progress` but the plan's `updated_at` is more than 5 days old, append a notice: "Current task has been in_progress for {N} days without updates. Consider running `/mvt-update-plan` to refresh status."
114
+ - **Stale task warning**: If plan's `current_tasks` entries reference tasks with status `in_progress` but the plan's `updated_at` is more than 5 days old, append a notice: "Current task has been in_progress for {N} days without updates. Consider running `/mvt-update-plan` to refresh status."
115
+ - **Stale deliverables warning**: If any task has `deliverables.freshness == "stale"`, warn: "Task(s) {ids} have stale deliverables. Downstream tasks may reference outdated contracts. Run `/mvt-implement` to refresh."
116
+ - **Epic-pending but epic.yaml missing**: warn "Epic state references `epic_path` but file not found at `{path}`. Run `/mvt-status` to inspect or `/mvt-cleanup` to archive stale entries."
117
+ - **Epic-pending but current_change empty or invalid**: warn "Epic `current_change` is empty or points to a non-existent child. Run `/mvt-status` to inspect the epic state."
@@ -30,8 +30,8 @@ sections:
30
30
  - rule: "Exactly one in_progress plan found -> Auto-select it and proceed"
31
31
  - rule: "No plans found -> Report no active plans, suggest `/mvt-analyze` or `/mvt-plan-dev`"
32
32
  - rule: "active_change is empty AND history is empty AND no plans -> Recommend `/mvt-init` or `/mvt-status`"
33
- - rule: "Plan exists and has current_task -> Use current_task's skill_hint as next-step recommendation"
34
- - rule: "Plan's current_task has been in_progress for >5 days -> Surface stale warning"
33
+ - rule: "Plan exists and has current_tasks -> Use current_tasks entry's skill_hint as next-step recommendation"
34
+ - rule: "Plan's current_tasks entry has been in_progress for >5 days -> Surface stale warning"
35
35
  - rule: "Last skill was interrupted -> Surface the context, suggest retry"
36
36
  boundaries:
37
37
  - scope: "read git state (branch, diff, commits)"
@@ -70,7 +70,7 @@ sections:
70
70
  current_skill: mvt-resume
71
71
  conditional_suggestions:
72
72
  conditions:
73
- - condition: "plan has current_task with skill_hint"
73
+ - condition: "plan has current_tasks entry with skill_hint"
74
74
  primary: mvt-implement
75
75
  primary_desc: "Continue with the next planned task (use skill_hint)"
76
76
  - condition: "no active plans found"