@educa-corp/sdd-framework 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/build.js +113 -19
- package/bin/gate-trace.js +487 -0
- package/bin/index.js +445 -146
- package/bin/lint-trace.js +643 -0
- package/bin/self-check.js +804 -2
- package/bin/trace-schema.json +621 -10
- package/core/FRAMEWORK_VERSION +1 -1
- package/core/README.md +20 -0
- package/core/commands/amend-prd.md +518 -0
- package/core/commands/debug.md +123 -511
- package/core/commands/define-product.md +86 -510
- package/core/commands/dev-gen-test.md +86 -510
- package/core/commands/dev-run-test.md +133 -519
- package/core/commands/dev-smoke-test.md +86 -510
- package/core/commands/extend-prd.md +128 -522
- package/core/commands/fix-bug.md +118 -509
- package/core/commands/generate-architecture.md +94 -515
- package/core/commands/generate-bdd.md +128 -513
- package/core/commands/generate-code.md +119 -510
- package/core/commands/generate-design-spec.md +86 -510
- package/core/commands/generate-prd.md +89 -510
- package/core/commands/generate-spec-manifest.md +86 -510
- package/core/commands/generate-tech-docs.md +120 -512
- package/core/commands/learn.md +172 -496
- package/core/commands/map-testids.md +86 -510
- package/core/commands/propose-scenario.md +86 -510
- package/core/commands/qc-analyze.md +86 -510
- package/core/commands/qc-design-test.md +86 -510
- package/core/commands/qc-plan.md +86 -510
- package/core/commands/qc-report.md +86 -510
- package/core/commands/qc-review.md +86 -510
- package/core/commands/qc-run-test.md +115 -513
- package/core/commands/refine-prd.md +112 -522
- package/core/commands/report-bug.md +86 -510
- package/core/commands/review-code.md +123 -511
- package/core/commands/review-context.md +136 -522
- package/core/commands/review-tech-docs.md +90 -511
- package/core/commands/setup-ai-first.md +166 -138
- package/core/commands/sync.md +155 -107
- package/core/commands/update-framework.md +16 -103
- package/core/commands/validate-traces.md +426 -511
- package/core/hooks/data-guard.js +174 -83
- package/core/hooks/settings.json +2 -1
- package/core/rules/workflow.md +64 -4
- package/core/steps/capture-lesson.md +34 -1
- package/core/steps/context-loader.md +50 -8
- package/core/steps/gate.md +92 -35
- package/core/steps/report-footer.md +23 -0
- package/core/templates/README.md +24 -1
- package/core/templates/ci/trace-gate.yml +146 -0
- package/core/templates/feature.template +1 -1
- package/core/templates/hooks/pre-push +61 -0
- package/docs/02-concepts/architecture.md +61 -6
- package/docs/02-concepts/traceability.md +57 -0
- package/docs/03-guides/architect.md +63 -0
- package/docs/04-reference/commands.md +148 -134
- package/docs/04-reference/model-selection.md +32 -19
- package/docs/04-reference/trace-schema.md +39 -0
- package/docs/explain/02b-extend-prd.md +1 -1
- package/docs/explain/02c-amend-prd.md +152 -0
- package/docs/explain/21-validate-traces.md +2 -1
- package/docs/explain/27-learn.md +5 -3
- package/docs/explain/28-sync.md +25 -0
- package/docs/explain/README.md +136 -135
- package/package.json +5 -9
- package/commands/debug.md +0 -917
- package/commands/debug.tmpl +0 -257
- package/commands/define-product.md +0 -862
- package/commands/define-product.tmpl +0 -225
- package/commands/dev-gen-test.md +0 -1124
- package/commands/dev-gen-test.tmpl +0 -490
- package/commands/dev-run-test.md +0 -859
- package/commands/dev-run-test.tmpl +0 -225
- package/commands/dev-smoke-test.md +0 -798
- package/commands/dev-smoke-test.tmpl +0 -217
- package/commands/extend-prd.md +0 -907
- package/commands/extend-prd.tmpl +0 -270
- package/commands/fix-bug.md +0 -910
- package/commands/fix-bug.tmpl +0 -197
- package/commands/generate-architecture.md +0 -775
- package/commands/generate-architecture.tmpl +0 -194
- package/commands/generate-bdd.md +0 -1347
- package/commands/generate-bdd.tmpl +0 -590
- package/commands/generate-code.md +0 -1283
- package/commands/generate-code.tmpl +0 -649
- package/commands/generate-design-spec.md +0 -1161
- package/commands/generate-design-spec.tmpl +0 -524
- package/commands/generate-prd.md +0 -1143
- package/commands/generate-prd.tmpl +0 -223
- package/commands/generate-spec-manifest.md +0 -745
- package/commands/generate-spec-manifest.tmpl +0 -164
- package/commands/generate-tech-docs.md +0 -1344
- package/commands/generate-tech-docs.tmpl +0 -273
- package/commands/learn.md +0 -723
- package/commands/learn.tmpl +0 -63
- package/commands/map-testids.md +0 -662
- package/commands/map-testids.tmpl +0 -81
- package/commands/propose-scenario.md +0 -783
- package/commands/propose-scenario.tmpl +0 -202
- package/commands/qc-analyze.md +0 -693
- package/commands/qc-analyze.tmpl +0 -112
- package/commands/qc-design-test.md +0 -650
- package/commands/qc-design-test.tmpl +0 -69
- package/commands/qc-plan.md +0 -630
- package/commands/qc-plan.tmpl +0 -49
- package/commands/qc-report.md +0 -641
- package/commands/qc-report.tmpl +0 -60
- package/commands/qc-review.md +0 -634
- package/commands/qc-review.tmpl +0 -53
- package/commands/qc-run-test.md +0 -750
- package/commands/qc-run-test.tmpl +0 -116
- package/commands/refine-prd.md +0 -1074
- package/commands/refine-prd.tmpl +0 -278
- package/commands/report-bug.md +0 -729
- package/commands/report-bug.tmpl +0 -148
- package/commands/review-code.md +0 -803
- package/commands/review-code.tmpl +0 -143
- package/commands/review-context.md +0 -1323
- package/commands/review-context.tmpl +0 -527
- package/commands/review-tech-docs.md +0 -982
- package/commands/review-tech-docs.tmpl +0 -401
- package/commands/setup-ai-first.md +0 -574
- package/commands/setup-ai-first.tmpl +0 -378
- package/commands/sync.md +0 -486
- package/commands/sync.tmpl +0 -384
- package/commands/update-framework.md +0 -290
- package/commands/update-framework.tmpl +0 -188
- package/commands/validate-traces.md +0 -1435
- package/commands/validate-traces.tmpl +0 -854
- package/hooks/data-guard.js +0 -141
- package/hooks/settings.json +0 -18
- package/modules/android-compose/module.yaml +0 -13
- package/modules/android-compose/stack-profile.yaml +0 -57
- package/modules/angular/architecture-snippets/component-patterns.md +0 -187
- package/modules/angular/module.yaml +0 -6
- package/modules/angular/stack-profile.yaml +0 -38
- package/modules/context-engineering/architecture-snippets/context-design.md +0 -119
- package/modules/context-engineering/module.yaml +0 -9
- package/modules/context-engineering/stack-profile.yaml +0 -61
- package/modules/dotnet/architecture-snippets/clean-arch.md +0 -160
- package/modules/dotnet/module.yaml +0 -6
- package/modules/dotnet/stack-profile.yaml +0 -50
- package/modules/flutter/module.yaml +0 -14
- package/modules/flutter/stack-profile.yaml +0 -59
- package/modules/golang/architecture-snippets/domain-layout.md +0 -283
- package/modules/golang/module.yaml +0 -6
- package/modules/golang/stack-profile.yaml +0 -40
- package/modules/ios-swiftui/module.yaml +0 -13
- package/modules/ios-swiftui/stack-profile.yaml +0 -55
- package/modules/java-spring/architecture-snippets/layered-arch.md +0 -201
- package/modules/java-spring/module.yaml +0 -15
- package/modules/java-spring/stack-profile.yaml +0 -28
- package/modules/nextjs/architecture-snippets/app-router-patterns.md +0 -269
- package/modules/nextjs/module.yaml +0 -14
- package/modules/nextjs/stack-profile.yaml +0 -74
- package/modules/nuxt/module.yaml +0 -14
- package/modules/nuxt/stack-profile.yaml +0 -58
- package/modules/phaser-game/architecture-snippets/phaser-scene-patterns.md +0 -646
- package/modules/phaser-game/module.yaml +0 -15
- package/modules/phaser-game/stack-profile.yaml +0 -90
- package/modules/php-laravel/architecture-snippets/service-repository.md +0 -302
- package/modules/php-laravel/module.yaml +0 -15
- package/modules/php-laravel/stack-profile.yaml +0 -56
- package/modules/qc-playwright/stack-profile.yaml +0 -66
- package/modules/react/architecture-snippets/hooks-query-patterns.md +0 -254
- package/modules/react/module.yaml +0 -14
- package/modules/react/stack-profile.yaml +0 -63
- package/modules/react-native/module.yaml +0 -14
- package/modules/react-native/stack-profile.yaml +0 -56
- package/modules/vue/module.yaml +0 -14
- package/modules/vue/stack-profile.yaml +0 -65
- package/rules/data-protection.md +0 -80
- package/rules/workflow.md +0 -73
- package/scripts/init.sh +0 -49
- package/scripts/upgrade.sh +0 -94
- package/skills/code/SKILL.md +0 -19
- package/skills/code/SKILL.tmpl +0 -19
- package/skills/debug/SKILL.md +0 -19
- package/skills/debug/SKILL.tmpl +0 -19
- package/skills/design-spec/SKILL.md +0 -11
- package/skills/design-spec/SKILL.tmpl +0 -11
- package/skills/discovery/SKILL.md +0 -14
- package/skills/discovery/SKILL.tmpl +0 -14
- package/skills/prd/SKILL.md +0 -19
- package/skills/prd/SKILL.tmpl +0 -19
- package/skills/qc/qa-analyst/DOC_GAPS.template.md +0 -63
- package/skills/qc/qa-analyst/acceptance-criteria.md +0 -60
- package/skills/qc/qa-analyst/business-rules.md +0 -59
- package/skills/qc/qa-analyst/data-flow.md +0 -64
- package/skills/qc/qa-analyst/spec-breakdown.md +0 -61
- package/skills/qc/qa-designer/e2e/journey.md +0 -41
- package/skills/qc/qa-designer/exploratory/charter.md +0 -68
- package/skills/qc/qa-designer/exploratory/explore-to-functional.md +0 -43
- package/skills/qc/qa-designer/functional/api.md +0 -45
- package/skills/qc/qa-designer/functional/gui-feature.md +0 -46
- package/skills/qc/qa-designer/functional/gui-screen.md +0 -52
- package/skills/qc/qa-designer/integration/api.md +0 -42
- package/skills/qc/qa-designer/integration/db.md +0 -39
- package/skills/qc/qa-designer/integration/gui.md +0 -40
- package/skills/qc/qa-designer/integration/kafka.md +0 -40
- package/skills/qc/qa-designer/non-functional.md +0 -40
- package/skills/qc/qa-planner/test-plan.md +0 -120
- package/skills/qc/qa-reviewer/script/e2e.md +0 -87
- package/skills/qc/qa-reviewer/script/exploratory.md +0 -45
- package/skills/qc/qa-reviewer/script/functional.md +0 -101
- package/skills/qc/qa-reviewer/script/integration.md +0 -91
- package/skills/qc/qa-reviewer/script/non-functional.md +0 -126
- package/skills/qc/qa-reviewer/test-case/e2e.md +0 -73
- package/skills/qc/qa-reviewer/test-case/exploratory.md +0 -43
- package/skills/qc/qa-reviewer/test-case/functional.md +0 -76
- package/skills/qc/qa-reviewer/test-case/integration.md +0 -69
- package/skills/qc/qa-reviewer/test-case/non-functional.md +0 -73
- package/skills/qc/qa-runner/e2e.md +0 -49
- package/skills/qc/qa-runner/exploratory/session.md +0 -36
- package/skills/qc/qa-runner/functional/api.md +0 -35
- package/skills/qc/qa-runner/functional/gui-feature.md +0 -51
- package/skills/qc/qa-runner/functional/gui-screen.md +0 -55
- package/skills/qc/qa-runner/integration.md +0 -47
- package/skills/qc/qa-runner/non-functional.md +0 -49
- package/skills/qc/qa-runner/report/report.md +0 -37
- package/skills/setup-ai-first/SKILL.md +0 -19
- package/skills/setup-ai-first/SKILL.tmpl +0 -19
- package/skills/spec/SKILL.md +0 -19
- package/skills/spec/SKILL.tmpl +0 -19
- package/skills/test/SKILL.md +0 -18
- package/skills/test/SKILL.tmpl +0 -18
- package/steps/business-language.md +0 -56
- package/steps/capture-lesson.md +0 -79
- package/steps/context-loader.md +0 -385
- package/steps/gate.md +0 -94
- package/steps/report-footer.md +0 -102
- package/steps/review-fanout.md +0 -159
- package/steps/spawn-agent.md +0 -129
- package/steps/trace-mirror.md +0 -53
- package/templates/README.md +0 -47
- package/templates/architecture.template.md +0 -394
- package/templates/design-spec.template.md +0 -217
- package/templates/feature.template +0 -123
- package/templates/platform-guide.template.md +0 -145
- package/templates/prd.template.md +0 -283
- package/templates/product-definition.template.md +0 -188
- package/templates/project-context.yaml +0 -212
- package/templates/tech-design.template.md +0 -490
package/bin/build.js
CHANGED
|
@@ -23,6 +23,41 @@ const SKILLS_DIR = path.join(ROOT, 'skills');
|
|
|
23
23
|
// Cache for step file contents
|
|
24
24
|
const stepCache = {};
|
|
25
25
|
|
|
26
|
+
// ── Step nào ĐỌC LÚC CHẠY thay vì nướng vào từng lệnh (GAPS-v3 G45) ──────────
|
|
27
|
+
//
|
|
28
|
+
// Vì sao: build inline `{{include:}}` vào TỪNG file lệnh, nên 32 lệnh = 2069 KB mà chỉ
|
|
29
|
+
// 580 KB là nội dung riêng của chúng — 72% là vài step giống hệt nhau, chép 30 lần.
|
|
30
|
+
// `/generate-code` = 108 KB ≈ 27.000 token đọc TRƯỚC khi làm gì; gần một nửa không nói
|
|
31
|
+
// gì về việc sinh code. `/refine-prd` thì 75% là nội dung dùng chung.
|
|
32
|
+
//
|
|
33
|
+
// Cái giá thật không phải tiền: trên PRD nhiều UC, nạp 27k token chỉ để đọc chỉ dẫn làm
|
|
34
|
+
// tăng rủi ro CẠN CONTEXT GIỮA CHỪNG — mà thứ đang được ghi lúc đó là sổ trace.
|
|
35
|
+
//
|
|
36
|
+
// PHẠM VI CÓ CHỦ Ý — chỉ hai step, không phải tất cả:
|
|
37
|
+
// context-loader (64% lãng phí) · report-footer (16%) → đọc lúc chạy
|
|
38
|
+
// gate (15%) → GIỮ INLINE
|
|
39
|
+
// Gate là lưới an toàn (model check · resolve target · CHECKPOINT). Bỏ sót gate thì lệnh
|
|
40
|
+
// VẪN CHẠY, chỉ là không còn cổng nào — hỏng ÂM THẦM. Bỏ sót context-loader thì lệnh dừng
|
|
41
|
+
// ngay vì thiếu path/config — hỏng ỒN ÀO, thấy liền. Đổi 15% lấy một lưới an toàn là lỗ.
|
|
42
|
+
//
|
|
43
|
+
// MỘT biến thể duy nhất kể từ khi G50 gỡ legacy mode. Trước đó phải build hai bản —
|
|
44
|
+
// `commands/*.md` inline đầy đủ cho legacy (nó copy thẳng file đó mà KHÔNG cài `.agent/`,
|
|
45
|
+
// nên không có `.agent/steps/` để đọc) và `core/commands/*.md` slim cho `--init`. Legacy
|
|
46
|
+
// đi rồi thì mọi bản cài đều có `.agent/steps/`, và nhánh build thứ hai là nợ chờ lệch.
|
|
47
|
+
const RUNTIME_READ = {
|
|
48
|
+
'steps/context-loader.md':
|
|
49
|
+
'**BẮT BUỘC — đọc `.agent/steps/context-loader.md` và thực thi TOÀN BỘ quy trình trong đó**,\n' +
|
|
50
|
+
'rồi mới tiếp tục phần bên dưới.\n' +
|
|
51
|
+
'\n' +
|
|
52
|
+
'Bỏ qua bước này thì `{paths.*}`, `{tech_stack.*}`, `{conventions.*}`, guardrail từ\n' +
|
|
53
|
+
'`project-lessons`, và routing service (chế độ umbrella) đều **chưa được phân giải** — mọi\n' +
|
|
54
|
+
'placeholder bên dưới sẽ rỗng và lệnh sẽ đọc/ghi sai chỗ.',
|
|
55
|
+
|
|
56
|
+
'steps/report-footer.md':
|
|
57
|
+
'**Đọc `.agent/steps/report-footer.md`** và áp đúng khuôn footer trong đó (Status Badge ·\n' +
|
|
58
|
+
'Output Artifacts · Next) cho report cuối, kèm khối bên dưới.',
|
|
59
|
+
};
|
|
60
|
+
|
|
26
61
|
/**
|
|
27
62
|
* Load a step file by name, caching the result.
|
|
28
63
|
* @param {string} stepPath - e.g. "steps/gate.md"
|
|
@@ -54,10 +89,11 @@ function buildTemplate(tmplFile, label) {
|
|
|
54
89
|
try {
|
|
55
90
|
let content = fs.readFileSync(tmplFile, 'utf8');
|
|
56
91
|
|
|
57
|
-
// Replace all {{include:...}} markers
|
|
92
|
+
// Replace all {{include:...}} markers — trừ những step nằm trong RUNTIME_READ,
|
|
93
|
+
// chúng được thay bằng một chỉ dẫn ĐỌC LÚC CHẠY thay vì nướng 33 KB vào đây (G45).
|
|
58
94
|
content = content.replace(/\{\{include:([^}]+)\}\}/g, (match, includePath) => {
|
|
59
|
-
const
|
|
60
|
-
return loadStep(
|
|
95
|
+
const key = includePath.trim();
|
|
96
|
+
return RUNTIME_READ[key] !== undefined ? RUNTIME_READ[key] : loadStep(key);
|
|
61
97
|
});
|
|
62
98
|
|
|
63
99
|
fs.writeFileSync(outFile, content, 'utf8');
|
|
@@ -155,6 +191,8 @@ if (skillTmplFiles.length === 0) {
|
|
|
155
191
|
// It is gitignored but included in the npm package (via "files" whitelist).
|
|
156
192
|
|
|
157
193
|
const CORE_DIR = path.join(ROOT, 'core');
|
|
194
|
+
const CORE_TMP = path.join(ROOT, 'core.tmp');
|
|
195
|
+
const CORE_BAK = path.join(ROOT, 'core.bak');
|
|
158
196
|
const pkg = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf8'));
|
|
159
197
|
const VERSION = pkg.version;
|
|
160
198
|
|
|
@@ -162,11 +200,48 @@ console.log('');
|
|
|
162
200
|
console.log('Populating core/ (distributable) ...');
|
|
163
201
|
console.log('');
|
|
164
202
|
|
|
165
|
-
//
|
|
166
|
-
|
|
167
|
-
|
|
203
|
+
// Dựng vào core.tmp/ rồi SWAP — không bao giờ xoá core/ trước khi có bản thay thế
|
|
204
|
+
// hoàn chỉnh (GAPS-v3 G43).
|
|
205
|
+
//
|
|
206
|
+
// Bản cũ làm `rmSync(core/)` rồi mới dựng lại. Nếu bước dựng fail nửa đường — đĩa đầy,
|
|
207
|
+
// thư mục read-only, Ctrl-C — thì core/ ĐÃ MẤT và không có gì thay thế. Với consumer thì
|
|
208
|
+
// hậu quả nặng hơn hẳn: `--init` chạy build ngay trong thư mục npx cache, nên một lần fail
|
|
209
|
+
// làm hỏng package trong cache VĨNH VIỄN, và mọi lần chạy sau đều báo "core/ not found.
|
|
210
|
+
// The package may not have been built correctly" — một thông điệp dẫn sai hướng, vì package
|
|
211
|
+
// được build đúng, chính installer đã xoá nó.
|
|
212
|
+
//
|
|
213
|
+
// Dọn rác của lần chạy trước (nếu có) — không thì swap sẽ trượt vào thư mục cũ.
|
|
214
|
+
for (const stale of [CORE_TMP, CORE_BAK]) {
|
|
215
|
+
if (fs.existsSync(stale)) fs.rmSync(stale, { recursive: true, force: true });
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Kiểm quyền ghi TRƯỚC khi làm gì cả: fail ở đây thì chưa có gì bị đụng tới.
|
|
219
|
+
try {
|
|
220
|
+
fs.mkdirSync(CORE_TMP, { recursive: true });
|
|
221
|
+
} catch (err) {
|
|
222
|
+
console.error('');
|
|
223
|
+
console.error(`❌ Không ghi được vào thư mục package: ${ROOT}`);
|
|
224
|
+
console.error(` (${err.code || err.message})`);
|
|
225
|
+
console.error('');
|
|
226
|
+
console.error(' Đây là bản cài read-only. core/ hiện tại KHÔNG bị đụng tới.');
|
|
227
|
+
console.error(' Thử: npx -y @educa-corp/sdd-framework@latest --init');
|
|
228
|
+
console.error(' Hoặc xoá cache npx: rm -rf ~/.npm/_npx');
|
|
229
|
+
console.error('');
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** Đưa core.tmp/ vào chỗ core/. Fail ở bất kỳ đâu thì khôi phục bản cũ. */
|
|
234
|
+
function swapCoreIntoPlace() {
|
|
235
|
+
const hadOld = fs.existsSync(CORE_DIR);
|
|
236
|
+
if (hadOld) fs.renameSync(CORE_DIR, CORE_BAK);
|
|
237
|
+
try {
|
|
238
|
+
fs.renameSync(CORE_TMP, CORE_DIR);
|
|
239
|
+
} catch (err) {
|
|
240
|
+
if (hadOld) fs.renameSync(CORE_BAK, CORE_DIR); // core/ trở lại nguyên trạng
|
|
241
|
+
throw err;
|
|
242
|
+
}
|
|
243
|
+
if (hadOld) fs.rmSync(CORE_BAK, { recursive: true, force: true });
|
|
168
244
|
}
|
|
169
|
-
fs.mkdirSync(CORE_DIR, { recursive: true });
|
|
170
245
|
|
|
171
246
|
/**
|
|
172
247
|
* Recursively copy src → dest, optionally filtering files by name.
|
|
@@ -190,29 +265,31 @@ function copyDirToCore(src, dest, fileFilter) {
|
|
|
190
265
|
|
|
191
266
|
const coreMappings = [
|
|
192
267
|
// Built command .md files (not .tmpl sources)
|
|
193
|
-
{ src: COMMANDS_DIR, dest: path.join(
|
|
268
|
+
{ src: COMMANDS_DIR, dest: path.join(CORE_TMP, 'commands'), filter: f => f.endsWith('.md') },
|
|
194
269
|
// Step files (gate, context-loader, spawn-agent, report-footer)
|
|
195
|
-
{ src: path.join(ROOT, 'steps'), dest: path.join(
|
|
270
|
+
{ src: path.join(ROOT, 'steps'), dest: path.join(CORE_TMP, 'steps'), filter: null },
|
|
196
271
|
// Hook scripts
|
|
197
|
-
{ src: path.join(ROOT, 'hooks'), dest: path.join(
|
|
272
|
+
{ src: path.join(ROOT, 'hooks'), dest: path.join(CORE_TMP, 'hooks'), filter: null },
|
|
198
273
|
// Data-protection and workflow rules
|
|
199
|
-
{ src: path.join(ROOT, 'rules'), dest: path.join(
|
|
274
|
+
{ src: path.join(ROOT, 'rules'), dest: path.join(CORE_TMP, 'rules'), filter: null },
|
|
200
275
|
// PRD / architecture templates
|
|
201
|
-
{ src: path.join(ROOT, 'templates'), dest: path.join(
|
|
276
|
+
{ src: path.join(ROOT, 'templates'), dest: path.join(CORE_TMP, 'templates'), filter: null },
|
|
202
277
|
// Stack module profiles
|
|
203
|
-
{ src: path.join(ROOT, 'modules'), dest: path.join(
|
|
278
|
+
{ src: path.join(ROOT, 'modules'), dest: path.join(CORE_TMP, 'modules'), filter: null },
|
|
204
279
|
// Built skill .md files (not .tmpl sources)
|
|
205
|
-
{ src: SKILLS_DIR, dest: path.join(
|
|
280
|
+
{ src: SKILLS_DIR, dest: path.join(CORE_TMP, 'skills'), filter: f => !f.endsWith('.tmpl') },
|
|
206
281
|
];
|
|
207
282
|
|
|
208
283
|
for (const { src, dest, filter } of coreMappings) {
|
|
209
284
|
copyDirToCore(src, dest, filter);
|
|
210
|
-
|
|
211
|
-
|
|
285
|
+
// Báo theo ĐÍCH CUỐI (core/…), không phải thư mục dựng trung gian. core.tmp/ là chi
|
|
286
|
+
// tiết của bước swap (G43) — người đọc log quan tâm cái gì được cài, không quan tâm
|
|
287
|
+
// nó đi qua đâu.
|
|
288
|
+
console.log(` ✅ core/${path.basename(dest)}/`);
|
|
212
289
|
}
|
|
213
290
|
|
|
214
|
-
// Write FRAMEWORK_VERSION so
|
|
215
|
-
fs.writeFileSync(path.join(
|
|
291
|
+
// Write FRAMEWORK_VERSION so /update-framework can compare installed vs latest
|
|
292
|
+
fs.writeFileSync(path.join(CORE_TMP, 'FRAMEWORK_VERSION'), VERSION + '\n', 'utf8');
|
|
216
293
|
console.log(` ✅ core/FRAMEWORK_VERSION (v${VERSION})`);
|
|
217
294
|
|
|
218
295
|
// .agent/README.md — which paths under .agent/ a project may edit, and which the
|
|
@@ -220,10 +297,27 @@ console.log(` ✅ core/FRAMEWORK_VERSION (v${VERSION})`);
|
|
|
220
297
|
// land inside .agent/templates/.
|
|
221
298
|
const agentReadmeSrc = path.join(ROOT, 'AGENT_README.md');
|
|
222
299
|
if (fs.existsSync(agentReadmeSrc)) {
|
|
223
|
-
fs.copyFileSync(agentReadmeSrc, path.join(
|
|
300
|
+
fs.copyFileSync(agentReadmeSrc, path.join(CORE_TMP, 'README.md'));
|
|
224
301
|
console.log(' ✅ core/README.md (← AGENT_README.md)');
|
|
225
302
|
}
|
|
226
303
|
|
|
304
|
+
// ── 3b. Swap core.tmp/ → core/ ───────────────────────────────────────────────
|
|
305
|
+
//
|
|
306
|
+
// Tới đây core.tmp/ đã hoàn chỉnh. Đây là điểm duy nhất core/ bị thay, và nó là
|
|
307
|
+
// một phép rename — gần như nguyên tử, không có cửa sổ nào core/ vắng mặt-và-không-
|
|
308
|
+
// có-bản-thay-thế. Fail thì swapCoreIntoPlace() khôi phục bản cũ (G43).
|
|
309
|
+
try {
|
|
310
|
+
swapCoreIntoPlace();
|
|
311
|
+
} catch (err) {
|
|
312
|
+
console.error('');
|
|
313
|
+
console.error(`❌ Không thay được core/: ${err.code || err.message}`);
|
|
314
|
+
console.error(' core/ cũ đã được khôi phục — package vẫn dùng được.');
|
|
315
|
+
console.error(` Bản vừa dựng còn ở: ${path.relative(ROOT, CORE_TMP)}/`);
|
|
316
|
+
console.error(' Nguyên nhân thường gặp: file trong core/ đang bị process khác giữ (antivirus, editor).');
|
|
317
|
+
console.error('');
|
|
318
|
+
process.exit(1);
|
|
319
|
+
}
|
|
320
|
+
|
|
227
321
|
// ── 4. Sync local dogfood .agent/ (dev repo only) ────────────────────────────
|
|
228
322
|
//
|
|
229
323
|
// In THIS framework repo, .agent/ is a pure mirror of core/ used to dogfood the
|