@educa-corp/sdd-framework 0.6.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/gate-trace.js +25 -2
- package/bin/index.js +32 -5
- package/bin/lint-trace.js +41 -0
- package/bin/self-check.js +430 -3
- package/bin/trace-schema.json +391 -30
- package/core/FRAMEWORK_VERSION +1 -1
- package/{commands/extend-prd.md → core/commands/amend-prd.md} +205 -173
- package/core/commands/dev-run-test.md +47 -9
- package/core/commands/extend-prd.md +39 -12
- package/core/commands/generate-bdd.md +43 -4
- package/core/commands/generate-code.md +33 -0
- package/core/commands/generate-tech-docs.md +34 -2
- package/core/commands/qc-run-test.md +29 -3
- package/core/commands/refine-prd.md +13 -2
- package/core/commands/review-context.md +43 -8
- package/core/commands/sync.md +105 -1
- package/core/commands/validate-traces.md +284 -11
- package/core/rules/workflow.md +34 -0
- package/core/steps/context-loader.md +26 -5
- package/core/templates/feature.template +1 -1
- package/docs/02-concepts/architecture.md +36 -0
- package/docs/04-reference/commands.md +148 -134
- 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/28-sync.md +25 -0
- package/docs/explain/README.md +136 -135
- package/package.json +1 -8
- package/commands/debug.md +0 -529
- package/commands/debug.tmpl +0 -260
- package/commands/define-product.md +0 -438
- package/commands/define-product.tmpl +0 -225
- package/commands/dev-gen-test.md +0 -700
- package/commands/dev-gen-test.tmpl +0 -490
- package/commands/dev-run-test.md +0 -435
- package/commands/dev-run-test.tmpl +0 -225
- package/commands/dev-smoke-test.md +0 -374
- package/commands/dev-smoke-test.tmpl +0 -217
- package/commands/extend-prd.tmpl +0 -273
- package/commands/fix-bug.md +0 -519
- package/commands/fix-bug.tmpl +0 -197
- package/commands/generate-architecture.md +0 -354
- package/commands/generate-architecture.tmpl +0 -197
- package/commands/generate-bdd.md +0 -923
- package/commands/generate-bdd.tmpl +0 -590
- package/commands/generate-code.md +0 -859
- package/commands/generate-code.tmpl +0 -649
- package/commands/generate-design-spec.md +0 -737
- package/commands/generate-design-spec.tmpl +0 -524
- package/commands/generate-prd.md +0 -722
- package/commands/generate-prd.tmpl +0 -226
- package/commands/generate-spec-manifest.md +0 -321
- package/commands/generate-spec-manifest.tmpl +0 -164
- package/commands/generate-tech-docs.md +0 -920
- package/commands/generate-tech-docs.tmpl +0 -273
- package/commands/learn.md +0 -399
- package/commands/learn.tmpl +0 -130
- package/commands/map-testids.md +0 -238
- package/commands/map-testids.tmpl +0 -81
- package/commands/propose-scenario.md +0 -359
- package/commands/propose-scenario.tmpl +0 -202
- package/commands/qc-analyze.md +0 -269
- package/commands/qc-analyze.tmpl +0 -112
- package/commands/qc-design-test.md +0 -226
- package/commands/qc-design-test.tmpl +0 -69
- package/commands/qc-plan.md +0 -206
- package/commands/qc-plan.tmpl +0 -49
- package/commands/qc-report.md +0 -217
- package/commands/qc-report.tmpl +0 -60
- package/commands/qc-review.md +0 -210
- package/commands/qc-review.tmpl +0 -53
- package/commands/qc-run-test.md +0 -326
- package/commands/qc-run-test.tmpl +0 -116
- package/commands/refine-prd.md +0 -653
- package/commands/refine-prd.tmpl +0 -281
- package/commands/report-bug.md +0 -305
- package/commands/report-bug.tmpl +0 -148
- package/commands/review-code.md +0 -415
- package/commands/review-code.tmpl +0 -146
- package/commands/review-context.md +0 -902
- package/commands/review-context.tmpl +0 -530
- package/commands/review-tech-docs.md +0 -561
- package/commands/review-tech-docs.tmpl +0 -404
- package/commands/setup-ai-first.md +0 -602
- package/commands/setup-ai-first.tmpl +0 -450
- package/commands/sync.md +0 -430
- package/commands/sync.tmpl +0 -429
- package/commands/update-framework.md +0 -203
- package/commands/update-framework.tmpl +0 -202
- package/commands/validate-traces.md +0 -1077
- package/commands/validate-traces.tmpl +0 -920
- package/hooks/data-guard.js +0 -232
- package/hooks/settings.json +0 -19
- 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 -99
- 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 -112
- package/steps/context-loader.md +0 -406
- package/steps/gate.md +0 -151
- package/steps/report-footer.md +0 -125
- 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 -70
- package/templates/architecture.template.md +0 -394
- package/templates/ci/trace-gate.yml +0 -146
- package/templates/design-spec.template.md +0 -217
- package/templates/feature.template +0 -123
- package/templates/hooks/pre-push +0 -61
- 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/hooks/data-guard.js
DELETED
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* data-guard.js — Claude Code PreToolUse Hook
|
|
4
|
-
*
|
|
5
|
-
* Chặn AI đọc/ghi/thực thi trên file nhạy cảm (credential, secret, private key, .env…).
|
|
6
|
-
*
|
|
7
|
-
* Cài: copy vào project + đăng ký trong .claude/settings.json
|
|
8
|
-
* (mẫu: hooks/settings.json — hoặc dùng `npx @educa-corp/sdd-framework --hooks`)
|
|
9
|
-
*
|
|
10
|
-
* Exit code:
|
|
11
|
-
* 0 = cho phép
|
|
12
|
-
* 2 = chặn cứng (Claude Code hiểu mã này là block)
|
|
13
|
-
*
|
|
14
|
-
* ── VÌ SAO BẢN NÀY KHÁC BẢN ĐẦU (GAPS-v3 G42) ────────────────────────────────
|
|
15
|
-
*
|
|
16
|
-
* Bản đầu có ba lỗi độc lập; hai trong số đó chặn đúng công việc mà framework tồn
|
|
17
|
-
* tại để làm, và cái còn lại làm lời hứa bảo mật không đúng:
|
|
18
|
-
*
|
|
19
|
-
* (a) matcher thiếu `Grep` — `Grep` với output_mode:"content" trên `.env` TRẢ VỀ
|
|
20
|
-
* nội dung file và không đi qua hook. Nên câu "AI will be blocked from reading
|
|
21
|
-
* .env" là sai.
|
|
22
|
-
* (b) pattern soi CẢ PATH, không neo. `/password/i` khớp
|
|
23
|
-
* `specs/auth/forgot-password/UC1.feature` và `src/auth/PasswordResetController.java`
|
|
24
|
-
* ⇒ một framework sinh code từ spec KHÔNG LÀM NỔI feature auth khi bật hook
|
|
25
|
-
* của chính nó.
|
|
26
|
-
* (c) Bash soi cả command string ⇒ `git commit -m "feat: password reset UC1"` bị
|
|
27
|
-
* chặn — đúng câu commit mà các lệnh hướng dẫn chạy ở cuối pipeline.
|
|
28
|
-
*
|
|
29
|
-
* Cả hai đường đều dẫn tới cùng một kết cục: người dùng TẮT HOOK, và mất luôn phần
|
|
30
|
-
* bảo vệ thật. Một guard bị tắt bảo vệ bằng không.
|
|
31
|
-
*
|
|
32
|
-
* ── MÔ HÌNH MỚI ──────────────────────────────────────────────────────────────
|
|
33
|
-
*
|
|
34
|
-
* Secret sống trong file CẤU HÌNH/DỮ LIỆU, không sống trong file MÃ NGUỒN.
|
|
35
|
-
* `secrets.json` là kho bí mật; `PasswordResetController.java` là code.
|
|
36
|
-
* Nên pattern chung (secret/credential/password/token/api-key) chỉ áp cho file
|
|
37
|
-
* KHÔNG phải mã nguồn. Pattern cứng (.env, .pem, .key…) áp cho mọi file.
|
|
38
|
-
* Cộng thêm allowlist thư mục làm việc của framework (specs/, .trace/, docs/…).
|
|
39
|
-
*/
|
|
40
|
-
|
|
41
|
-
// ── Thư mục làm việc của framework — không bao giờ chứa secret thật ───────────
|
|
42
|
-
// Tên feature ("forgot-password", "api-key-rotation") hay khớp pattern chung, và
|
|
43
|
-
// đây chính là chỗ ca (b) nổ. Cho qua TRƯỚC khi soi.
|
|
44
|
-
const SAFE_DIR_PREFIXES = [
|
|
45
|
-
'specs/', '.trace/', '.trace-mirror/', '.living-docs/',
|
|
46
|
-
'docs/', '.agent/', 'feedback/', '.claude/',
|
|
47
|
-
];
|
|
48
|
-
|
|
49
|
-
// ── Đuôi file MÃ NGUỒN — pattern chung không áp ───────────────────────────────
|
|
50
|
-
// Một file .java/.ts/.dart tên gì đi nữa cũng là code, không phải kho secret.
|
|
51
|
-
// (Pattern CỨNG bên dưới vẫn áp — nhưng .pem/.key không nằm trong danh sách này.)
|
|
52
|
-
const CODE_EXT = new Set([
|
|
53
|
-
'java', 'kt', 'kts', 'scala', 'groovy',
|
|
54
|
-
'ts', 'tsx', 'js', 'jsx', 'mjs', 'cjs', 'vue', 'svelte',
|
|
55
|
-
'py', 'go', 'rs', 'rb', 'php', 'cs', 'fs', 'vb',
|
|
56
|
-
'swift', 'm', 'mm', 'dart', 'c', 'h', 'cpp', 'hpp', 'cc',
|
|
57
|
-
'sql', 'graphql', 'proto', 'feature', 'md', 'mdx', 'txt',
|
|
58
|
-
'html', 'css', 'scss', 'less', 'tsv', 'csv',
|
|
59
|
-
]);
|
|
60
|
-
|
|
61
|
-
// ── Pattern CỨNG — áp cho mọi file, soi TÊN FILE ─────────────────────────────
|
|
62
|
-
const SENSITIVE_NAME_HARD = [
|
|
63
|
-
/^\.env$/i,
|
|
64
|
-
/^\.env\./i,
|
|
65
|
-
/\.env$/i,
|
|
66
|
-
|
|
67
|
-
/\.key$/i,
|
|
68
|
-
/\.pem$/i,
|
|
69
|
-
/\.p12$/i,
|
|
70
|
-
/\.pfx$/i,
|
|
71
|
-
/\.jks$/i,
|
|
72
|
-
/\.keystore$/i,
|
|
73
|
-
/^id_rsa$/i,
|
|
74
|
-
/^id_ed25519$/i,
|
|
75
|
-
|
|
76
|
-
/^application-(prod|production|staging)\.(yml|yaml|properties)$/i,
|
|
77
|
-
/^appsettings\.(Production|Staging)\.json$/i,
|
|
78
|
-
/^database\.yml$/i,
|
|
79
|
-
/^master\.key$/i,
|
|
80
|
-
/^oauth-private\.key$/i,
|
|
81
|
-
/^credentials$/i,
|
|
82
|
-
/^\.npmrc$/i,
|
|
83
|
-
/^\.pypirc$/i,
|
|
84
|
-
/^\.netrc$/i,
|
|
85
|
-
];
|
|
86
|
-
|
|
87
|
-
// ── Pattern CHUNG — chỉ áp cho file KHÔNG phải mã nguồn, soi TÊN FILE ────────
|
|
88
|
-
const SENSITIVE_NAME_SOFT = [
|
|
89
|
-
/secret/i,
|
|
90
|
-
/credential/i,
|
|
91
|
-
/password/i,
|
|
92
|
-
/passwd/i,
|
|
93
|
-
/private[_-]?key/i,
|
|
94
|
-
/api[_-]?key/i,
|
|
95
|
-
/access[_-]?token/i,
|
|
96
|
-
/auth[_-]?token/i,
|
|
97
|
-
];
|
|
98
|
-
|
|
99
|
-
// ── Pattern THƯ MỤC — soi cả path ────────────────────────────────────────────
|
|
100
|
-
const SENSITIVE_DIR = [
|
|
101
|
-
/(^|\/)secrets?\//i,
|
|
102
|
-
/(^|\/)\.secrets?\//i,
|
|
103
|
-
/(^|\/)\.ssh\//i,
|
|
104
|
-
/(^|\/)\.aws\//i,
|
|
105
|
-
/(^|\/)\.gnupg\//i,
|
|
106
|
-
];
|
|
107
|
-
|
|
108
|
-
// ── Lệnh bash nguy hiểm bất kể path ──────────────────────────────────────────
|
|
109
|
-
const SENSITIVE_BASH = [
|
|
110
|
-
/\bprintenv\b/i,
|
|
111
|
-
/\benv\b\s*(\||$)/i,
|
|
112
|
-
/kubectl\s+get\s+secrets?\b[^|]*-o\s*(yaml|json)/i,
|
|
113
|
-
/\baws\s+secretsmanager\s+get-secret-value/i,
|
|
114
|
-
/\bgcloud\s+secrets\s+versions\s+access/i,
|
|
115
|
-
/\bvault\s+(read|kv\s+get)\b/i,
|
|
116
|
-
// `docker inspect` KHÔNG chặn cả cụm (lệnh debug thường dùng) — chỉ chặn khi nó
|
|
117
|
-
// thực sự moi Env ra. Bản đầu chặn cả cụm và đó là ma sát không đổi lấy gì.
|
|
118
|
-
/docker\s+inspect[^|]*\.Config\.Env/i,
|
|
119
|
-
];
|
|
120
|
-
|
|
121
|
-
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
122
|
-
|
|
123
|
-
function normalize(p) {
|
|
124
|
-
return String(p).replace(/\\/g, '/').replace(/^\.\//, '');
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function extOf(base) {
|
|
128
|
-
const i = base.lastIndexOf('.');
|
|
129
|
-
return i > 0 ? base.slice(i + 1).toLowerCase() : '';
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function isSensitivePath(filePath) {
|
|
133
|
-
if (!filePath) return false;
|
|
134
|
-
const p = normalize(filePath);
|
|
135
|
-
|
|
136
|
-
// Vùng làm việc của framework — spec/trace/doc không chứa secret thật, và tên
|
|
137
|
-
// feature ở đó hay khớp pattern chung. Bỏ cả tiền tố tuyệt đối trước khi so.
|
|
138
|
-
const relish = p.replace(/^([a-zA-Z]:)?\/+/, '');
|
|
139
|
-
if (SAFE_DIR_PREFIXES.some(d => relish.startsWith(d) || relish.includes('/' + d))) return false;
|
|
140
|
-
|
|
141
|
-
if (SENSITIVE_DIR.some(re => re.test(p))) return true;
|
|
142
|
-
|
|
143
|
-
const base = p.split('/').pop() || '';
|
|
144
|
-
if (SENSITIVE_NAME_HARD.some(re => re.test(base))) return true;
|
|
145
|
-
|
|
146
|
-
// Pattern chung: bỏ qua mã nguồn. Đây là chỗ bản đầu chặn PasswordResetController.java.
|
|
147
|
-
if (CODE_EXT.has(extOf(base))) return false;
|
|
148
|
-
return SENSITIVE_NAME_SOFT.some(re => re.test(base));
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Tách các token TRÔNG GIỐNG PATH ra khỏi một command line.
|
|
153
|
-
* Bản đầu soi cả chuỗi lệnh nên `git commit -m "feat: password reset"` bị chặn.
|
|
154
|
-
*/
|
|
155
|
-
function pathishTokens(command) {
|
|
156
|
-
return String(command)
|
|
157
|
-
.split(/[\s;|&()<>]+/)
|
|
158
|
-
.map(t => t.replace(/^["']|["']$/g, ''))
|
|
159
|
-
.filter(t => t && !t.startsWith('-') && /[\/.]/.test(t) && !/^-{1,2}/.test(t));
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
function block(reason, detail) {
|
|
163
|
-
console.error(`\n🔒 DATA GUARD — BLOCKED\n${reason}`);
|
|
164
|
-
if (detail) console.error(detail);
|
|
165
|
-
console.error('\nCần giá trị cấu hình? Mô tả thứ bạn cần mà KHÔNG đưa secret thật;');
|
|
166
|
-
console.error('dùng placeholder trong code sinh ra.');
|
|
167
|
-
console.error('Nghĩ đây là chặn nhầm? Vùng specs/ .trace/ docs/ .agent/ luôn được cho qua,');
|
|
168
|
-
console.error('và file mã nguồn (.java/.ts/.dart…) không bị pattern chung đụng tới.\n');
|
|
169
|
-
process.exit(2);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// ── Main ─────────────────────────────────────────────────────────────────────
|
|
173
|
-
|
|
174
|
-
let rawInput = '';
|
|
175
|
-
process.stdin.setEncoding('utf8');
|
|
176
|
-
process.stdin.on('data', chunk => { rawInput += chunk; });
|
|
177
|
-
process.stdin.on('end', () => {
|
|
178
|
-
let input;
|
|
179
|
-
try {
|
|
180
|
-
input = JSON.parse(rawInput);
|
|
181
|
-
} catch {
|
|
182
|
-
// Fail-open CÓ CHỦ Ý: hook parse lỗi mà chặn hết thì làm cả project đứng máy.
|
|
183
|
-
// Nhưng không im lặng — im lặng là cách một guard chết mà không ai biết.
|
|
184
|
-
console.error('⚠️ data-guard: không parse được input hook — CHO QUA (fail-open).');
|
|
185
|
-
process.exit(0);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
const tool = input.tool_name || '';
|
|
189
|
-
const arg = input.tool_input || {};
|
|
190
|
-
|
|
191
|
-
switch (tool) {
|
|
192
|
-
case 'Read':
|
|
193
|
-
case 'Write':
|
|
194
|
-
case 'Edit':
|
|
195
|
-
case 'NotebookEdit': {
|
|
196
|
-
const f = arg.file_path || arg.notebook_path || '';
|
|
197
|
-
if (isSensitivePath(f)) block(`Thao tác ${tool} trên file nhạy cảm: ${f}`);
|
|
198
|
-
break;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Grep ĐỌC ĐƯỢC NỘI DUNG (output_mode: "content"). Thiếu nhánh này thì mọi thứ
|
|
202
|
-
// ở trên chỉ là cửa trước, còn cửa sau mở toang — chính là lỗi (a) của G42.
|
|
203
|
-
case 'Grep': {
|
|
204
|
-
const target = arg.path || '';
|
|
205
|
-
if (target && isSensitivePath(target)) {
|
|
206
|
-
block(`Grep nhắm vào path nhạy cảm: ${target}`);
|
|
207
|
-
}
|
|
208
|
-
if (arg.glob && isSensitivePath(String(arg.glob).replace(/\*/g, 'x'))) {
|
|
209
|
-
block(`Grep dùng glob nhắm vào file nhạy cảm: ${arg.glob}`);
|
|
210
|
-
}
|
|
211
|
-
// Đang đi TÌM chính chuỗi secret — chặn kèm lý do khác hẳn.
|
|
212
|
-
if (arg.pattern && /\b(BEGIN [A-Z ]*PRIVATE KEY|aws_secret_access_key|sk-[A-Za-z0-9]{16,})/i
|
|
213
|
-
.test(String(arg.pattern))) {
|
|
214
|
-
block(`Grep đang tìm chính giá trị bí mật: ${String(arg.pattern).slice(0, 40)}…`);
|
|
215
|
-
}
|
|
216
|
-
break;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
case 'Bash': {
|
|
220
|
-
const cmd = arg.command || '';
|
|
221
|
-
if (SENSITIVE_BASH.some(re => re.test(cmd))) {
|
|
222
|
-
block(`Lệnh moi secret: ${cmd.slice(0, 120)}`);
|
|
223
|
-
}
|
|
224
|
-
// CHỈ soi token trông giống path — không soi cả chuỗi lệnh (lỗi (c) của G42).
|
|
225
|
-
const hit = pathishTokens(cmd).find(isSensitivePath);
|
|
226
|
-
if (hit) block(`Lệnh bash chạm file nhạy cảm: ${hit}`, ` (trong: ${cmd.slice(0, 120)})`);
|
|
227
|
-
break;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
process.exit(0);
|
|
232
|
-
});
|
package/hooks/settings.json
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"_comment": "Claude Code hook registration template. Copy this content into your project's .claude/settings.json",
|
|
3
|
-
"_matcher_note": "Grep BẮT BUỘC có trong matcher: Grep với output_mode:content ĐỌC ĐƯỢC nội dung file, nên thiếu nó thì việc chặn Read chỉ là cửa trước (GAPS-v3 G42a).",
|
|
4
|
-
"_docs": "https://docs.anthropic.com/claude/claude-code/hooks",
|
|
5
|
-
|
|
6
|
-
"hooks": {
|
|
7
|
-
"PreToolUse": [
|
|
8
|
-
{
|
|
9
|
-
"matcher": "Read|Write|Edit|Grep|NotebookEdit|Bash",
|
|
10
|
-
"hooks": [
|
|
11
|
-
{
|
|
12
|
-
"type": "command",
|
|
13
|
-
"command": "node .claude/hooks/data-guard.js"
|
|
14
|
-
}
|
|
15
|
-
]
|
|
16
|
-
}
|
|
17
|
-
]
|
|
18
|
-
}
|
|
19
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
name: "Android (Jetpack Compose)"
|
|
2
|
-
version: "1.0.0"
|
|
3
|
-
description: "Native Android development with Jetpack Compose + Kotlin"
|
|
4
|
-
language: "Kotlin"
|
|
5
|
-
framework: "Jetpack Compose"
|
|
6
|
-
stack_type: "mobile"
|
|
7
|
-
default_layer_order:
|
|
8
|
-
- Domain models
|
|
9
|
-
- Repository (data layer)
|
|
10
|
-
- UseCase (domain logic)
|
|
11
|
-
- ViewModel (StateFlow<UiState>)
|
|
12
|
-
- Composable screens (presentation)
|
|
13
|
-
test_framework: "JUnit5 + MockK + Turbine"
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
build:
|
|
2
|
-
compile: "./gradlew assembleRelease"
|
|
3
|
-
test: "./gradlew test"
|
|
4
|
-
run: "./gradlew installDebug / Open in Android Studio → Run"
|
|
5
|
-
lint: "./gradlew lint"
|
|
6
|
-
|
|
7
|
-
architecture:
|
|
8
|
-
style: "MVVM + Clean Architecture (Composable → ViewModel → UseCase → Repository)"
|
|
9
|
-
key_rules:
|
|
10
|
-
- "Composables are pure UI functions — no business logic, no direct suspend calls"
|
|
11
|
-
- "ViewModels expose StateFlow<UiState>; Composables collect via collectAsStateWithLifecycle()"
|
|
12
|
-
- "UseCases are single-responsibility classes injected into ViewModels"
|
|
13
|
-
- "Repositories are interfaces; implementations live in the data layer"
|
|
14
|
-
- "Dependency injection via Hilt"
|
|
15
|
-
- "Never launch coroutines from a Composable directly — use LaunchedEffect or ViewModel"
|
|
16
|
-
folder_structure: |
|
|
17
|
-
src/main/java/{package}/
|
|
18
|
-
├── core/
|
|
19
|
-
│ ├── network/ ← Retrofit instance, interceptors
|
|
20
|
-
│ ├── theme/ ← MaterialTheme, Color, Type, Shape
|
|
21
|
-
│ └── utils/
|
|
22
|
-
├── shared/
|
|
23
|
-
│ └── components/ ← reusable Composables (AppButton, AppTextField...)
|
|
24
|
-
├── features/
|
|
25
|
-
│ └── {domain}/
|
|
26
|
-
│ ├── ui/ ← Composable screens + components
|
|
27
|
-
│ ├── viewmodel/ ← ViewModel + UiState
|
|
28
|
-
│ ├── domain/ ← UseCases, domain models
|
|
29
|
-
│ └── data/ ← Repository impl, data sources
|
|
30
|
-
|
|
31
|
-
coding_standards:
|
|
32
|
-
naming:
|
|
33
|
-
composables: "PascalCase (e.g., OrderListScreen, CreateOrderForm)"
|
|
34
|
-
viewmodels: "PascalCase + ViewModel suffix (e.g., OrderListViewModel)"
|
|
35
|
-
usecases: "PascalCase + UseCase suffix (e.g., CreateOrderUseCase)"
|
|
36
|
-
files:
|
|
37
|
-
screen: "{Feature}Screen.kt"
|
|
38
|
-
viewmodel: "{Feature}ViewModel.kt"
|
|
39
|
-
usecase: "{Feature}UseCase.kt"
|
|
40
|
-
patterns:
|
|
41
|
-
state_management: "StateFlow<UiState> in ViewModel"
|
|
42
|
-
navigation: "Jetpack Navigation Compose"
|
|
43
|
-
networking: "Retrofit + OkHttp"
|
|
44
|
-
serialization: "Kotlinx Serialization or Gson"
|
|
45
|
-
di: "Hilt"
|
|
46
|
-
async: "Kotlin Coroutines + Flow"
|
|
47
|
-
|
|
48
|
-
testing:
|
|
49
|
-
unit: "JUnit5 + MockK + Turbine (Flow testing)"
|
|
50
|
-
ui: "Compose UI Test (composeTestRule)"
|
|
51
|
-
patterns:
|
|
52
|
-
- "Test ViewModel with fake repositories and TestCoroutineDispatcher"
|
|
53
|
-
- "UI tests use semantics matchers — set Modifier.testTag() on Composables"
|
|
54
|
-
|
|
55
|
-
trace_tags:
|
|
56
|
-
implements: "// @trace.implements={UC-ID}-SC{N}"
|
|
57
|
-
source: "// @trace.source=specs/{domain}/{prd-slug}/bdd/{platform}/{UC-ID}-{slug}.feature"
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
# Angular — Component Architecture Patterns
|
|
2
|
-
|
|
3
|
-
## Smart / Container Component Pattern
|
|
4
|
-
|
|
5
|
-
```typescript
|
|
6
|
-
// order-list.component.ts — Smart component: manages state, injects services
|
|
7
|
-
import { Component, OnInit, inject } from '@angular/core';
|
|
8
|
-
import { CommonModule } from '@angular/common';
|
|
9
|
-
import { OrderService } from '../services/order.service';
|
|
10
|
-
import { OrderListItemComponent } from './order-list-item.component';
|
|
11
|
-
import { Order } from '../models/order.model';
|
|
12
|
-
|
|
13
|
-
@Component({
|
|
14
|
-
selector: 'app-order-list',
|
|
15
|
-
standalone: true,
|
|
16
|
-
imports: [CommonModule, OrderListItemComponent],
|
|
17
|
-
template: `
|
|
18
|
-
<div class="order-list">
|
|
19
|
-
<app-order-list-item
|
|
20
|
-
*ngFor="let order of orders"
|
|
21
|
-
[order]="order"
|
|
22
|
-
(cancel)="onCancelOrder($event)"
|
|
23
|
-
/>
|
|
24
|
-
</div>
|
|
25
|
-
`
|
|
26
|
-
})
|
|
27
|
-
export class OrderListComponent implements OnInit {
|
|
28
|
-
private orderService = inject(OrderService);
|
|
29
|
-
orders: Order[] = [];
|
|
30
|
-
|
|
31
|
-
ngOnInit(): void {
|
|
32
|
-
this.orderService.getOrders().subscribe(orders => this.orders = orders);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
onCancelOrder(orderId: number): void {
|
|
36
|
-
this.orderService.cancelOrder(orderId).subscribe(() => {
|
|
37
|
-
this.orders = this.orders.filter(o => o.id !== orderId);
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Dumb / Presentational Component Pattern
|
|
44
|
-
|
|
45
|
-
```typescript
|
|
46
|
-
// order-list-item.component.ts — Dumb component: pure I/O, OnPush, no service injection
|
|
47
|
-
import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
|
|
48
|
-
import { Order } from '../models/order.model';
|
|
49
|
-
|
|
50
|
-
@Component({
|
|
51
|
-
selector: 'app-order-list-item',
|
|
52
|
-
standalone: true,
|
|
53
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
54
|
-
template: `
|
|
55
|
-
<div class="order-item">
|
|
56
|
-
<span>{{ order.id }}</span>
|
|
57
|
-
<span>{{ order.status }}</span>
|
|
58
|
-
<button (click)="cancel.emit(order.id)" [disabled]="order.status === 'CANCELLED'">
|
|
59
|
-
Cancel
|
|
60
|
-
</button>
|
|
61
|
-
</div>
|
|
62
|
-
`
|
|
63
|
-
})
|
|
64
|
-
export class OrderListItemComponent {
|
|
65
|
-
@Input({ required: true }) order!: Order;
|
|
66
|
-
@Output() cancel = new EventEmitter<number>();
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
## Service with HttpClient Pattern
|
|
71
|
-
|
|
72
|
-
```typescript
|
|
73
|
-
// order.service.ts
|
|
74
|
-
import { Injectable, inject } from '@angular/core';
|
|
75
|
-
import { HttpClient, HttpParams } from '@angular/common/http';
|
|
76
|
-
import { Observable } from 'rxjs';
|
|
77
|
-
import { Order, CreateOrderRequest, OrderResponse } from '../models/order.model';
|
|
78
|
-
import { environment } from '@env/environment';
|
|
79
|
-
|
|
80
|
-
@Injectable({ providedIn: 'root' })
|
|
81
|
-
export class OrderService {
|
|
82
|
-
private http = inject(HttpClient);
|
|
83
|
-
private baseUrl = `${environment.apiUrl}/v1/orders`;
|
|
84
|
-
|
|
85
|
-
getOrders(customerId?: number): Observable<Order[]> {
|
|
86
|
-
let params = new HttpParams();
|
|
87
|
-
if (customerId) params = params.set('customerId', customerId.toString());
|
|
88
|
-
return this.http.get<Order[]>(this.baseUrl, { params });
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
getOrder(id: number): Observable<Order> {
|
|
92
|
-
return this.http.get<Order>(`${this.baseUrl}/${id}`);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
createOrder(request: CreateOrderRequest): Observable<OrderResponse> {
|
|
96
|
-
return this.http.post<OrderResponse>(this.baseUrl, request);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
cancelOrder(id: number): Observable<void> {
|
|
100
|
-
return this.http.patch<void>(`${this.baseUrl}/${id}/cancel`, {});
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## Signal-Based State Pattern (Angular 17+)
|
|
106
|
-
|
|
107
|
-
```typescript
|
|
108
|
-
// order.store.ts — using Angular Signals for state management
|
|
109
|
-
import { Injectable, signal, computed } from '@angular/core';
|
|
110
|
-
import { Order } from '../models/order.model';
|
|
111
|
-
|
|
112
|
-
@Injectable({ providedIn: 'root' })
|
|
113
|
-
export class OrderStore {
|
|
114
|
-
private _orders = signal<Order[]>([]);
|
|
115
|
-
private _loading = signal(false);
|
|
116
|
-
private _error = signal<string | null>(null);
|
|
117
|
-
|
|
118
|
-
// Public readable signals
|
|
119
|
-
readonly orders = this._orders.asReadonly();
|
|
120
|
-
readonly loading = this._loading.asReadonly();
|
|
121
|
-
readonly error = this._error.asReadonly();
|
|
122
|
-
|
|
123
|
-
// Computed signals
|
|
124
|
-
readonly pendingOrders = computed(() =>
|
|
125
|
-
this._orders().filter(o => o.status === 'PENDING')
|
|
126
|
-
);
|
|
127
|
-
readonly orderCount = computed(() => this._orders().length);
|
|
128
|
-
|
|
129
|
-
setOrders(orders: Order[]): void {
|
|
130
|
-
this._orders.set(orders);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
setLoading(loading: boolean): void {
|
|
134
|
-
this._loading.set(loading);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
setError(error: string | null): void {
|
|
138
|
-
this._error.set(error);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
removeOrder(id: number): void {
|
|
142
|
-
this._orders.update(orders => orders.filter(o => o.id !== id));
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
## Route Guard Pattern
|
|
148
|
-
|
|
149
|
-
```typescript
|
|
150
|
-
// auth.guard.ts
|
|
151
|
-
import { inject } from '@angular/core';
|
|
152
|
-
import { CanActivateFn, Router } from '@angular/router';
|
|
153
|
-
import { AuthService } from '../services/auth.service';
|
|
154
|
-
|
|
155
|
-
export const authGuard: CanActivateFn = (route, state) => {
|
|
156
|
-
const auth = inject(AuthService);
|
|
157
|
-
const router = inject(Router);
|
|
158
|
-
|
|
159
|
-
if (auth.isAuthenticated()) {
|
|
160
|
-
return true;
|
|
161
|
-
}
|
|
162
|
-
return router.createUrlTree(['/login'], { queryParams: { returnUrl: state.url } });
|
|
163
|
-
};
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
## Standalone Component with Lazy Loading
|
|
167
|
-
|
|
168
|
-
```typescript
|
|
169
|
-
// app.routes.ts
|
|
170
|
-
import { Routes } from '@angular/router';
|
|
171
|
-
import { authGuard } from './guards/auth.guard';
|
|
172
|
-
|
|
173
|
-
export const APP_ROUTES: Routes = [
|
|
174
|
-
{
|
|
175
|
-
path: 'orders',
|
|
176
|
-
canActivate: [authGuard],
|
|
177
|
-
loadComponent: () =>
|
|
178
|
-
import('./features/orders/order-list.component').then(m => m.OrderListComponent)
|
|
179
|
-
},
|
|
180
|
-
{
|
|
181
|
-
path: 'orders/:id',
|
|
182
|
-
canActivate: [authGuard],
|
|
183
|
-
loadComponent: () =>
|
|
184
|
-
import('./features/orders/order-detail.component').then(m => m.OrderDetailComponent)
|
|
185
|
-
}
|
|
186
|
-
];
|
|
187
|
-
```
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
build:
|
|
2
|
-
compile: "ng build"
|
|
3
|
-
test: "ng test --watch=false"
|
|
4
|
-
run: "ng serve"
|
|
5
|
-
|
|
6
|
-
architecture:
|
|
7
|
-
style: "Component → Service → HTTP Client → Backend API"
|
|
8
|
-
key_rules:
|
|
9
|
-
- "Smart (container) components manage state and inject services"
|
|
10
|
-
- "Dumb (presentational) components receive data via @Input and emit via @Output"
|
|
11
|
-
- "Business logic lives in services, not in component classes"
|
|
12
|
-
- "Use OnPush change detection for all pure presentational components"
|
|
13
|
-
- "HTTP calls must be in services, never in component files"
|
|
14
|
-
|
|
15
|
-
coding_standards:
|
|
16
|
-
naming:
|
|
17
|
-
components: "PascalCase + Component suffix (e.g., OrderListComponent)"
|
|
18
|
-
services: "PascalCase + Service suffix (e.g., OrderService)"
|
|
19
|
-
pipes: "PascalCase + Pipe suffix (e.g., CurrencyFormatPipe)"
|
|
20
|
-
directives: "PascalCase + Directive suffix (e.g., HighlightDirective)"
|
|
21
|
-
guards: "PascalCase + Guard suffix (e.g., AuthGuard)"
|
|
22
|
-
files:
|
|
23
|
-
component: "{feature}.component.ts / .html / .scss"
|
|
24
|
-
service: "{feature}.service.ts"
|
|
25
|
-
model: "{feature}.model.ts"
|
|
26
|
-
store: "{feature}.store.ts"
|
|
27
|
-
patterns:
|
|
28
|
-
state_management: "NgRx (complex) or Angular Signals (simple/medium)"
|
|
29
|
-
http_error_handling: "HttpInterceptor catches 4xx/5xx globally"
|
|
30
|
-
lazy_loading: "All feature modules must be lazily loaded"
|
|
31
|
-
|
|
32
|
-
testing:
|
|
33
|
-
unit: "Jasmine + Karma or Jest"
|
|
34
|
-
e2e: "Cypress or Playwright"
|
|
35
|
-
patterns:
|
|
36
|
-
- "Use TestBed.configureTestingModule for component tests"
|
|
37
|
-
- "Mock services with jasmine.createSpyObj or jest.fn()"
|
|
38
|
-
- "Test component DOM via DebugElement and By.css selectors"
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
# Context Engineering — Design Templates and Patterns
|
|
2
|
-
|
|
3
|
-
## System Context Design Template
|
|
4
|
-
|
|
5
|
-
```markdown
|
|
6
|
-
# System Context: {Agent Name}
|
|
7
|
-
|
|
8
|
-
## Role
|
|
9
|
-
You are {role description}. You help {target user} to {primary purpose}.
|
|
10
|
-
|
|
11
|
-
## Scope
|
|
12
|
-
In scope:
|
|
13
|
-
- {capability 1}
|
|
14
|
-
- {capability 2}
|
|
15
|
-
|
|
16
|
-
Out of scope (do not attempt):
|
|
17
|
-
- {excluded capability 1}
|
|
18
|
-
- {excluded capability 2}
|
|
19
|
-
|
|
20
|
-
## Output Format
|
|
21
|
-
Always respond with:
|
|
22
|
-
- {format requirement 1, e.g., "structured YAML when producing artifacts"}
|
|
23
|
-
- {format requirement 2, e.g., "numbered steps for procedural instructions"}
|
|
24
|
-
- {format requirement 3, e.g., "a CHECKPOINT before any destructive action"}
|
|
25
|
-
|
|
26
|
-
## Constraints
|
|
27
|
-
- {constraint 1, e.g., "Never make changes without explicit user confirmation"}
|
|
28
|
-
- {constraint 2, e.g., "Always cite source files when referencing code"}
|
|
29
|
-
|
|
30
|
-
## Tools Available
|
|
31
|
-
- {tool name}: {what it does and when to use it}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Context Layering: Persistent vs Ephemeral
|
|
35
|
-
|
|
36
|
-
```
|
|
37
|
-
┌─────────────────────────────────────────────────┐
|
|
38
|
-
│ PERSISTENT (system prompt — stable, pre-loaded) │
|
|
39
|
-
│ - Role and persona │
|
|
40
|
-
│ - Output format requirements │
|
|
41
|
-
│ - Constraint rules │
|
|
42
|
-
│ - Domain knowledge (project context) │
|
|
43
|
-
└────────────────────┬────────────────────────────┘
|
|
44
|
-
│ passed once at session start
|
|
45
|
-
┌────────────────────▼────────────────────────────┐
|
|
46
|
-
│ SESSION (loaded once per task) │
|
|
47
|
-
│ - Project-context.yaml │
|
|
48
|
-
│ - CLAUDE.md │
|
|
49
|
-
│ - Business dictionary │
|
|
50
|
-
└────────────────────┬────────────────────────────┘
|
|
51
|
-
│ loaded on demand
|
|
52
|
-
┌────────────────────▼────────────────────────────┐
|
|
53
|
-
│ EPHEMERAL (per-turn, discarded after use) │
|
|
54
|
-
│ - Tool results │
|
|
55
|
-
│ - File contents read mid-task │
|
|
56
|
-
│ - User clarification answers │
|
|
57
|
-
└─────────────────────────────────────────────────┘
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## Context Handoff Between Agents
|
|
61
|
-
|
|
62
|
-
When passing work from one agent to another, include a structured handoff payload:
|
|
63
|
-
|
|
64
|
-
```yaml
|
|
65
|
-
# Agent Handoff Payload
|
|
66
|
-
handoff_from: "{source agent name}"
|
|
67
|
-
handoff_to: "{target agent name}"
|
|
68
|
-
task_id: "{unique task identifier}"
|
|
69
|
-
status: "partial_complete" # pending | partial_complete | blocked | ready_for_review
|
|
70
|
-
|
|
71
|
-
# What was accomplished
|
|
72
|
-
completed:
|
|
73
|
-
- "{step 1 done}"
|
|
74
|
-
- "{step 2 done}"
|
|
75
|
-
|
|
76
|
-
# What the next agent must do
|
|
77
|
-
pending:
|
|
78
|
-
- "{step 3 to do}"
|
|
79
|
-
- "{step 4 to do}"
|
|
80
|
-
|
|
81
|
-
# Decisions made (so next agent doesn't re-litigate)
|
|
82
|
-
decisions:
|
|
83
|
-
- decision: "{what was decided}"
|
|
84
|
-
rationale: "{why}"
|
|
85
|
-
|
|
86
|
-
# Artifacts produced (file paths)
|
|
87
|
-
artifacts:
|
|
88
|
-
- path: "{file path}"
|
|
89
|
-
type: "{type: spec | code | test | report}"
|
|
90
|
-
status: "{draft | approved | final}"
|
|
91
|
-
|
|
92
|
-
# Context the next agent needs immediately
|
|
93
|
-
context_snapshot:
|
|
94
|
-
project_name: "{name}"
|
|
95
|
-
domain: "{domain}"
|
|
96
|
-
uc_id: "{UC-ID}"
|
|
97
|
-
tech_stack: "{stack}"
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
## Context Compression Pattern
|
|
101
|
-
|
|
102
|
-
When conversation history grows large, compress before the next turn:
|
|
103
|
-
|
|
104
|
-
```
|
|
105
|
-
CONTEXT SUMMARY (replaces N previous turns):
|
|
106
|
-
Task: {what we are doing}
|
|
107
|
-
Progress: {what has been completed so far}
|
|
108
|
-
Current state: {where we are now}
|
|
109
|
-
Key decisions: {decisions that must not be reversed}
|
|
110
|
-
Pending: {what still needs to be done}
|
|
111
|
-
Files produced: {list of artifact paths}
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
Compression rules:
|
|
115
|
-
1. Keep all decisions and their rationale.
|
|
116
|
-
2. Keep all file paths that were created.
|
|
117
|
-
3. Drop intermediate reasoning that led to a confirmed decision.
|
|
118
|
-
4. Keep any user corrections or explicit preferences.
|
|
119
|
-
5. Keep any open questions that are still unresolved.
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
name: "Context Engineering"
|
|
2
|
-
version: "1.0.0"
|
|
3
|
-
description: "AI context design, prompt engineering, and system context workflows"
|
|
4
|
-
stack_type: "ai-first"
|
|
5
|
-
use_cases:
|
|
6
|
-
- "Designing AI system contexts"
|
|
7
|
-
- "Reverse engineering existing prompts"
|
|
8
|
-
- "Context window optimization"
|
|
9
|
-
- "Multi-agent coordination"
|