@polymorphism-tech/morph-spec 4.8.19 → 4.10.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.
Files changed (214) hide show
  1. package/CLAUDE.md +21 -0
  2. package/README.md +2 -2
  3. package/bin/morph-spec.js +44 -55
  4. package/bin/task-manager.js +133 -20
  5. package/bin/validate.js +67 -33
  6. package/claude-plugin.json +1 -1
  7. package/docs/CHEATSHEET.md +201 -203
  8. package/docs/QUICKSTART.md +2 -2
  9. package/framework/CLAUDE.md +99 -77
  10. package/framework/agents.json +734 -182
  11. package/framework/commands/commit.md +166 -0
  12. package/framework/commands/morph-apply.md +13 -2
  13. package/framework/commands/morph-archive.md +8 -2
  14. package/framework/commands/morph-infra.md +6 -0
  15. package/framework/commands/morph-preflight.md +6 -0
  16. package/framework/commands/morph-proposal.md +56 -7
  17. package/framework/commands/morph-status.md +6 -0
  18. package/framework/commands/morph-troubleshoot.md +6 -0
  19. package/framework/hooks/claude-code/notification/approval-reminder.js +3 -2
  20. package/framework/hooks/claude-code/post-tool-use/context-refresh.js +1 -1
  21. package/framework/hooks/claude-code/post-tool-use/dispatch.js +155 -32
  22. package/framework/hooks/claude-code/post-tool-use/skill-reminder.js +78 -0
  23. package/framework/hooks/claude-code/post-tool-use/validator-feedback.js +8 -17
  24. package/framework/hooks/claude-code/pre-compact/save-morph-context.js +16 -3
  25. package/framework/hooks/claude-code/pre-tool-use/enforce-phase-writes.js +4 -3
  26. package/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +4 -3
  27. package/framework/hooks/claude-code/pre-tool-use/task-tracking-guard.js +60 -0
  28. package/framework/hooks/claude-code/session-start/inject-morph-context.js +124 -2
  29. package/framework/hooks/claude-code/session-start/post-compact-restore.js +41 -0
  30. package/framework/hooks/claude-code/statusline.py +76 -30
  31. package/framework/hooks/claude-code/stop/validate-completion.js +2 -15
  32. package/framework/hooks/claude-code/user-prompt/enrich-prompt.js +23 -5
  33. package/framework/hooks/claude-code/user-prompt/set-terminal-title.js +14 -6
  34. package/framework/hooks/shared/activity-logger.js +0 -24
  35. package/framework/hooks/shared/compact-restore.js +100 -0
  36. package/framework/hooks/shared/dispatch-helpers.js +116 -0
  37. package/framework/hooks/shared/phase-utils.js +12 -5
  38. package/framework/hooks/shared/skill-reminder-helpers.js +79 -0
  39. package/framework/hooks/shared/stale-task-reset.js +57 -0
  40. package/framework/hooks/shared/state-reader.js +29 -5
  41. package/framework/hooks/shared/worktree-helpers.js +53 -0
  42. package/framework/phases.json +69 -14
  43. package/framework/rules/morph-workflow.md +88 -86
  44. package/framework/skills/level-0-meta/mcp-registry.json +86 -51
  45. package/framework/skills/level-0-meta/{brainstorming → morph-brainstorming}/SKILL.md +14 -17
  46. package/framework/skills/level-0-meta/morph-checklist/SKILL.md +2 -2
  47. package/framework/skills/level-0-meta/{code-review → morph-code-review}/SKILL.md +2 -2
  48. package/framework/skills/level-0-meta/{code-review-nextjs → morph-code-review-nextjs}/SKILL.md +163 -163
  49. package/framework/skills/level-0-meta/{frontend-review → morph-frontend-review}/SKILL.md +9 -9
  50. package/framework/skills/level-0-meta/morph-init/SKILL.md +77 -12
  51. package/framework/skills/level-0-meta/{post-implementation → morph-post-implementation}/SKILL.md +62 -15
  52. package/framework/skills/level-0-meta/morph-replicate/SKILL.md +5 -5
  53. package/framework/skills/level-0-meta/morph-replicate/references/blazor-html-mapping.md +1 -1
  54. package/framework/skills/level-0-meta/{simulation-checklist → morph-simulation-checklist}/SKILL.md +1 -1
  55. package/framework/skills/level-0-meta/{terminal-title → morph-terminal-title}/SKILL.md +2 -2
  56. package/framework/skills/level-0-meta/{tool-usage-guide → morph-tool-usage-guide}/SKILL.md +3 -4
  57. package/framework/skills/level-0-meta/{tool-usage-guide → morph-tool-usage-guide}/references/tools-per-phase.md +7 -7
  58. package/framework/skills/level-0-meta/{verification-before-completion → morph-verification-before-completion}/SKILL.md +2 -2
  59. package/framework/skills/level-0-meta/{verification-before-completion → morph-verification-before-completion}/scripts/check-phase-outputs.mjs +2 -2
  60. package/framework/skills/level-1-workflows/morph-phase-clarify/SKILL.md +238 -0
  61. package/framework/skills/level-1-workflows/{phase-codebase-analysis → morph-phase-codebase-analysis}/SKILL.md +3 -3
  62. package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +507 -0
  63. package/framework/skills/level-1-workflows/{phase-implement → morph-phase-implement}/SKILL.md +168 -27
  64. package/framework/skills/level-1-workflows/morph-phase-implement/prompts/code-quality-reviewer-prompt.md +50 -0
  65. package/framework/skills/level-1-workflows/morph-phase-implement/prompts/implementer-prompt.md +45 -0
  66. package/framework/skills/level-1-workflows/morph-phase-implement/prompts/spec-reviewer-prompt.md +47 -0
  67. package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +254 -0
  68. package/framework/skills/level-1-workflows/{phase-setup → morph-phase-setup}/SKILL.md +50 -3
  69. package/framework/skills/level-1-workflows/{phase-tasks → morph-phase-tasks}/SKILL.md +48 -11
  70. package/framework/skills/level-1-workflows/{phase-tasks → morph-phase-tasks}/scripts/validate-tasks.mjs +3 -3
  71. package/framework/skills/level-1-workflows/{phase-uiux → morph-phase-uiux}/SKILL.md +46 -11
  72. package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +97 -0
  73. package/framework/standards/STANDARDS.json +640 -88
  74. package/framework/standards/infrastructure/vercel/vercel-database.md +106 -0
  75. package/framework/standards/integration/mcp/mcp-tools.md +25 -7
  76. package/framework/templates/REGISTRY.json +1825 -1909
  77. package/framework/templates/context/CONTEXT-FEATURE.md +276 -276
  78. package/framework/templates/docs/onboarding.md +3 -7
  79. package/package.json +2 -7
  80. package/src/commands/agents/dispatch-agents.js +104 -6
  81. package/src/commands/mcp/mcp-setup.js +39 -2
  82. package/src/commands/phase/phase-reset.js +74 -0
  83. package/src/commands/project/doctor.js +34 -51
  84. package/src/commands/project/init.js +1 -1
  85. package/src/commands/project/status.js +2 -2
  86. package/src/commands/project/update.js +381 -365
  87. package/src/commands/project/worktree.js +154 -0
  88. package/src/commands/scope/escalate.js +215 -0
  89. package/src/commands/state/advance-phase.js +132 -68
  90. package/src/commands/state/approve.js +2 -2
  91. package/src/commands/state/index.js +7 -8
  92. package/src/commands/state/phase-runner.js +1 -1
  93. package/src/commands/state/state.js +61 -6
  94. package/src/commands/task/expand.js +100 -0
  95. package/src/commands/tasks/task.js +78 -99
  96. package/src/commands/templates/template-render.js +93 -173
  97. package/src/commands/trust/trust.js +26 -21
  98. package/src/core/paths/output-schema.js +19 -3
  99. package/src/core/state/phase-state-machine.js +7 -4
  100. package/src/core/state/state-manager.js +32 -57
  101. package/src/core/workflows/workflow-detector.js +9 -87
  102. package/src/lib/detectors/claude-config-detector.js +93 -347
  103. package/src/lib/detectors/design-system-detector.js +189 -189
  104. package/src/lib/detectors/index.js +155 -57
  105. package/src/lib/generators/context-generator.js +2 -2
  106. package/src/lib/installers/mcp-installer.js +37 -5
  107. package/src/lib/phase-chain/phase-validator.js +336 -0
  108. package/src/lib/scope/impact-analyzer.js +106 -0
  109. package/src/lib/stack/stack-profile.js +88 -0
  110. package/src/lib/tasks/task-classifier.js +16 -0
  111. package/src/lib/tasks/task-parser.js +1 -1
  112. package/src/lib/tasks/test-runner.js +77 -0
  113. package/src/lib/trust/trust-manager.js +32 -144
  114. package/src/lib/validators/shared/emit-validator-dispatch.js +64 -0
  115. package/src/lib/validators/spec-validator.js +58 -4
  116. package/src/lib/validators/validation-runner.js +23 -11
  117. package/src/scripts/setup-infra.js +255 -224
  118. package/src/utils/agents-installer.js +34 -14
  119. package/src/utils/banner.js +1 -1
  120. package/src/utils/claude-settings-manager.js +1 -1
  121. package/src/utils/file-copier.js +1 -1
  122. package/src/utils/hooks-installer.js +272 -8
  123. package/framework/hooks/dev/check-sync-health.js +0 -117
  124. package/framework/hooks/dev/guard-version-numbers.js +0 -57
  125. package/framework/hooks/dev/sync-standards-registry.js +0 -60
  126. package/framework/hooks/dev/sync-template-registry.js +0 -60
  127. package/framework/hooks/dev/validate-skill-format.js +0 -70
  128. package/framework/hooks/dev/validate-standard-format.js +0 -73
  129. package/framework/skills/level-1-workflows/phase-clarify/SKILL.md +0 -190
  130. package/framework/skills/level-1-workflows/phase-design/SKILL.md +0 -366
  131. package/framework/templates/meta-prompts/hops/hop-retry.md +0 -78
  132. package/framework/templates/meta-prompts/hops/hop-validation.md +0 -97
  133. package/framework/templates/meta-prompts/hops/hop-wrapper.md +0 -36
  134. package/framework/workflows/configs/design-impl.json +0 -49
  135. package/framework/workflows/configs/express.json +0 -45
  136. package/framework/workflows/configs/fast-track.json +0 -42
  137. package/framework/workflows/configs/full-morph.json +0 -79
  138. package/framework/workflows/configs/fusion.json +0 -39
  139. package/framework/workflows/configs/long-running.json +0 -33
  140. package/framework/workflows/configs/spec-only.json +0 -43
  141. package/framework/workflows/configs/ui-refresh.json +0 -49
  142. package/framework/workflows/configs/zero-touch.json +0 -82
  143. package/src/commands/project/index.js +0 -8
  144. package/src/commands/project/monitor.js +0 -295
  145. package/src/commands/project/tutorial.js +0 -115
  146. package/src/commands/state/validate-phase.js +0 -238
  147. package/src/commands/templates/generate-contracts.js +0 -445
  148. package/src/core/index.js +0 -10
  149. package/src/core/orchestrator.js +0 -171
  150. package/src/core/registry/command-registry.js +0 -28
  151. package/src/core/registry/index.js +0 -8
  152. package/src/core/registry/validator-registry.js +0 -204
  153. package/src/core/state/index.js +0 -8
  154. package/src/core/templates/index.js +0 -9
  155. package/src/core/templates/template-data-sources.js +0 -325
  156. package/src/core/templates/template-validator.js +0 -296
  157. package/src/core/workflows/index.js +0 -7
  158. package/src/generator/config-generator.js +0 -206
  159. package/src/generator/templates/config.json.template +0 -40
  160. package/src/generator/templates/project.md.template +0 -67
  161. package/src/lib/agents/micro-agent-factory.js +0 -161
  162. package/src/lib/analysis/complexity-analyzer.js +0 -441
  163. package/src/lib/analysis/index.js +0 -7
  164. package/src/lib/analytics/analytics-engine.js +0 -345
  165. package/src/lib/checkpoints/checkpoint-hooks.js +0 -298
  166. package/src/lib/checkpoints/index.js +0 -7
  167. package/src/lib/context/context-bundler.js +0 -241
  168. package/src/lib/context/context-optimizer.js +0 -212
  169. package/src/lib/context/context-tracker.js +0 -273
  170. package/src/lib/context/core-four-tracker.js +0 -201
  171. package/src/lib/context/mcp-optimizer.js +0 -200
  172. package/src/lib/detectors/config-detector.js +0 -223
  173. package/src/lib/detectors/standards-generator.js +0 -335
  174. package/src/lib/detectors/structure-detector.js +0 -275
  175. package/src/lib/execution/fusion-executor.js +0 -304
  176. package/src/lib/execution/parallel-executor.js +0 -270
  177. package/src/lib/hooks/stop-hook-executor.js +0 -286
  178. package/src/lib/hops/hop-composer.js +0 -221
  179. package/src/lib/monitor/agent-resolver.js +0 -144
  180. package/src/lib/monitor/renderer.js +0 -230
  181. package/src/lib/orchestration/index.js +0 -7
  182. package/src/lib/orchestration/team-orchestrator.js +0 -404
  183. package/src/lib/phase-chain/eligibility-checker.js +0 -243
  184. package/src/lib/threads/thread-coordinator.js +0 -238
  185. package/src/lib/threads/thread-manager.js +0 -317
  186. package/src/lib/tracking/artifact-trail.js +0 -202
  187. package/src/sanitizer/context-sanitizer.js +0 -221
  188. package/src/sanitizer/patterns.js +0 -163
  189. package/src/scanner/project-scanner.js +0 -242
  190. package/src/ui/diff-display.js +0 -91
  191. package/src/ui/interactive-wizard.js +0 -96
  192. package/src/ui/user-review.js +0 -211
  193. package/src/ui/wizard-questions.js +0 -188
  194. package/src/utils/color-utils.js +0 -70
  195. package/src/utils/process-handler.js +0 -97
  196. package/src/writer/file-writer.js +0 -86
  197. /package/framework/skills/level-0-meta/{brainstorming → morph-brainstorming}/references/proposal-example.md +0 -0
  198. /package/framework/skills/level-0-meta/{code-review → morph-code-review}/references/review-example.md +0 -0
  199. /package/framework/skills/level-0-meta/{code-review → morph-code-review}/references/review-guidelines.md +0 -0
  200. /package/framework/skills/level-0-meta/{code-review → morph-code-review}/scripts/scan-csharp.mjs +0 -0
  201. /package/framework/skills/level-0-meta/{code-review-nextjs → morph-code-review-nextjs}/references/review-example-nextjs.md +0 -0
  202. /package/framework/skills/level-0-meta/{code-review-nextjs → morph-code-review-nextjs}/scripts/scan-nextjs.mjs +0 -0
  203. /package/framework/skills/level-0-meta/{frontend-review → morph-frontend-review}/scripts/scan-accessibility.mjs +0 -0
  204. /package/framework/skills/level-0-meta/{post-implementation → morph-post-implementation}/scripts/detect-dev-server.mjs +0 -0
  205. /package/framework/skills/level-0-meta/{post-implementation → morph-post-implementation}/scripts/detect-stack.mjs +0 -0
  206. /package/framework/skills/level-0-meta/{terminal-title → morph-terminal-title}/scripts/set_title.sh +0 -0
  207. /package/framework/skills/level-1-workflows/{phase-clarify → morph-phase-clarify}/references/clarifications-example.md +0 -0
  208. /package/framework/skills/level-1-workflows/{phase-design → morph-phase-design}/references/architecture-analysis-guide.md +0 -0
  209. /package/framework/skills/level-1-workflows/{phase-design → morph-phase-design}/references/spec-authoring-guide.md +0 -0
  210. /package/framework/skills/level-1-workflows/{phase-design → morph-phase-design}/references/spec-example.md +0 -0
  211. /package/framework/skills/level-1-workflows/{phase-implement → morph-phase-implement}/references/recap-example.md +0 -0
  212. /package/framework/skills/level-1-workflows/{phase-implement → morph-phase-implement}/references/vsa-implementation-guide.md +0 -0
  213. /package/framework/skills/level-1-workflows/{phase-tasks → morph-phase-tasks}/references/task-planning-patterns.md +0 -0
  214. /package/framework/skills/level-1-workflows/{phase-tasks → morph-phase-tasks}/references/tasks-example.md +0 -0
@@ -1,241 +0,0 @@
1
- /**
2
- * Context Bundler — Checkpoint compression (180K → 15K)
3
- *
4
- * Compresses checkpoint state into a compact bundle for session resumption.
5
- * Saves bundles to .morph/bundles/{bundleId}.json
6
- *
7
- * A bundle contains:
8
- * - decisions[]: key architectural decisions made
9
- * - artifacts[]: paths to important generated files
10
- * - nextSteps[]: what to implement next
11
- * - metadata: original vs bundled token counts
12
- */
13
-
14
- import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from 'fs';
15
- import { join } from 'path';
16
- import { getOutputPath } from '../../core/paths/output-schema.js';
17
- import { randomUUID } from 'crypto';
18
-
19
- const BUNDLES_DIR = join(process.cwd(), '.morph/bundles');
20
-
21
- // ============================================================================
22
- // Bundle Creation
23
- // ============================================================================
24
-
25
- /**
26
- * Create a context bundle from checkpoint data
27
- * @param {Object} opts
28
- * @param {string} opts.feature - Feature name
29
- * @param {number} opts.checkpointNum - Checkpoint number this bundle captures
30
- * @param {Array} opts.decisions - Key decisions made: [{ id, title, summary }]
31
- * @param {Array} opts.artifacts - Important file paths: [{ path, description }]
32
- * @param {Array} opts.nextSteps - Next tasks to implement: [string]
33
- * @param {number} [opts.originalTokens=180000] - Estimated original context size
34
- * @param {Object} [opts.meta] - Additional metadata
35
- * @returns {Object} Bundle object with ID
36
- */
37
- export function createBundle({
38
- feature,
39
- checkpointNum,
40
- decisions = [],
41
- artifacts = [],
42
- nextSteps = [],
43
- originalTokens = 180000,
44
- meta = {}
45
- }) {
46
- const bundleId = `${feature}-cp${checkpointNum}-${randomUUID().substring(0, 8)}`;
47
- const now = new Date().toISOString();
48
-
49
- // Estimate bundle size (decisions + artifacts + nextSteps summary)
50
- const bundledContent = JSON.stringify({ decisions, artifacts, nextSteps, meta });
51
- const bundledTokens = Math.round(bundledContent.length / 4); // ~4 chars/token
52
-
53
- const bundle = {
54
- bundleId,
55
- feature,
56
- checkpointNum,
57
- createdAt: now,
58
- decisions,
59
- artifacts,
60
- nextSteps,
61
- meta,
62
- tokenMetrics: {
63
- originalTokens,
64
- bundledTokens,
65
- compressionRatio: Math.round(originalTokens / Math.max(bundledTokens, 1)),
66
- savingsTokens: originalTokens - bundledTokens
67
- },
68
- resumeInstructions: buildResumeInstructions(feature, checkpointNum, decisions, nextSteps)
69
- };
70
-
71
- return bundle;
72
- }
73
-
74
- /**
75
- * Save a bundle to disk
76
- * @param {Object} bundle - Bundle object (from createBundle)
77
- * @returns {string} Path to saved bundle file
78
- */
79
- export function saveBundle(bundle) {
80
- if (!existsSync(BUNDLES_DIR)) {
81
- mkdirSync(BUNDLES_DIR, { recursive: true });
82
- }
83
-
84
- const filePath = join(BUNDLES_DIR, `${bundle.bundleId}.json`);
85
- writeFileSync(filePath, JSON.stringify(bundle, null, 2), 'utf8');
86
-
87
- // Also update feature state with bundle reference
88
- try {
89
- const statePath = join(process.cwd(), '.morph/state.json');
90
- if (existsSync(statePath)) {
91
- const state = JSON.parse(readFileSync(statePath, 'utf8'));
92
- if (state.features?.[bundle.feature]) {
93
- state.features[bundle.feature].contextBundles = state.features[bundle.feature].contextBundles || [];
94
- state.features[bundle.feature].contextBundles.push({
95
- bundleId: bundle.bundleId,
96
- checkpointNum: bundle.checkpointNum,
97
- createdAt: bundle.createdAt,
98
- originalTokens: bundle.tokenMetrics.originalTokens,
99
- bundledTokens: bundle.tokenMetrics.bundledTokens,
100
- path: filePath
101
- });
102
- state.metadata = state.metadata || {};
103
- state.metadata.lastUpdated = new Date().toISOString();
104
- writeFileSync(statePath, JSON.stringify(state, null, 2), 'utf8');
105
- }
106
- }
107
- } catch {
108
- // Non-fatal if state update fails
109
- }
110
-
111
- return filePath;
112
- }
113
-
114
- /**
115
- * Load a bundle from disk
116
- * @param {string} bundleId - Bundle ID
117
- * @returns {Object|null} Bundle object or null if not found
118
- */
119
- export function loadBundle(bundleId) {
120
- const filePath = join(BUNDLES_DIR, `${bundleId}.json`);
121
-
122
- if (!existsSync(filePath)) {
123
- return null;
124
- }
125
-
126
- try {
127
- return JSON.parse(readFileSync(filePath, 'utf8'));
128
- } catch {
129
- return null;
130
- }
131
- }
132
-
133
- /**
134
- * List all bundles, optionally filtered by feature
135
- * @param {string} [feature] - Filter by feature name
136
- * @returns {Array} Array of bundle summaries
137
- */
138
- export function listBundles(feature = null) {
139
- if (!existsSync(BUNDLES_DIR)) return [];
140
-
141
- const files = readdirSync(BUNDLES_DIR).filter(f => f.endsWith('.json'));
142
- const bundles = [];
143
-
144
- for (const file of files) {
145
- try {
146
- const bundle = JSON.parse(readFileSync(join(BUNDLES_DIR, file), 'utf8'));
147
- if (!feature || bundle.feature === feature) {
148
- bundles.push({
149
- bundleId: bundle.bundleId,
150
- feature: bundle.feature,
151
- checkpointNum: bundle.checkpointNum,
152
- createdAt: bundle.createdAt,
153
- originalTokens: bundle.tokenMetrics?.originalTokens,
154
- bundledTokens: bundle.tokenMetrics?.bundledTokens,
155
- compressionRatio: bundle.tokenMetrics?.compressionRatio,
156
- nextStepsCount: bundle.nextSteps?.length || 0
157
- });
158
- }
159
- } catch {
160
- // Skip malformed files
161
- }
162
- }
163
-
164
- return bundles.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
165
- }
166
-
167
- /**
168
- * Get the latest bundle for a feature at or before a checkpoint number
169
- * @param {string} feature - Feature name
170
- * @param {number} [checkpointNum] - Target checkpoint (latest if not specified)
171
- * @returns {Object|null} Bundle or null
172
- */
173
- export function getLatestBundle(feature, checkpointNum = Infinity) {
174
- const bundles = listBundles(feature)
175
- .filter(b => b.checkpointNum <= checkpointNum)
176
- .sort((a, b) => b.checkpointNum - a.checkpointNum);
177
-
178
- if (bundles.length === 0) return null;
179
- return loadBundle(bundles[0].bundleId);
180
- }
181
-
182
- // ============================================================================
183
- // Session Replay
184
- // ============================================================================
185
-
186
- /**
187
- * Generate minimal context for session replay from a bundle
188
- * @param {Object} bundle - Bundle object
189
- * @returns {string} Compact context string (~15K tokens) for session resumption
190
- */
191
- export function generateResumeContext(bundle) {
192
- const lines = [];
193
- lines.push(`# Session Resume — ${bundle.feature} @ Checkpoint ${bundle.checkpointNum}`);
194
- lines.push(`> Bundle ID: ${bundle.bundleId} | Created: ${bundle.createdAt}`);
195
- lines.push(`> Context compression: ${bundle.tokenMetrics?.originalTokens?.toLocaleString()} → ${bundle.tokenMetrics?.bundledTokens?.toLocaleString()} tokens`);
196
- lines.push('');
197
-
198
- if (bundle.decisions?.length > 0) {
199
- lines.push('## Key Decisions Made');
200
- for (const d of bundle.decisions) {
201
- lines.push(`- **${d.id || ''}${d.id ? ':' : ''} ${d.title}** — ${d.summary}`);
202
- if (d.fullPath) lines.push(` *(Full: ${d.fullPath})*`);
203
- }
204
- lines.push('');
205
- }
206
-
207
- if (bundle.artifacts?.length > 0) {
208
- lines.push('## Created Artifacts');
209
- for (const a of bundle.artifacts) {
210
- lines.push(`- \`${a.path}\` — ${a.description || ''}`);
211
- }
212
- lines.push('');
213
- }
214
-
215
- if (bundle.nextSteps?.length > 0) {
216
- lines.push('## Next Steps (continue from here)');
217
- bundle.nextSteps.forEach((step, i) => {
218
- lines.push(`${i + 1}. ${step}`);
219
- });
220
- lines.push('');
221
- }
222
-
223
- lines.push(bundle.resumeInstructions || '');
224
-
225
- return lines.join('\n');
226
- }
227
-
228
- // ============================================================================
229
- // Helpers
230
- // ============================================================================
231
-
232
- function buildResumeInstructions(feature, checkpointNum, decisions, nextSteps) {
233
- return `## Resume Instructions
234
-
235
- 1. Load minimal standards: run \`morph-spec prime feature\`
236
- 2. Read spec: \`${getOutputPath(feature, 'spec')}\` (key sections only)
237
- 3. Check tasks: \`morph-spec state get ${feature}\`
238
- 4. Continue from: ${nextSteps[0] || `task after checkpoint ${checkpointNum}`}
239
-
240
- > This bundle was created at checkpoint ${checkpointNum}. All decisions above are final.`;
241
- }
@@ -1,212 +0,0 @@
1
- /**
2
- * Context Optimizer — Selective context loading strategy
3
- *
4
- * Provides intelligent recommendations for reducing context window usage:
5
- * - selectStandards: pick only relevant standards for a feature type
6
- * - selectTemplates: pick only relevant templates
7
- * - suggestOptimizations: compare current vs optimal context, return savings
8
- *
9
- * Connects to standards resolver and template registry.
10
- */
11
-
12
- import { readFileSync, existsSync } from 'fs';
13
- import { join } from 'path';
14
-
15
- const STANDARDS_DIR = join(process.cwd(), 'framework/standards');
16
- const TEMPLATES_REGISTRY = join(process.cwd(), 'framework/templates/REGISTRY.json');
17
-
18
- // Average token cost estimates per file type
19
- const TOKEN_ESTIMATES = {
20
- standard_file: 2000,
21
- template_file: 1500,
22
- claude_md: 23000,
23
- spec_file: 8000,
24
- decisions_file: 3000
25
- };
26
-
27
- // Feature type → relevant standards mapping
28
- const STANDARDS_BY_FEATURE_TYPE = {
29
- backend: [
30
- 'coding.md', 'architecture.md', 'dotnet10-compatibility.md',
31
- 'integration/api/rest-design.md'
32
- ],
33
- frontend: [
34
- 'coding.md', 'blazor-components.md', 'blazor-state.md',
35
- 'css-architecture.md', 'css-design-system.md'
36
- ],
37
- database: [
38
- 'coding.md', 'ef-core.md', 'architecture.md'
39
- ],
40
- infrastructure: [
41
- 'azure.md', 'bicep.md', 'devops.md'
42
- ],
43
- authentication: [
44
- 'coding.md', 'architecture.md', 'dotnet10-compatibility.md',
45
- 'integration/api/rest-design.md'
46
- ],
47
- fullstack: [
48
- 'coding.md', 'architecture.md', 'blazor-components.md',
49
- 'ef-core.md', 'dotnet10-compatibility.md'
50
- ],
51
- observability: [
52
- 'observability/monitoring.md', 'observability/logging.md',
53
- 'observability/tracing.md', 'observability/metrics.md'
54
- ],
55
- event_driven: [
56
- 'integration/event-driven/service-bus.md',
57
- 'integration/event-driven/cqrs.md'
58
- ]
59
- };
60
-
61
- // ============================================================================
62
- // Standards Selection
63
- // ============================================================================
64
-
65
- /**
66
- * Select minimal relevant standards for a given feature type
67
- * @param {string} featureType - Feature type keyword
68
- * @param {Object} [opts]
69
- * @param {string[]} [opts.extraKeywords] - Additional keywords for selection
70
- * @returns {Object} { selected: string[], skipped: string[], estimatedTokens: number }
71
- */
72
- export function selectStandards(featureType, { extraKeywords = [] } = {}) {
73
- const typeKey = detectFeatureCategory(featureType, extraKeywords);
74
- const selected = STANDARDS_BY_FEATURE_TYPE[typeKey] || STANDARDS_BY_FEATURE_TYPE.fullstack;
75
-
76
- // Check which selected files actually exist
77
- const existing = selected.filter(f => {
78
- const fullPath = join(STANDARDS_DIR, f);
79
- return existsSync(fullPath);
80
- });
81
-
82
- // Estimate all standard files count for skipped calculation
83
- const allStandards = getAllStandardsCount();
84
- const skippedCount = allStandards - existing.length;
85
-
86
- return {
87
- selected: existing,
88
- skipped: skippedCount,
89
- featureType: typeKey,
90
- estimatedTokens: existing.length * TOKEN_ESTIMATES.standard_file,
91
- fullLoadTokens: allStandards * TOKEN_ESTIMATES.standard_file,
92
- savings: skippedCount * TOKEN_ESTIMATES.standard_file
93
- };
94
- }
95
-
96
- /**
97
- * Select relevant templates for a feature type
98
- * @param {string} featureType - Feature type keyword
99
- * @returns {Object} { selected: string[], estimatedTokens: number }
100
- */
101
- export function selectTemplates(featureType) {
102
- const TEMPLATES_BY_TYPE = {
103
- backend: ['dotnet-backend-service', 'dotnet-repository', 'dotnet-api-contracts'],
104
- frontend: ['dotnet-blazor-component', 'dotnet-design-system'],
105
- database: ['dotnet-migration', 'sql-migration'],
106
- infrastructure: ['azure-container-app', 'azure-key-vault', 'azure-main-bicep'],
107
- fullstack: ['dotnet-backend-service', 'dotnet-blazor-component', 'dotnet-migration']
108
- };
109
-
110
- const typeKey = detectFeatureCategory(featureType, []);
111
- const selected = TEMPLATES_BY_TYPE[typeKey] || TEMPLATES_BY_TYPE.fullstack;
112
-
113
- // Load registry to get full template count
114
- let totalTemplates = 50;
115
- try {
116
- const registry = JSON.parse(readFileSync(TEMPLATES_REGISTRY, 'utf8'));
117
- totalTemplates = (registry.templates || []).length;
118
- } catch {
119
- // Use estimate
120
- }
121
-
122
- return {
123
- selected,
124
- skipped: totalTemplates - selected.length,
125
- estimatedTokens: selected.length * TOKEN_ESTIMATES.template_file,
126
- fullLoadTokens: totalTemplates * TOKEN_ESTIMATES.template_file,
127
- savings: (totalTemplates - selected.length) * TOKEN_ESTIMATES.template_file
128
- };
129
- }
130
-
131
- /**
132
- * Suggest context optimizations based on current vs optimal load
133
- * @param {Object} current - Current context state
134
- * @param {number} current.totalTokens - Current token count
135
- * @param {number} current.standardsCount - Number of standards currently loaded
136
- * @param {number} current.templatesCount - Number of templates currently loaded
137
- * @param {string} featureType - Feature type for optimal selection
138
- * @returns {Object} Optimization suggestions with savings estimates
139
- */
140
- export function suggestOptimizations(current, featureType) {
141
- const optimalStandards = selectStandards(featureType);
142
- const optimalTemplates = selectTemplates(featureType);
143
- const suggestions = [];
144
-
145
- // Claude.md optimization
146
- if (current.totalTokens > 50000) {
147
- suggestions.push({
148
- type: 'priming_file',
149
- title: 'Use priming file instead of full CLAUDE.md',
150
- description: 'Replace 23K token CLAUDE.md with a 500-token priming file',
151
- savings: TOKEN_ESTIMATES.claude_md - 500,
152
- priority: 'high',
153
- command: 'morph-spec prime feature'
154
- });
155
- }
156
-
157
- // Standards optimization
158
- if (current.standardsCount > optimalStandards.selected.length + 3) {
159
- suggestions.push({
160
- type: 'standards_subset',
161
- title: `Load only ${optimalStandards.selected.length} relevant standards`,
162
- description: `Currently loading ${current.standardsCount} standards. Only ${optimalStandards.selected.length} are needed for ${featureType} features.`,
163
- savings: optimalStandards.savings,
164
- priority: 'medium',
165
- selectedStandards: optimalStandards.selected
166
- });
167
- }
168
-
169
- // Context bundle for large sessions
170
- if (current.totalTokens > 100000) {
171
- suggestions.push({
172
- type: 'context_bundle',
173
- title: 'Create context bundle checkpoint',
174
- description: 'Compress current context (180K → ~15K tokens) for session resume',
175
- savings: current.totalTokens - 15000,
176
- priority: 'critical',
177
- command: 'morph-spec bundle create'
178
- });
179
- }
180
-
181
- const totalSavings = suggestions.reduce((sum, s) => sum + s.savings, 0);
182
- const optimizedTokens = Math.max(current.totalTokens - totalSavings, 5000);
183
-
184
- return {
185
- currentTokens: current.totalTokens,
186
- optimizedTokens,
187
- totalSavings,
188
- savingsPercent: Math.round(totalSavings / current.totalTokens * 100),
189
- suggestions: suggestions.sort((a, b) => b.savings - a.savings)
190
- };
191
- }
192
-
193
- // ============================================================================
194
- // Helpers
195
- // ============================================================================
196
-
197
- function detectFeatureCategory(featureType, extraKeywords) {
198
- const text = (featureType + ' ' + extraKeywords.join(' ')).toLowerCase();
199
-
200
- if (/auth|login|jwt|oauth|identity/.test(text)) return 'authentication';
201
- if (/blazor|frontend|ui|component|razor/.test(text)) return 'frontend';
202
- if (/migration|ef.core|database|entity/.test(text)) return 'database';
203
- if (/bicep|azure|infra|container|devops/.test(text)) return 'infrastructure';
204
- if (/service.bus|cqrs|event.sourcing|pub.sub/.test(text)) return 'event_driven';
205
- if (/monitor|logging|trace|metric|appinsight/.test(text)) return 'observability';
206
- if (/api|endpoint|controller|rest/.test(text)) return 'backend';
207
- return 'fullstack';
208
- }
209
-
210
- function getAllStandardsCount() {
211
- return 30; // Known approximate count
212
- }