codymaster 4.4.4 → 4.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/README.md +29 -14
- package/commands/demo.md +1 -1
- package/dist/context-bus.js +70 -0
- package/dist/context-db.js +265 -0
- package/dist/continuity.js +12 -0
- package/dist/file-watcher.js +79 -0
- package/dist/index.js +152 -1
- package/dist/l0-indexer.js +158 -0
- package/dist/mcp-context-server.js +400 -0
- package/dist/migrate-json-to-sqlite.js +126 -0
- package/dist/skill-chain.js +19 -3
- package/dist/token-budget.js +108 -0
- package/dist/uri-resolver.js +203 -0
- package/package.json +7 -1
- package/skills/_shared/helpers.md +50 -14
- package/skills/cm-autopilot/SKILL.md +29 -0
- package/skills/cm-autopilot/scripts/autopilot.py +190 -0
- package/skills/cm-continuity/SKILL.md +90 -28
- package/skills/cm-quality-gate/SKILL.md +11 -1
- package/skills/cm-safe-deploy/SKILL.md +38 -2
- package/skills/cm-security-gate/SKILL.md +158 -34
- package/skills/cm-skill-chain/SKILL.md +47 -1
- package/skills/cm-start/SKILL.md +11 -2
- package/skills/cm-test-gate/SKILL.md +3 -0
- package/skills/boxme-git-config/SKILL.md +0 -56
- package/skills/boxme-local-dev/SKILL.md +0 -66
- package/skills/jobs-to-be-done/SKILL.md +0 -266
- package/skills/jobs-to-be-done/references/case-studies.md +0 -154
- package/skills/jobs-to-be-done/references/competitive-strategy.md +0 -280
- package/skills/jobs-to-be-done/references/diagnostics.md +0 -158
- package/skills/jobs-to-be-done/references/innovation-process.md +0 -392
- package/skills/jobs-to-be-done/references/organizational-change.md +0 -328
- package/skills/marketplace-report-crawler/SKILL.md +0 -176
- package/skills/marketplace-report-crawler/config/accounts.json +0 -41
- package/skills/marketplace-report-crawler/config/report-types.json +0 -422
- package/skills/marketplace-report-crawler/config/sessions.json +0 -3
- package/skills/marketplace-report-crawler/scripts/ab-wrapper.sh +0 -102
- package/skills/marketplace-report-crawler/scripts/browser-actions/lazada/lazada-actions.js +0 -114
- package/skills/marketplace-report-crawler/scripts/browser-actions/shopee/shopee-actions.js +0 -94
- package/skills/marketplace-report-crawler/scripts/browser-actions/tiktok/tiktok-actions.js +0 -272
- package/skills/marketplace-report-crawler/scripts/crawl-runner.js +0 -281
- package/skills/marketplace-report-crawler/scripts/session-check.sh +0 -72
- package/skills/marketplace-report-crawler/scripts/session-manager.sh +0 -349
- package/skills/marketplace-report-crawler/scripts/setup-folders.sh +0 -83
- package/skills/medical-research/SKILL.md +0 -194
- package/skills/medical-research/scripts/evidence_checker.py +0 -288
- package/skills/mom-test/SKILL.md +0 -267
- package/skills/mom-test/references/avoiding-bad-data.md +0 -221
- package/skills/mom-test/references/case-studies.md +0 -306
- package/skills/mom-test/references/commitment-advancement.md +0 -219
- package/skills/mom-test/references/finding-conversations.md +0 -251
- package/skills/mom-test/references/processing-learning.md +0 -256
- package/skills/mom-test/references/question-patterns.md +0 -198
- package/skills/pandasai-analytics/SKILL.md +0 -251
- package/skills/release-it/SKILL.md +0 -235
- package/skills/release-it/references/anti-patterns.md +0 -279
- package/skills/release-it/references/capacity-planning.md +0 -285
- package/skills/release-it/references/chaos-engineering.md +0 -325
- package/skills/release-it/references/deployment-strategies.md +0 -331
- package/skills/release-it/references/observability.md +0 -301
- package/skills/release-it/references/stability-patterns.md +0 -355
- package/skills/skill-creator-ultra/.agents/workflows/skill-audit.md +0 -37
- package/skills/skill-creator-ultra/.agents/workflows/skill-compare.md +0 -34
- package/skills/skill-creator-ultra/.agents/workflows/skill-export.md +0 -51
- package/skills/skill-creator-ultra/.agents/workflows/skill-generate.md +0 -39
- package/skills/skill-creator-ultra/.agents/workflows/skill-scaffold.md +0 -52
- package/skills/skill-creator-ultra/.agents/workflows/skill-simulate.md +0 -25
- package/skills/skill-creator-ultra/.agents/workflows/skill-stats.md +0 -31
- package/skills/skill-creator-ultra/.agents/workflows/skill-validate.md +0 -25
- package/skills/skill-creator-ultra/README.md +0 -1242
- package/skills/skill-creator-ultra/SKILL.md +0 -388
- package/skills/skill-creator-ultra/agents/analyzer.md +0 -274
- package/skills/skill-creator-ultra/agents/comparator.md +0 -202
- package/skills/skill-creator-ultra/agents/grader.md +0 -223
- package/skills/skill-creator-ultra/assets/eval_review.html +0 -146
- package/skills/skill-creator-ultra/eval-viewer/generate_review.py +0 -471
- package/skills/skill-creator-ultra/eval-viewer/viewer.html +0 -1325
- package/skills/skill-creator-ultra/examples/example_anthropic_frontend.md +0 -109
- package/skills/skill-creator-ultra/examples/example_anthropic_pdf.md +0 -116
- package/skills/skill-creator-ultra/examples/example_api_docs.md +0 -189
- package/skills/skill-creator-ultra/examples/example_db_migration.md +0 -253
- package/skills/skill-creator-ultra/examples/example_git_commit.md +0 -111
- package/skills/skill-creator-ultra/install.ps1 +0 -289
- package/skills/skill-creator-ultra/install.sh +0 -313
- package/skills/skill-creator-ultra/phases/phase1_interview.md +0 -202
- package/skills/skill-creator-ultra/phases/phase2_extract.md +0 -55
- package/skills/skill-creator-ultra/phases/phase3_detect.md +0 -57
- package/skills/skill-creator-ultra/phases/phase4_generate.md +0 -543
- package/skills/skill-creator-ultra/phases/phase5_test.md +0 -319
- package/skills/skill-creator-ultra/phases/phase6_eval.md +0 -301
- package/skills/skill-creator-ultra/phases/phase7_iterate.md +0 -103
- package/skills/skill-creator-ultra/phases/phase8_optimize.md +0 -113
- package/skills/skill-creator-ultra/resources/advanced_patterns.md +0 -499
- package/skills/skill-creator-ultra/resources/anti_patterns.md +0 -376
- package/skills/skill-creator-ultra/resources/blueprints.md +0 -498
- package/skills/skill-creator-ultra/resources/checklist.md +0 -243
- package/skills/skill-creator-ultra/resources/composition_cookbook.md +0 -291
- package/skills/skill-creator-ultra/resources/description_optimization.md +0 -90
- package/skills/skill-creator-ultra/resources/eval_guide.md +0 -133
- package/skills/skill-creator-ultra/resources/industry_questions.md +0 -189
- package/skills/skill-creator-ultra/resources/interview_questions.md +0 -200
- package/skills/skill-creator-ultra/resources/pattern_detection.md +0 -200
- package/skills/skill-creator-ultra/resources/prompt_engineering.md +0 -531
- package/skills/skill-creator-ultra/resources/schemas.md +0 -430
- package/skills/skill-creator-ultra/resources/script_integration.md +0 -593
- package/skills/skill-creator-ultra/resources/scripts_guide.md +0 -339
- package/skills/skill-creator-ultra/resources/skill_template.md +0 -124
- package/skills/skill-creator-ultra/resources/skill_writing_guide.md +0 -634
- package/skills/skill-creator-ultra/resources/versioning_guide.md +0 -193
- package/skills/skill-creator-ultra/scripts/ci_eval.py +0 -200
- package/skills/skill-creator-ultra/scripts/package_skill.py +0 -165
- package/skills/skill-creator-ultra/scripts/simulate_skill.py +0 -398
- package/skills/skill-creator-ultra/scripts/skill_audit.py +0 -611
- package/skills/skill-creator-ultra/scripts/skill_compare.py +0 -265
- package/skills/skill-creator-ultra/scripts/skill_export.py +0 -334
- package/skills/skill-creator-ultra/scripts/skill_scaffold.py +0 -403
- package/skills/skill-creator-ultra/scripts/skill_stats.py +0 -339
- package/skills/skill-creator-ultra/scripts/validate_skill.py +0 -411
- package/skills/tailwind-mastery/SKILL.md +0 -229
- package/skills/vercel-react-best-practices/AGENTS.md +0 -3373
- package/skills/vercel-react-best-practices/README.md +0 -123
- package/skills/vercel-react-best-practices/SKILL.md +0 -143
- package/skills/vercel-react-best-practices/rules/_sections.md +0 -46
- package/skills/vercel-react-best-practices/rules/_template.md +0 -28
- package/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -55
- package/skills/vercel-react-best-practices/rules/advanced-init-once.md +0 -42
- package/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -39
- package/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -38
- package/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -80
- package/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -51
- package/skills/vercel-react-best-practices/rules/async-parallel.md +0 -28
- package/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -99
- package/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -59
- package/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -31
- package/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -49
- package/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -35
- package/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -50
- package/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -74
- package/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -71
- package/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -48
- package/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -56
- package/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -107
- package/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -80
- package/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -28
- package/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -70
- package/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -32
- package/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -50
- package/skills/vercel-react-best-practices/rules/js-flatmap-filter.md +0 -60
- package/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -45
- package/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -37
- package/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -49
- package/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -82
- package/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -24
- package/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -57
- package/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -26
- package/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
- package/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -40
- package/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -38
- package/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -46
- package/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
- package/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +0 -30
- package/skills/vercel-react-best-practices/rules/rendering-resource-hints.md +0 -85
- package/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +0 -68
- package/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -28
- package/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +0 -75
- package/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -39
- package/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -45
- package/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +0 -40
- package/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -29
- package/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -74
- package/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -58
- package/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +0 -38
- package/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -44
- package/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +0 -45
- package/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +0 -82
- package/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +0 -35
- package/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +0 -64
- package/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -40
- package/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +0 -59
- package/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +0 -73
- package/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -73
- package/skills/vercel-react-best-practices/rules/server-auth-actions.md +0 -96
- package/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -41
- package/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -76
- package/skills/vercel-react-best-practices/rules/server-dedup-props.md +0 -65
- package/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +0 -142
- package/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -83
- package/skills/vercel-react-best-practices/rules/server-serialization.md +0 -38
- package/skills/web-design-guidelines/SKILL.md +0 -39
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* CodyMaster MCP Context Server
|
|
5
|
+
*
|
|
6
|
+
* Exposes 7 tools over JSON-RPC 2.0 / stdio (Content-Length framing):
|
|
7
|
+
* cm_query — FTS5 search across learnings + decisions
|
|
8
|
+
* cm_resolve — resolve a cm:// URI at L0/L1/L2
|
|
9
|
+
* cm_bus_read — read context bus state
|
|
10
|
+
* cm_bus_write — publish skill output to context bus
|
|
11
|
+
* cm_budget_check — check token budget for a category
|
|
12
|
+
* cm_memory_decay — TTL cleanup for learnings
|
|
13
|
+
* cm_index_refresh — regenerate L0 indexes
|
|
14
|
+
*
|
|
15
|
+
* Usage (stdio MCP):
|
|
16
|
+
* node dist/mcp-context-server.js --project /path/to/project
|
|
17
|
+
*
|
|
18
|
+
* Claude Desktop config:
|
|
19
|
+
* {
|
|
20
|
+
* "mcpServers": {
|
|
21
|
+
* "cm-context": {
|
|
22
|
+
* "command": "node",
|
|
23
|
+
* "args": ["/path/to/dist/mcp-context-server.js", "--project", "/path/to/project"]
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
*/
|
|
28
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
29
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
30
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
31
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
32
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
33
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
34
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
38
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
39
|
+
};
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
const path_1 = __importDefault(require("path"));
|
|
42
|
+
const context_db_1 = require("./context-db");
|
|
43
|
+
const uri_resolver_1 = require("./uri-resolver");
|
|
44
|
+
const context_bus_1 = require("./context-bus");
|
|
45
|
+
const token_budget_1 = require("./token-budget");
|
|
46
|
+
const l0_indexer_1 = require("./l0-indexer");
|
|
47
|
+
// ─── Config ──────────────────────────────────────────────────────────────────
|
|
48
|
+
const SERVER_NAME = 'cm-context';
|
|
49
|
+
const SERVER_VERSION = '1.0.0';
|
|
50
|
+
function getProjectPath() {
|
|
51
|
+
const args = process.argv.slice(2);
|
|
52
|
+
const idx = args.indexOf('--project');
|
|
53
|
+
if (idx !== -1 && args[idx + 1])
|
|
54
|
+
return path_1.default.resolve(args[idx + 1]);
|
|
55
|
+
return process.env.CM_PROJECT_PATH ? path_1.default.resolve(process.env.CM_PROJECT_PATH) : process.cwd();
|
|
56
|
+
}
|
|
57
|
+
const PROJECT_PATH = getProjectPath();
|
|
58
|
+
function cmQuery(args) {
|
|
59
|
+
const { query = '', scope = 'all', filter_scope, limit = 10 } = args;
|
|
60
|
+
const dbPath = (0, context_db_1.getDbPath)(PROJECT_PATH);
|
|
61
|
+
(0, context_db_1.openDb)(dbPath);
|
|
62
|
+
const results = [];
|
|
63
|
+
if (scope === 'all' || scope === 'learnings') {
|
|
64
|
+
const learnings = (0, context_db_1.queryLearnings)(dbPath, query, filter_scope, limit);
|
|
65
|
+
for (const l of learnings) {
|
|
66
|
+
results.push(Object.assign({ type: 'learning' }, l));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (scope === 'all' || scope === 'decisions') {
|
|
70
|
+
const decisions = (0, context_db_1.queryDecisions)(dbPath, query, limit);
|
|
71
|
+
for (const d of decisions) {
|
|
72
|
+
results.push(Object.assign({ type: 'decision' }, d));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
query,
|
|
77
|
+
scope,
|
|
78
|
+
count: results.length,
|
|
79
|
+
results,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function cmResolve(args) {
|
|
83
|
+
const { uri, depth = 'L1' } = args;
|
|
84
|
+
const resolved = (0, uri_resolver_1.resolve)(uri, PROJECT_PATH, depth);
|
|
85
|
+
return {
|
|
86
|
+
uri: resolved.uri,
|
|
87
|
+
depth: resolved.depth,
|
|
88
|
+
found: resolved.found,
|
|
89
|
+
tokenEstimate: resolved.tokenEstimate,
|
|
90
|
+
content: resolved.content,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function cmBusRead() {
|
|
94
|
+
const bus = (0, context_bus_1.readBus)(PROJECT_PATH);
|
|
95
|
+
if (!bus) {
|
|
96
|
+
return { active: false, message: 'No active context bus. Start a skill chain first.' };
|
|
97
|
+
}
|
|
98
|
+
return { active: true, bus };
|
|
99
|
+
}
|
|
100
|
+
function cmBusWrite(args) {
|
|
101
|
+
const { skill, summary, affected_files, output_path, metadata } = args;
|
|
102
|
+
if (!skill)
|
|
103
|
+
throw new Error('skill is required');
|
|
104
|
+
(0, context_bus_1.updateBusStep)(PROJECT_PATH, skill, {
|
|
105
|
+
summary: summary !== null && summary !== void 0 ? summary : '',
|
|
106
|
+
output_path: output_path !== null && output_path !== void 0 ? output_path : '',
|
|
107
|
+
affected_files: affected_files !== null && affected_files !== void 0 ? affected_files : [],
|
|
108
|
+
metadata: metadata !== null && metadata !== void 0 ? metadata : {},
|
|
109
|
+
});
|
|
110
|
+
const bus = (0, context_bus_1.readBus)(PROJECT_PATH);
|
|
111
|
+
return {
|
|
112
|
+
ok: true,
|
|
113
|
+
skill,
|
|
114
|
+
current_step: bus === null || bus === void 0 ? void 0 : bus.current_step,
|
|
115
|
+
pipeline: bus === null || bus === void 0 ? void 0 : bus.pipeline,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function cmBudgetCheck(args) {
|
|
119
|
+
const { category, text, token_count } = args;
|
|
120
|
+
if (!category)
|
|
121
|
+
throw new Error('category is required');
|
|
122
|
+
const budget = (0, token_budget_1.loadBudget)(PROJECT_PATH);
|
|
123
|
+
const tokens = token_count !== null && token_count !== void 0 ? token_count : (text ? (0, token_budget_1.estimateTokens)(text) : 0);
|
|
124
|
+
const check = (0, token_budget_1.checkBudget)(budget, category, tokens);
|
|
125
|
+
return {
|
|
126
|
+
category,
|
|
127
|
+
tokens_requested: tokens,
|
|
128
|
+
allowed: check.allowed,
|
|
129
|
+
remaining: check.remaining,
|
|
130
|
+
suggestion: check.suggestion,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function cmMemoryDecay(args) {
|
|
134
|
+
const { dry_run = false } = args;
|
|
135
|
+
const dbPath = (0, context_db_1.getDbPath)(PROJECT_PATH);
|
|
136
|
+
const db = (0, context_db_1.openDb)(dbPath);
|
|
137
|
+
const now = new Date();
|
|
138
|
+
// Find learnings past TTL
|
|
139
|
+
const candidates = db.prepare(`
|
|
140
|
+
SELECT id, what_failed, created_at, ttl
|
|
141
|
+
FROM learnings
|
|
142
|
+
WHERE status = 'active'
|
|
143
|
+
AND ttl IS NOT NULL
|
|
144
|
+
AND ttl > 0
|
|
145
|
+
`).all();
|
|
146
|
+
const expired = [];
|
|
147
|
+
for (const row of candidates) {
|
|
148
|
+
const created = new Date(row.created_at);
|
|
149
|
+
const daysSince = (now.getTime() - created.getTime()) / (1000 * 60 * 60 * 24);
|
|
150
|
+
if (daysSince >= row.ttl) {
|
|
151
|
+
expired.push(row.id);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (!dry_run && expired.length > 0) {
|
|
155
|
+
const placeholders = expired.map(() => '?').join(',');
|
|
156
|
+
db.prepare(`UPDATE learnings SET status = 'archived' WHERE id IN (${placeholders})`).run(...expired);
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
dry_run,
|
|
160
|
+
expired_count: expired.length,
|
|
161
|
+
expired_ids: expired,
|
|
162
|
+
message: dry_run
|
|
163
|
+
? `${expired.length} learnings would be archived (dry run)`
|
|
164
|
+
: `${expired.length} learnings archived`,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function cmIndexRefresh(args) {
|
|
168
|
+
const { target = 'all' } = args;
|
|
169
|
+
if (target === 'all') {
|
|
170
|
+
const result = (0, l0_indexer_1.refreshAllIndexes)(PROJECT_PATH);
|
|
171
|
+
return {
|
|
172
|
+
target,
|
|
173
|
+
learnings: { generated: true, tokens: (0, token_budget_1.estimateTokens)(result.learnings) },
|
|
174
|
+
skeleton: { generated: true, tokens: (0, token_budget_1.estimateTokens)(result.skeleton) },
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
if (target === 'learnings') {
|
|
178
|
+
const { generateLearningsIndex } = require('./l0-indexer');
|
|
179
|
+
const content = generateLearningsIndex(PROJECT_PATH);
|
|
180
|
+
return { target, learnings: { generated: true, tokens: (0, token_budget_1.estimateTokens)(content) } };
|
|
181
|
+
}
|
|
182
|
+
if (target === 'skeleton') {
|
|
183
|
+
const { generateSkeletonIndex } = require('./l0-indexer');
|
|
184
|
+
const content = generateSkeletonIndex(PROJECT_PATH);
|
|
185
|
+
return { target, skeleton: { generated: true, tokens: (0, token_budget_1.estimateTokens)(content) } };
|
|
186
|
+
}
|
|
187
|
+
throw new Error(`Unknown target: ${target}. Valid: learnings, skeleton, all`);
|
|
188
|
+
}
|
|
189
|
+
// ─── Tool Registry ─────────────────────────────────────────────────────────────
|
|
190
|
+
const TOOLS = [
|
|
191
|
+
{
|
|
192
|
+
name: 'cm_query',
|
|
193
|
+
description: 'FTS5 semantic search across CodyMaster learnings and decisions stored in SQLite.',
|
|
194
|
+
inputSchema: {
|
|
195
|
+
type: 'object',
|
|
196
|
+
properties: {
|
|
197
|
+
query: { type: 'string', description: 'Search query (FTS5 syntax supported)' },
|
|
198
|
+
scope: {
|
|
199
|
+
type: 'string',
|
|
200
|
+
enum: ['learnings', 'decisions', 'all'],
|
|
201
|
+
description: 'Which collection to search (default: all)',
|
|
202
|
+
},
|
|
203
|
+
filter_scope: {
|
|
204
|
+
type: 'string',
|
|
205
|
+
description: 'Optional scope filter for learnings (e.g. "module", "global")',
|
|
206
|
+
},
|
|
207
|
+
limit: { type: 'number', description: 'Max results per collection (default: 10)' },
|
|
208
|
+
},
|
|
209
|
+
required: ['query'],
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
name: 'cm_resolve',
|
|
214
|
+
description: 'Resolve a cm:// URI to content at the specified depth (L0=compact, L1=overview, L2=full).',
|
|
215
|
+
inputSchema: {
|
|
216
|
+
type: 'object',
|
|
217
|
+
properties: {
|
|
218
|
+
uri: {
|
|
219
|
+
type: 'string',
|
|
220
|
+
description: 'cm:// URI (e.g. cm://memory/learnings, cm://skills/cm-tdd, cm://pipeline/current)',
|
|
221
|
+
},
|
|
222
|
+
depth: {
|
|
223
|
+
type: 'string',
|
|
224
|
+
enum: ['L0', 'L1', 'L2'],
|
|
225
|
+
description: 'Loading depth (default: L1)',
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
required: ['uri'],
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
name: 'cm_bus_read',
|
|
233
|
+
description: 'Read the current context bus state — pipeline name, current step, and shared skill outputs.',
|
|
234
|
+
inputSchema: { type: 'object', properties: {} },
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
name: 'cm_bus_write',
|
|
238
|
+
description: 'Publish a skill completion event to the context bus so subsequent skills can read it.',
|
|
239
|
+
inputSchema: {
|
|
240
|
+
type: 'object',
|
|
241
|
+
properties: {
|
|
242
|
+
skill: { type: 'string', description: 'Skill name (e.g. cm-brainstorm-idea)' },
|
|
243
|
+
summary: { type: 'string', description: 'Human-readable outcome summary' },
|
|
244
|
+
affected_files: {
|
|
245
|
+
type: 'array',
|
|
246
|
+
items: { type: 'string' },
|
|
247
|
+
description: 'Files created/modified by this skill',
|
|
248
|
+
},
|
|
249
|
+
output_path: { type: 'string', description: 'Primary output file path' },
|
|
250
|
+
metadata: { type: 'object', description: 'Arbitrary key-value metadata' },
|
|
251
|
+
},
|
|
252
|
+
required: ['skill'],
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
name: 'cm_budget_check',
|
|
257
|
+
description: 'Check whether loading content for a given category is within token budget.',
|
|
258
|
+
inputSchema: {
|
|
259
|
+
type: 'object',
|
|
260
|
+
properties: {
|
|
261
|
+
category: {
|
|
262
|
+
type: 'string',
|
|
263
|
+
description: 'Budget category (e.g. skill_index_L0, memory_learnings, context_retrieval)',
|
|
264
|
+
},
|
|
265
|
+
text: { type: 'string', description: 'Text to estimate tokens for (optional)' },
|
|
266
|
+
token_count: { type: 'number', description: 'Pre-computed token count (overrides text)' },
|
|
267
|
+
},
|
|
268
|
+
required: ['category'],
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
name: 'cm_memory_decay',
|
|
273
|
+
description: 'Archive learnings whose TTL has expired. Run periodically to keep the memory lean.',
|
|
274
|
+
inputSchema: {
|
|
275
|
+
type: 'object',
|
|
276
|
+
properties: {
|
|
277
|
+
dry_run: {
|
|
278
|
+
type: 'boolean',
|
|
279
|
+
description: 'If true, reports what would be archived without changing data (default: false)',
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
name: 'cm_index_refresh',
|
|
286
|
+
description: 'Regenerate L0 compact indexes for learnings and/or skeleton to keep context fresh.',
|
|
287
|
+
inputSchema: {
|
|
288
|
+
type: 'object',
|
|
289
|
+
properties: {
|
|
290
|
+
target: {
|
|
291
|
+
type: 'string',
|
|
292
|
+
enum: ['learnings', 'skeleton', 'all'],
|
|
293
|
+
description: 'Which index to refresh (default: all)',
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
];
|
|
299
|
+
// ─── MCP stdio protocol (JSON-RPC 2.0, Content-Length framing) ───────────────
|
|
300
|
+
function sendMessage(msg) {
|
|
301
|
+
const json = JSON.stringify(msg);
|
|
302
|
+
const header = `Content-Length: ${Buffer.byteLength(json)}\r\n\r\n`;
|
|
303
|
+
process.stdout.write(header + json);
|
|
304
|
+
}
|
|
305
|
+
function respond(id, result) {
|
|
306
|
+
sendMessage({ jsonrpc: '2.0', id, result });
|
|
307
|
+
}
|
|
308
|
+
function respondError(id, code, message) {
|
|
309
|
+
sendMessage({ jsonrpc: '2.0', id, error: { code, message } });
|
|
310
|
+
}
|
|
311
|
+
function handleRequest(msg) {
|
|
312
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
313
|
+
const { id, method, params } = msg;
|
|
314
|
+
if (method === 'initialize') {
|
|
315
|
+
respond(id, {
|
|
316
|
+
protocolVersion: '2024-11-05',
|
|
317
|
+
capabilities: { tools: {} },
|
|
318
|
+
serverInfo: { name: SERVER_NAME, version: SERVER_VERSION },
|
|
319
|
+
});
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
if (method === 'notifications/initialized')
|
|
323
|
+
return;
|
|
324
|
+
if (method === 'tools/list') {
|
|
325
|
+
respond(id, { tools: TOOLS });
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
if (method === 'tools/call') {
|
|
329
|
+
const { name, arguments: args } = (params || {});
|
|
330
|
+
try {
|
|
331
|
+
let result;
|
|
332
|
+
const a = args || {};
|
|
333
|
+
if (name === 'cm_query')
|
|
334
|
+
result = cmQuery(a);
|
|
335
|
+
else if (name === 'cm_resolve')
|
|
336
|
+
result = cmResolve(a);
|
|
337
|
+
else if (name === 'cm_bus_read')
|
|
338
|
+
result = cmBusRead();
|
|
339
|
+
else if (name === 'cm_bus_write')
|
|
340
|
+
result = cmBusWrite(a);
|
|
341
|
+
else if (name === 'cm_budget_check')
|
|
342
|
+
result = cmBudgetCheck(a);
|
|
343
|
+
else if (name === 'cm_memory_decay')
|
|
344
|
+
result = cmMemoryDecay(a);
|
|
345
|
+
else if (name === 'cm_index_refresh')
|
|
346
|
+
result = cmIndexRefresh(a);
|
|
347
|
+
else
|
|
348
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
349
|
+
respond(id, {
|
|
350
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
catch (err) {
|
|
354
|
+
respond(id, {
|
|
355
|
+
content: [{ type: 'text', text: `Error: ${err.message}` }],
|
|
356
|
+
isError: true,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
if (id !== undefined) {
|
|
362
|
+
respondError(id, -32601, `Method not found: ${method}`);
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
// ─── Stdin reader (Content-Length framed) ────────────────────────────────────
|
|
367
|
+
let buffer = Buffer.alloc(0);
|
|
368
|
+
process.stdin.on('data', (chunk) => __awaiter(void 0, void 0, void 0, function* () {
|
|
369
|
+
buffer = Buffer.concat([buffer, chunk]);
|
|
370
|
+
while (true) {
|
|
371
|
+
const sep = buffer.indexOf('\r\n\r\n');
|
|
372
|
+
if (sep === -1)
|
|
373
|
+
break;
|
|
374
|
+
const header = buffer.slice(0, sep).toString();
|
|
375
|
+
const match = header.match(/Content-Length:\s*(\d+)/i);
|
|
376
|
+
if (!match) {
|
|
377
|
+
buffer = buffer.slice(sep + 4);
|
|
378
|
+
break;
|
|
379
|
+
}
|
|
380
|
+
const contentLength = parseInt(match[1], 10);
|
|
381
|
+
const bodyStart = sep + 4;
|
|
382
|
+
if (buffer.length < bodyStart + contentLength)
|
|
383
|
+
break;
|
|
384
|
+
const body = buffer.slice(bodyStart, bodyStart + contentLength).toString('utf8');
|
|
385
|
+
buffer = buffer.slice(bodyStart + contentLength);
|
|
386
|
+
try {
|
|
387
|
+
const msg = JSON.parse(body);
|
|
388
|
+
yield handleRequest(msg);
|
|
389
|
+
}
|
|
390
|
+
catch (_a) {
|
|
391
|
+
// ignore malformed messages
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}));
|
|
395
|
+
process.stdin.on('end', () => {
|
|
396
|
+
(0, context_db_1.closeDb)((0, context_db_1.getDbPath)(PROJECT_PATH));
|
|
397
|
+
process.exit(0);
|
|
398
|
+
});
|
|
399
|
+
process.on('SIGTERM', () => { (0, context_db_1.closeDb)((0, context_db_1.getDbPath)(PROJECT_PATH)); process.exit(0); });
|
|
400
|
+
process.on('SIGINT', () => { (0, context_db_1.closeDb)((0, context_db_1.getDbPath)(PROJECT_PATH)); process.exit(0); });
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.migrateJsonToSqlite = migrateJsonToSqlite;
|
|
7
|
+
exports.exportSqliteToJson = exportSqliteToJson;
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const context_db_1 = require("./context-db");
|
|
11
|
+
function migrateJsonToSqlite(projectPath) {
|
|
12
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3;
|
|
13
|
+
const cmDir = path_1.default.join(projectPath, '.cm');
|
|
14
|
+
const dbPath = (0, context_db_1.getDbPath)(projectPath);
|
|
15
|
+
(0, context_db_1.openDb)(dbPath);
|
|
16
|
+
const result = {
|
|
17
|
+
learnings: { migrated: 0, skipped: 0 },
|
|
18
|
+
decisions: { migrated: 0, skipped: 0 },
|
|
19
|
+
dbPath,
|
|
20
|
+
backupCreated: false,
|
|
21
|
+
};
|
|
22
|
+
// ── Migrate learnings ─────────────────────────────────────────────────────
|
|
23
|
+
const learningsPath = path_1.default.join(cmDir, 'memory', 'learnings.json');
|
|
24
|
+
if (fs_1.default.existsSync(learningsPath)) {
|
|
25
|
+
// Backup
|
|
26
|
+
const backupPath = learningsPath + '.backup';
|
|
27
|
+
fs_1.default.copyFileSync(learningsPath, backupPath);
|
|
28
|
+
result.backupCreated = true;
|
|
29
|
+
let raw = [];
|
|
30
|
+
try {
|
|
31
|
+
raw = JSON.parse(fs_1.default.readFileSync(learningsPath, 'utf-8'));
|
|
32
|
+
}
|
|
33
|
+
catch ( /* invalid JSON — skip */_4) { /* invalid JSON — skip */ }
|
|
34
|
+
for (const l of raw) {
|
|
35
|
+
try {
|
|
36
|
+
const now = new Date().toISOString();
|
|
37
|
+
const learning = {
|
|
38
|
+
id: (_a = l.id) !== null && _a !== void 0 ? _a : `L-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
39
|
+
what_failed: (_d = (_c = (_b = l.whatFailed) !== null && _b !== void 0 ? _b : l.what_failed) !== null && _c !== void 0 ? _c : l.error) !== null && _d !== void 0 ? _d : '(unknown)',
|
|
40
|
+
why_failed: (_g = (_f = (_e = l.whyFailed) !== null && _e !== void 0 ? _e : l.why_failed) !== null && _f !== void 0 ? _f : l.cause) !== null && _g !== void 0 ? _g : '',
|
|
41
|
+
how_to_prevent: (_k = (_j = (_h = l.howToPrevent) !== null && _h !== void 0 ? _h : l.how_to_prevent) !== null && _j !== void 0 ? _j : l.prevention) !== null && _k !== void 0 ? _k : '',
|
|
42
|
+
scope: (_l = l.scope) !== null && _l !== void 0 ? _l : 'global',
|
|
43
|
+
ttl: (_m = l.ttl) !== null && _m !== void 0 ? _m : 60,
|
|
44
|
+
reinforce_count: (_p = (_o = l.reinforceCount) !== null && _o !== void 0 ? _o : l.reinforce_count) !== null && _p !== void 0 ? _p : 0,
|
|
45
|
+
status: (_q = l.status) !== null && _q !== void 0 ? _q : 'active',
|
|
46
|
+
created_at: (_s = (_r = l.date) !== null && _r !== void 0 ? _r : l.timestamp) !== null && _s !== void 0 ? _s : now,
|
|
47
|
+
updated_at: (_u = (_t = l.date) !== null && _t !== void 0 ? _t : l.timestamp) !== null && _u !== void 0 ? _u : now,
|
|
48
|
+
agent: l.agent,
|
|
49
|
+
task_id: (_v = l.taskId) !== null && _v !== void 0 ? _v : l.task_id,
|
|
50
|
+
module: l.module,
|
|
51
|
+
};
|
|
52
|
+
(0, context_db_1.insertLearning)(dbPath, learning);
|
|
53
|
+
result.learnings.migrated++;
|
|
54
|
+
}
|
|
55
|
+
catch (_5) {
|
|
56
|
+
result.learnings.skipped++;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// ── Migrate decisions ─────────────────────────────────────────────────────
|
|
61
|
+
const decisionsPath = path_1.default.join(cmDir, 'memory', 'decisions.json');
|
|
62
|
+
if (fs_1.default.existsSync(decisionsPath)) {
|
|
63
|
+
const backupPath = decisionsPath + '.backup';
|
|
64
|
+
fs_1.default.copyFileSync(decisionsPath, backupPath);
|
|
65
|
+
let raw = [];
|
|
66
|
+
try {
|
|
67
|
+
raw = JSON.parse(fs_1.default.readFileSync(decisionsPath, 'utf-8'));
|
|
68
|
+
}
|
|
69
|
+
catch ( /* invalid JSON — skip */_6) { /* invalid JSON — skip */ }
|
|
70
|
+
for (const d of raw) {
|
|
71
|
+
try {
|
|
72
|
+
const now = new Date().toISOString();
|
|
73
|
+
const decision = {
|
|
74
|
+
id: (_w = d.id) !== null && _w !== void 0 ? _w : `D-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
75
|
+
decision: (_x = d.decision) !== null && _x !== void 0 ? _x : '(unknown)',
|
|
76
|
+
rationale: (_y = d.rationale) !== null && _y !== void 0 ? _y : '',
|
|
77
|
+
scope: (_z = d.scope) !== null && _z !== void 0 ? _z : 'global',
|
|
78
|
+
status: (_0 = d.status) !== null && _0 !== void 0 ? _0 : 'active',
|
|
79
|
+
superseded_by: (_1 = d.supersededBy) !== null && _1 !== void 0 ? _1 : d.superseded_by,
|
|
80
|
+
created_at: (_3 = (_2 = d.date) !== null && _2 !== void 0 ? _2 : d.timestamp) !== null && _3 !== void 0 ? _3 : now,
|
|
81
|
+
agent: d.agent,
|
|
82
|
+
};
|
|
83
|
+
(0, context_db_1.insertDecision)(dbPath, decision);
|
|
84
|
+
result.decisions.migrated++;
|
|
85
|
+
}
|
|
86
|
+
catch (_7) {
|
|
87
|
+
result.decisions.skipped++;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
function exportSqliteToJson(projectPath) {
|
|
94
|
+
const cmDir = path_1.default.join(projectPath, '.cm');
|
|
95
|
+
const memDir = path_1.default.join(cmDir, 'memory');
|
|
96
|
+
const dbPath = (0, context_db_1.getDbPath)(projectPath);
|
|
97
|
+
const db = (0, context_db_1.openDb)(dbPath);
|
|
98
|
+
fs_1.default.mkdirSync(memDir, { recursive: true });
|
|
99
|
+
// Export learnings
|
|
100
|
+
const learnings = db.prepare(`
|
|
101
|
+
SELECT id, what_failed, why_failed, how_to_prevent, scope, ttl,
|
|
102
|
+
reinforce_count as reinforceCount, status, created_at as date,
|
|
103
|
+
agent, task_id as taskId, module
|
|
104
|
+
FROM learnings
|
|
105
|
+
WHERE status != 'archived'
|
|
106
|
+
ORDER BY created_at DESC
|
|
107
|
+
`).all();
|
|
108
|
+
const learningsPath = path_1.default.join(memDir, 'learnings.json');
|
|
109
|
+
fs_1.default.writeFileSync(learningsPath, JSON.stringify(learnings, null, 2), 'utf-8');
|
|
110
|
+
// Export decisions
|
|
111
|
+
const decisions = db.prepare(`
|
|
112
|
+
SELECT id, decision, rationale, scope, status,
|
|
113
|
+
superseded_by as supersededBy, created_at as date, agent
|
|
114
|
+
FROM decisions
|
|
115
|
+
WHERE status != 'archived'
|
|
116
|
+
ORDER BY created_at DESC
|
|
117
|
+
`).all();
|
|
118
|
+
const decisionsPath = path_1.default.join(memDir, 'decisions.json');
|
|
119
|
+
fs_1.default.writeFileSync(decisionsPath, JSON.stringify(decisions, null, 2), 'utf-8');
|
|
120
|
+
return {
|
|
121
|
+
learnings: learnings.length,
|
|
122
|
+
decisions: decisions.length,
|
|
123
|
+
learningsPath,
|
|
124
|
+
decisionsPath,
|
|
125
|
+
};
|
|
126
|
+
}
|
package/dist/skill-chain.js
CHANGED
|
@@ -16,6 +16,7 @@ exports.formatChainProgressBar = formatChainProgressBar;
|
|
|
16
16
|
exports.getCurrentSkill = getCurrentSkill;
|
|
17
17
|
const crypto_1 = __importDefault(require("crypto"));
|
|
18
18
|
const builtin_1 = require("./chains/builtin");
|
|
19
|
+
const context_bus_1 = require("./context-bus");
|
|
19
20
|
// ─── Chain Matching ─────────────────────────────────────────────────────────
|
|
20
21
|
// TRIZ #10: Preliminary Action — analyze task BEFORE dispatching
|
|
21
22
|
/**
|
|
@@ -59,7 +60,7 @@ function findChain(chainId) {
|
|
|
59
60
|
/**
|
|
60
61
|
* Create a new chain execution from a chain definition.
|
|
61
62
|
*/
|
|
62
|
-
function createChainExecution(chain, projectId, taskTitle, agent) {
|
|
63
|
+
function createChainExecution(chain, projectId, taskTitle, agent, projectPath) {
|
|
63
64
|
const now = new Date().toISOString();
|
|
64
65
|
const steps = chain.steps.map((step, index) => ({
|
|
65
66
|
index,
|
|
@@ -74,7 +75,7 @@ function createChainExecution(chain, projectId, taskTitle, agent) {
|
|
|
74
75
|
steps[0].status = 'running';
|
|
75
76
|
steps[0].startedAt = now;
|
|
76
77
|
}
|
|
77
|
-
|
|
78
|
+
const execution = {
|
|
78
79
|
id: crypto_1.default.randomUUID(),
|
|
79
80
|
chainId: chain.id,
|
|
80
81
|
chainName: chain.name,
|
|
@@ -87,12 +88,20 @@ function createChainExecution(chain, projectId, taskTitle, agent) {
|
|
|
87
88
|
startedAt: now,
|
|
88
89
|
updatedAt: now,
|
|
89
90
|
};
|
|
91
|
+
// Init context bus for this chain execution
|
|
92
|
+
if (projectPath) {
|
|
93
|
+
try {
|
|
94
|
+
(0, context_bus_1.initBus)(projectPath, chain.id, execution.id);
|
|
95
|
+
}
|
|
96
|
+
catch ( /* non-fatal: context bus is optional enhancement */_a) { /* non-fatal: context bus is optional enhancement */ }
|
|
97
|
+
}
|
|
98
|
+
return execution;
|
|
90
99
|
}
|
|
91
100
|
/**
|
|
92
101
|
* Advance the chain to the next step. Marks current step as completed.
|
|
93
102
|
* Returns the next step's skill name, or null if chain is complete.
|
|
94
103
|
*/
|
|
95
|
-
function advanceChain(execution, output) {
|
|
104
|
+
function advanceChain(execution, output, projectPath) {
|
|
96
105
|
const now = new Date().toISOString();
|
|
97
106
|
const currentStep = execution.steps[execution.currentStepIndex];
|
|
98
107
|
if (!currentStep) {
|
|
@@ -104,6 +113,13 @@ function advanceChain(execution, output) {
|
|
|
104
113
|
if (output)
|
|
105
114
|
currentStep.output = output;
|
|
106
115
|
execution.updatedAt = now;
|
|
116
|
+
// Update context bus with completed step's output
|
|
117
|
+
if (projectPath) {
|
|
118
|
+
try {
|
|
119
|
+
(0, context_bus_1.updateBusStep)(projectPath, currentStep.skill, { summary: output });
|
|
120
|
+
}
|
|
121
|
+
catch ( /* non-fatal */_a) { /* non-fatal */ }
|
|
122
|
+
}
|
|
107
123
|
// Find next non-skipped step
|
|
108
124
|
let nextIndex = execution.currentStepIndex + 1;
|
|
109
125
|
while (nextIndex < execution.steps.length) {
|