oh-my-customcode 0.9.3 → 0.9.4
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/README.md +1 -14
- package/dist/cli/index.js +1107 -842
- package/dist/index.js +250 -17
- package/package.json +1 -1
- package/templates/.claude/agents/arch-documenter.md +7 -71
- package/templates/.claude/agents/arch-speckit-agent.md +21 -108
- package/templates/.claude/agents/be-express-expert.md +8 -58
- package/templates/.claude/agents/be-nestjs-expert.md +6 -38
- package/templates/.claude/agents/be-springboot-expert.md +11 -56
- package/templates/.claude/agents/db-postgres-expert.md +10 -80
- package/templates/.claude/agents/db-redis-expert.md +10 -75
- package/templates/.claude/agents/db-supabase-expert.md +12 -48
- package/templates/.claude/agents/de-airflow-expert.md +8 -45
- package/templates/.claude/agents/de-dbt-expert.md +8 -46
- package/templates/.claude/agents/de-kafka-expert.md +10 -10
- package/templates/.claude/agents/de-pipeline-expert.md +9 -69
- package/templates/.claude/agents/de-snowflake-expert.md +9 -62
- package/templates/.claude/agents/de-spark-expert.md +10 -54
- package/templates/.claude/agents/fe-svelte-agent.md +5 -41
- package/templates/.claude/agents/fe-vercel-agent.md +9 -41
- package/templates/.claude/agents/fe-vuejs-agent.md +7 -42
- package/templates/.claude/agents/lang-java21-expert.md +11 -37
- package/templates/.claude/agents/mgr-claude-code-bible.md +22 -207
- package/templates/.claude/agents/mgr-creator.md +7 -88
- package/templates/.claude/agents/mgr-gitnerd.md +8 -76
- package/templates/.claude/agents/mgr-sauron.md +27 -20
- package/templates/.claude/agents/mgr-supplier.md +11 -96
- package/templates/.claude/agents/mgr-sync-checker.md +9 -70
- package/templates/.claude/agents/mgr-updater.md +9 -79
- package/templates/.claude/agents/qa-engineer.md +8 -72
- package/templates/.claude/agents/qa-planner.md +2 -3
- package/templates/.claude/agents/qa-writer.md +6 -76
- package/templates/.claude/agents/sys-memory-keeper.md +13 -87
- package/templates/.claude/agents/sys-naggy.md +9 -62
- package/templates/.claude/agents/tool-bun-expert.md +7 -52
- package/templates/.claude/agents/tool-npm-expert.md +6 -64
- package/templates/.claude/agents/tool-optimizer.md +7 -60
- package/templates/.claude/rules/MAY-optimization.md +16 -80
- package/templates/.claude/rules/MUST-agent-design.md +29 -134
- package/templates/.claude/rules/MUST-agent-identification.md +9 -88
- package/templates/.claude/rules/MUST-continuous-improvement.md +10 -117
- package/templates/.claude/rules/MUST-intent-transparency.md +14 -171
- package/templates/.claude/rules/MUST-language-policy.md +11 -46
- package/templates/.claude/rules/MUST-orchestrator-coordination.md +82 -425
- package/templates/.claude/rules/MUST-parallel-execution.md +33 -405
- package/templates/.claude/rules/MUST-permissions.md +14 -68
- package/templates/.claude/rules/MUST-safety.md +11 -57
- package/templates/.claude/rules/MUST-sync-verification.md +49 -205
- package/templates/.claude/rules/MUST-tool-identification.md +21 -134
- package/templates/.claude/rules/SHOULD-agent-teams.md +22 -166
- package/templates/.claude/rules/SHOULD-ecomode.md +15 -123
- package/templates/.claude/rules/SHOULD-error-handling.md +19 -88
- package/templates/.claude/rules/SHOULD-hud-statusline.md +9 -89
- package/templates/.claude/rules/SHOULD-interaction.md +18 -87
- package/templates/.claude/rules/SHOULD-memory-integration.md +25 -118
- package/templates/.claude/skills/dev-lead-routing/SKILL.md +70 -243
- package/templates/.claude/skills/springboot-best-practices/SKILL.md +180 -319
- package/templates/.codex/agents/arch-documenter.md +7 -71
- package/templates/.codex/agents/arch-speckit-agent.md +21 -108
- package/templates/.codex/agents/be-express-expert.md +8 -58
- package/templates/.codex/agents/be-nestjs-expert.md +6 -38
- package/templates/.codex/agents/be-springboot-expert.md +11 -56
- package/templates/.codex/agents/db-postgres-expert.md +10 -80
- package/templates/.codex/agents/db-redis-expert.md +10 -75
- package/templates/.codex/agents/db-supabase-expert.md +12 -48
- package/templates/.codex/agents/de-airflow-expert.md +8 -45
- package/templates/.codex/agents/de-dbt-expert.md +8 -46
- package/templates/.codex/agents/de-kafka-expert.md +10 -10
- package/templates/.codex/agents/de-pipeline-expert.md +9 -69
- package/templates/.codex/agents/de-snowflake-expert.md +9 -62
- package/templates/.codex/agents/de-spark-expert.md +10 -54
- package/templates/.codex/agents/fe-svelte-agent.md +5 -41
- package/templates/.codex/agents/fe-vercel-agent.md +9 -41
- package/templates/.codex/agents/fe-vuejs-agent.md +7 -42
- package/templates/.codex/agents/infra-aws-expert.md +1 -1
- package/templates/.codex/agents/infra-docker-expert.md +1 -1
- package/templates/.codex/agents/lang-java21-expert.md +11 -37
- package/templates/.codex/agents/mgr-claude-code-bible.md +25 -210
- package/templates/.codex/agents/mgr-creator.md +7 -88
- package/templates/.codex/agents/mgr-gitnerd.md +8 -76
- package/templates/.codex/agents/mgr-sauron.md +30 -23
- package/templates/.codex/agents/mgr-supplier.md +11 -96
- package/templates/.codex/agents/mgr-sync-checker.md +12 -73
- package/templates/.codex/agents/mgr-updater.md +9 -79
- package/templates/.codex/agents/qa-engineer.md +8 -72
- package/templates/.codex/agents/qa-planner.md +2 -3
- package/templates/.codex/agents/qa-writer.md +6 -76
- package/templates/.codex/agents/sys-memory-keeper.md +13 -87
- package/templates/.codex/agents/sys-naggy.md +9 -62
- package/templates/.codex/agents/tool-bun-expert.md +7 -52
- package/templates/.codex/agents/tool-npm-expert.md +6 -64
- package/templates/.codex/agents/tool-optimizer.md +7 -60
- package/templates/.codex/codex-native-hash.txt +1 -0
- package/templates/.codex/rules/MAY-optimization.md +16 -80
- package/templates/.codex/rules/MUST-agent-design.md +29 -134
- package/templates/.codex/rules/MUST-agent-identification.md +9 -88
- package/templates/.codex/rules/MUST-continuous-improvement.md +10 -117
- package/templates/.codex/rules/MUST-intent-transparency.md +14 -171
- package/templates/.codex/rules/MUST-language-policy.md +11 -46
- package/templates/.codex/rules/MUST-orchestrator-coordination.md +82 -425
- package/templates/.codex/rules/MUST-parallel-execution.md +33 -405
- package/templates/.codex/rules/MUST-permissions.md +14 -68
- package/templates/.codex/rules/MUST-safety.md +11 -57
- package/templates/.codex/rules/MUST-sync-verification.md +58 -214
- package/templates/.codex/rules/MUST-tool-identification.md +22 -135
- package/templates/.codex/rules/SHOULD-agent-teams.md +22 -166
- package/templates/.codex/rules/SHOULD-ecomode.md +15 -123
- package/templates/.codex/rules/SHOULD-error-handling.md +19 -88
- package/templates/.codex/rules/SHOULD-hud-statusline.md +9 -89
- package/templates/.codex/rules/SHOULD-interaction.md +18 -87
- package/templates/.codex/rules/SHOULD-memory-integration.md +25 -118
- package/templates/.codex/skills/dev-lead-routing/SKILL.md +70 -243
- package/templates/.codex/skills/springboot-best-practices/SKILL.md +180 -319
package/dist/index.js
CHANGED
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
8
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
|
+
for (let key of __getOwnPropNames(mod))
|
|
11
|
+
if (!__hasOwnProp.call(to, key))
|
|
12
|
+
__defProp(to, key, {
|
|
13
|
+
get: () => mod[key],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
2
18
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
19
|
|
|
4
20
|
// src/core/config.ts
|
|
5
21
|
import { join as join2 } from "node:path";
|
|
6
22
|
|
|
7
23
|
// src/utils/fs.ts
|
|
8
|
-
import { dirname, join, resolve } from "node:path";
|
|
24
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
9
25
|
import { fileURLToPath } from "node:url";
|
|
10
26
|
async function fileExists(path) {
|
|
11
27
|
const fs = await import("node:fs/promises");
|
|
@@ -70,6 +86,25 @@ async function handleFile(srcPath, destPath, options, fs) {
|
|
|
70
86
|
await fs.utimes(destPath, stats.atime, stats.mtime);
|
|
71
87
|
}
|
|
72
88
|
}
|
|
89
|
+
function shouldSkipPath(destPath, destRoot, skipPaths) {
|
|
90
|
+
if (!skipPaths || skipPaths.length === 0) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
const relativePath = relative(destRoot, destPath);
|
|
94
|
+
for (const skipPath of skipPaths) {
|
|
95
|
+
if (skipPath.endsWith("/")) {
|
|
96
|
+
const dirPath = skipPath.slice(0, -1);
|
|
97
|
+
if (relativePath === dirPath || relativePath.startsWith(dirPath + sep)) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
if (relativePath === skipPath) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
73
108
|
async function copyDirectory(src, dest, options = {}) {
|
|
74
109
|
const fs = await import("node:fs/promises");
|
|
75
110
|
const path = await import("node:path");
|
|
@@ -81,6 +116,9 @@ async function copyDirectory(src, dest, options = {}) {
|
|
|
81
116
|
}
|
|
82
117
|
const srcPath = path.join(src, entry.name);
|
|
83
118
|
const destPath = path.join(dest, entry.name);
|
|
119
|
+
if (shouldSkipPath(destPath, dest, options.skipPaths)) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
84
122
|
if (entry.isSymbolicLink()) {
|
|
85
123
|
await handleSymlink(srcPath, destPath, options, fs);
|
|
86
124
|
} else if (entry.isDirectory()) {
|
|
@@ -100,6 +138,15 @@ async function writeJsonFile(path, data) {
|
|
|
100
138
|
const content = JSON.stringify(data, null, 2);
|
|
101
139
|
await fs.writeFile(path, content, "utf-8");
|
|
102
140
|
}
|
|
141
|
+
async function readTextFile(path) {
|
|
142
|
+
const fs = await import("node:fs/promises");
|
|
143
|
+
return fs.readFile(path, "utf-8");
|
|
144
|
+
}
|
|
145
|
+
async function writeTextFile(path, content) {
|
|
146
|
+
const fs = await import("node:fs/promises");
|
|
147
|
+
await ensureDirectory(dirname(path));
|
|
148
|
+
await fs.writeFile(path, content, "utf-8");
|
|
149
|
+
}
|
|
103
150
|
function getPackageRoot() {
|
|
104
151
|
const currentFile = fileURLToPath(import.meta.url);
|
|
105
152
|
const currentDir = dirname(currentFile);
|
|
@@ -333,7 +380,9 @@ function getDefaultConfig() {
|
|
|
333
380
|
enabled: false,
|
|
334
381
|
checkIntervalHours: 24,
|
|
335
382
|
autoApplyMinor: false
|
|
336
|
-
}
|
|
383
|
+
},
|
|
384
|
+
preserveFiles: [],
|
|
385
|
+
customComponents: []
|
|
337
386
|
};
|
|
338
387
|
}
|
|
339
388
|
function getDefaultPreferences() {
|
|
@@ -375,6 +424,13 @@ async function saveConfig(targetDir, config) {
|
|
|
375
424
|
await writeJsonFile(configPath, config);
|
|
376
425
|
debug("config.saved", { path: configPath });
|
|
377
426
|
}
|
|
427
|
+
function deduplicateCustomComponents(components) {
|
|
428
|
+
const seen = new Map;
|
|
429
|
+
for (const c of components) {
|
|
430
|
+
seen.set(c.path, c);
|
|
431
|
+
}
|
|
432
|
+
return [...seen.values()];
|
|
433
|
+
}
|
|
378
434
|
function mergeConfig(defaults, overrides) {
|
|
379
435
|
return {
|
|
380
436
|
...defaults,
|
|
@@ -388,7 +444,12 @@ function mergeConfig(defaults, overrides) {
|
|
|
388
444
|
agents: {
|
|
389
445
|
...defaults.agents,
|
|
390
446
|
...overrides.agents
|
|
391
|
-
}
|
|
447
|
+
},
|
|
448
|
+
preserveFiles: overrides.preserveFiles ? [...new Set([...defaults.preserveFiles || [], ...overrides.preserveFiles])] : defaults.preserveFiles,
|
|
449
|
+
customComponents: overrides.customComponents ? deduplicateCustomComponents([
|
|
450
|
+
...defaults.customComponents || [],
|
|
451
|
+
...overrides.customComponents
|
|
452
|
+
]) : defaults.customComponents
|
|
392
453
|
};
|
|
393
454
|
}
|
|
394
455
|
function migrateConfig(config) {
|
|
@@ -839,6 +900,98 @@ async function detectProvider(options = {}) {
|
|
|
839
900
|
}
|
|
840
901
|
// src/core/updater.ts
|
|
841
902
|
import { join as join5 } from "node:path";
|
|
903
|
+
|
|
904
|
+
// src/core/entry-merger.ts
|
|
905
|
+
var MANAGED_START = "<!-- omcustom:start -->";
|
|
906
|
+
var MANAGED_END = "<!-- omcustom:end -->";
|
|
907
|
+
function parseEntryDoc(content) {
|
|
908
|
+
const sections = [];
|
|
909
|
+
const lines = content.split(`
|
|
910
|
+
`);
|
|
911
|
+
let currentSection = null;
|
|
912
|
+
let currentLines = [];
|
|
913
|
+
for (const line of lines) {
|
|
914
|
+
if (line.trim() === MANAGED_START) {
|
|
915
|
+
if (currentLines.length > 0) {
|
|
916
|
+
sections.push({
|
|
917
|
+
type: "custom",
|
|
918
|
+
content: currentLines.join(`
|
|
919
|
+
`)
|
|
920
|
+
});
|
|
921
|
+
currentLines = [];
|
|
922
|
+
}
|
|
923
|
+
currentSection = { type: "managed", content: "" };
|
|
924
|
+
continue;
|
|
925
|
+
}
|
|
926
|
+
if (line.trim() === MANAGED_END) {
|
|
927
|
+
if (currentSection && currentSection.type === "managed") {
|
|
928
|
+
currentSection.content = currentLines.join(`
|
|
929
|
+
`);
|
|
930
|
+
sections.push(currentSection);
|
|
931
|
+
currentSection = null;
|
|
932
|
+
currentLines = [];
|
|
933
|
+
}
|
|
934
|
+
continue;
|
|
935
|
+
}
|
|
936
|
+
currentLines.push(line);
|
|
937
|
+
}
|
|
938
|
+
if (currentLines.length > 0) {
|
|
939
|
+
sections.push({
|
|
940
|
+
type: "custom",
|
|
941
|
+
content: currentLines.join(`
|
|
942
|
+
`)
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
return { sections };
|
|
946
|
+
}
|
|
947
|
+
function mergeEntryDoc(existingContent, templateContent) {
|
|
948
|
+
const warnings = [];
|
|
949
|
+
const { sections } = parseEntryDoc(existingContent);
|
|
950
|
+
const hasManagedSections = sections.some((s) => s.type === "managed");
|
|
951
|
+
if (!hasManagedSections) {
|
|
952
|
+
const wrapped = wrapInManagedMarkers(templateContent);
|
|
953
|
+
return {
|
|
954
|
+
content: wrapped,
|
|
955
|
+
managedSections: 1,
|
|
956
|
+
customSections: 0,
|
|
957
|
+
warnings: ["No managed sections found in existing content, wrapping template entirely"]
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
const mergedSections = [];
|
|
961
|
+
let managedCount = 0;
|
|
962
|
+
let customCount = 0;
|
|
963
|
+
let templateInserted = false;
|
|
964
|
+
for (const section of sections) {
|
|
965
|
+
if (section.type === "managed") {
|
|
966
|
+
if (!templateInserted) {
|
|
967
|
+
mergedSections.push(MANAGED_START);
|
|
968
|
+
mergedSections.push(templateContent);
|
|
969
|
+
mergedSections.push(MANAGED_END);
|
|
970
|
+
templateInserted = true;
|
|
971
|
+
managedCount++;
|
|
972
|
+
} else {
|
|
973
|
+
warnings.push("Multiple managed sections found, keeping only the first one");
|
|
974
|
+
}
|
|
975
|
+
} else {
|
|
976
|
+
mergedSections.push(section.content);
|
|
977
|
+
customCount++;
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
return {
|
|
981
|
+
content: mergedSections.join(`
|
|
982
|
+
`),
|
|
983
|
+
managedSections: managedCount,
|
|
984
|
+
customSections: customCount,
|
|
985
|
+
warnings
|
|
986
|
+
};
|
|
987
|
+
}
|
|
988
|
+
function wrapInManagedMarkers(content) {
|
|
989
|
+
return `${MANAGED_START}
|
|
990
|
+
${content}
|
|
991
|
+
${MANAGED_END}`;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
// src/core/updater.ts
|
|
842
995
|
var CUSTOMIZATION_MANIFEST_FILE = ".omcustom-customizations.json";
|
|
843
996
|
function createUpdateResult() {
|
|
844
997
|
return {
|
|
@@ -885,6 +1038,75 @@ async function updateAllComponents(targetDir, provider, components, updateCheck,
|
|
|
885
1038
|
await processComponentUpdate(targetDir, provider, component, updateCheck, customizations, options, result);
|
|
886
1039
|
}
|
|
887
1040
|
}
|
|
1041
|
+
function getEntryTemplateName2(provider, language) {
|
|
1042
|
+
const layout = getProviderLayout(provider);
|
|
1043
|
+
const baseName = layout.entryFile.replace(".md", "");
|
|
1044
|
+
return language === "ko" ? `${baseName}.md.ko` : `${baseName}.md.en`;
|
|
1045
|
+
}
|
|
1046
|
+
async function backupFile(filePath) {
|
|
1047
|
+
const fs = await import("node:fs/promises");
|
|
1048
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
1049
|
+
const backupPath = `${filePath}.backup-${timestamp}`;
|
|
1050
|
+
if (await fileExists(filePath)) {
|
|
1051
|
+
await fs.copyFile(filePath, backupPath);
|
|
1052
|
+
debug("update.file_backed_up", { path: filePath, backup: backupPath });
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
function resolveCustomizations(customizations, configPreserveFiles) {
|
|
1056
|
+
if (!customizations && configPreserveFiles.length === 0) {
|
|
1057
|
+
return null;
|
|
1058
|
+
}
|
|
1059
|
+
if (customizations && configPreserveFiles.length > 0) {
|
|
1060
|
+
customizations.preserveFiles = [
|
|
1061
|
+
...new Set([...customizations.preserveFiles, ...configPreserveFiles])
|
|
1062
|
+
];
|
|
1063
|
+
return customizations;
|
|
1064
|
+
}
|
|
1065
|
+
if (configPreserveFiles.length > 0) {
|
|
1066
|
+
return {
|
|
1067
|
+
modifiedFiles: [],
|
|
1068
|
+
preserveFiles: configPreserveFiles,
|
|
1069
|
+
customComponents: [],
|
|
1070
|
+
lastUpdated: new Date().toISOString()
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
1073
|
+
return customizations;
|
|
1074
|
+
}
|
|
1075
|
+
async function updateEntryDoc(targetDir, provider, config, options) {
|
|
1076
|
+
const layout = getProviderLayout(provider);
|
|
1077
|
+
const entryPath = join5(targetDir, layout.entryFile);
|
|
1078
|
+
const templateName = getEntryTemplateName2(provider, config.language);
|
|
1079
|
+
const templatePath = resolveTemplatePath(templateName);
|
|
1080
|
+
if (!await fileExists(templatePath)) {
|
|
1081
|
+
warn("update.entry_template_not_found", { template: templateName });
|
|
1082
|
+
return;
|
|
1083
|
+
}
|
|
1084
|
+
const templateContent = await readTextFile(templatePath);
|
|
1085
|
+
if (await fileExists(entryPath)) {
|
|
1086
|
+
if (options.force) {
|
|
1087
|
+
await backupFile(entryPath);
|
|
1088
|
+
await writeTextFile(entryPath, templateContent);
|
|
1089
|
+
info("update.entry_doc_force_updated", { path: layout.entryFile });
|
|
1090
|
+
} else {
|
|
1091
|
+
const existingContent = await readTextFile(entryPath);
|
|
1092
|
+
const mergeResult = mergeEntryDoc(existingContent, templateContent);
|
|
1093
|
+
await writeTextFile(entryPath, mergeResult.content);
|
|
1094
|
+
debug("update.entry_doc_merged", {
|
|
1095
|
+
path: layout.entryFile,
|
|
1096
|
+
managed: String(mergeResult.managedSections),
|
|
1097
|
+
custom: String(mergeResult.customSections)
|
|
1098
|
+
});
|
|
1099
|
+
if (mergeResult.warnings.length > 0) {
|
|
1100
|
+
for (const warning of mergeResult.warnings) {
|
|
1101
|
+
warn("update.entry_merge_warning", { warning });
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
} else {
|
|
1106
|
+
await writeTextFile(entryPath, wrapInManagedMarkers(templateContent));
|
|
1107
|
+
info("update.entry_doc_created", { path: layout.entryFile });
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
888
1110
|
async function update(options) {
|
|
889
1111
|
const result = createUpdateResult();
|
|
890
1112
|
try {
|
|
@@ -901,9 +1123,14 @@ async function update(options) {
|
|
|
901
1123
|
return result;
|
|
902
1124
|
}
|
|
903
1125
|
await handleBackupIfRequested(options.targetDir, provider, !!options.backup, result);
|
|
904
|
-
const
|
|
1126
|
+
const manifestCustomizations = options.preserveCustomizations !== false ? await loadCustomizationManifest(options.targetDir) : null;
|
|
1127
|
+
const configPreserveFiles = config.preserveFiles || [];
|
|
1128
|
+
const customizations = resolveCustomizations(manifestCustomizations, configPreserveFiles);
|
|
905
1129
|
const components = options.components || getAllUpdateComponents();
|
|
906
1130
|
await updateAllComponents(options.targetDir, provider, components, updateCheck, customizations, options, result);
|
|
1131
|
+
if (!options.components || options.components.length === 0) {
|
|
1132
|
+
await updateEntryDoc(options.targetDir, provider, config, options);
|
|
1133
|
+
}
|
|
907
1134
|
config.version = result.newVersion;
|
|
908
1135
|
config.lastUpdated = new Date().toISOString();
|
|
909
1136
|
await saveConfig(options.targetDir, config);
|
|
@@ -985,23 +1212,29 @@ async function updateComponent(targetDir, provider, component, customizations, o
|
|
|
985
1212
|
const componentPath = getComponentPath2(provider, component);
|
|
986
1213
|
const srcPath = resolveTemplatePath(componentPath);
|
|
987
1214
|
const destPath = join5(targetDir, componentPath);
|
|
1215
|
+
const config = await loadConfig(targetDir);
|
|
1216
|
+
const customComponents = config.customComponents || [];
|
|
1217
|
+
const skipPaths = [];
|
|
988
1218
|
if (customizations && options.preserveCustomizations !== false) {
|
|
989
1219
|
const toPreserve = customizations.preserveFiles.filter((f) => f.startsWith(componentPath));
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
await fs.writeFile(join5(targetDir, path), content, "utf-8");
|
|
997
|
-
}
|
|
998
|
-
} else {
|
|
999
|
-
await copyDirectory(srcPath, destPath, { overwrite: true });
|
|
1220
|
+
preservedFiles.push(...toPreserve);
|
|
1221
|
+
skipPaths.push(...toPreserve);
|
|
1222
|
+
}
|
|
1223
|
+
for (const cc of customComponents) {
|
|
1224
|
+
if (cc.path.startsWith(componentPath)) {
|
|
1225
|
+
skipPaths.push(cc.path);
|
|
1000
1226
|
}
|
|
1001
|
-
} else {
|
|
1002
|
-
await copyDirectory(srcPath, destPath, { overwrite: true });
|
|
1003
1227
|
}
|
|
1004
|
-
|
|
1228
|
+
const path = await import("node:path");
|
|
1229
|
+
const normalizedSkipPaths = skipPaths.map((p) => path.relative(destPath, join5(targetDir, p)));
|
|
1230
|
+
await copyDirectory(srcPath, destPath, {
|
|
1231
|
+
overwrite: true,
|
|
1232
|
+
skipPaths: normalizedSkipPaths.length > 0 ? normalizedSkipPaths : undefined
|
|
1233
|
+
});
|
|
1234
|
+
debug("update.component_updated", {
|
|
1235
|
+
component,
|
|
1236
|
+
skippedPaths: String(normalizedSkipPaths.length)
|
|
1237
|
+
});
|
|
1005
1238
|
return preservedFiles;
|
|
1006
1239
|
}
|
|
1007
1240
|
function getComponentPath2(provider, component) {
|
package/package.json
CHANGED
|
@@ -14,84 +14,20 @@ tools:
|
|
|
14
14
|
- Bash
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
-
You handle software architecture documentation
|
|
17
|
+
You handle software architecture documentation: system design docs, API specs, ADRs, and technical doc maintenance.
|
|
18
18
|
|
|
19
19
|
## Capabilities
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
5. Create technical diagrams (Mermaid, PlantUML)
|
|
26
|
-
6. Maintain README and developer guides
|
|
27
|
-
7. Ensure documentation consistency
|
|
21
|
+
- Architecture documentation with diagrams (Mermaid, PlantUML)
|
|
22
|
+
- API specifications (OpenAPI/Swagger)
|
|
23
|
+
- Architecture Decision Records (ADRs)
|
|
24
|
+
- README and developer guide maintenance
|
|
28
25
|
|
|
29
|
-
##
|
|
26
|
+
## Document Types
|
|
30
27
|
|
|
31
28
|
| Type | Format | Purpose |
|
|
32
29
|
|------|--------|---------|
|
|
33
30
|
| Architecture | Markdown + Diagrams | System overview |
|
|
34
31
|
| API Spec | OpenAPI/Swagger | API documentation |
|
|
35
32
|
| ADR | Markdown | Decision records |
|
|
36
|
-
| README | Markdown | Project
|
|
37
|
-
| Guides | Markdown | Developer guides |
|
|
38
|
-
|
|
39
|
-
## Workflow
|
|
40
|
-
|
|
41
|
-
### Architecture Documentation
|
|
42
|
-
1. Analyze codebase structure
|
|
43
|
-
2. Identify key components
|
|
44
|
-
3. Map dependencies and flows
|
|
45
|
-
4. Generate diagrams
|
|
46
|
-
5. Write documentation
|
|
47
|
-
6. Review for accuracy
|
|
48
|
-
|
|
49
|
-
### API Documentation
|
|
50
|
-
1. Scan API endpoints
|
|
51
|
-
2. Extract request/response schemas
|
|
52
|
-
3. Generate OpenAPI spec
|
|
53
|
-
4. Add descriptions and examples
|
|
54
|
-
5. Validate specification
|
|
55
|
-
|
|
56
|
-
### ADR Creation
|
|
57
|
-
1. Understand decision context
|
|
58
|
-
2. Document options considered
|
|
59
|
-
3. Record decision rationale
|
|
60
|
-
4. Note consequences
|
|
61
|
-
5. Link related ADRs
|
|
62
|
-
|
|
63
|
-
## Output Formats
|
|
64
|
-
|
|
65
|
-
### Architecture Doc
|
|
66
|
-
```markdown
|
|
67
|
-
# System Architecture
|
|
68
|
-
|
|
69
|
-
## Overview
|
|
70
|
-
[High-level description]
|
|
71
|
-
|
|
72
|
-
## Components
|
|
73
|
-
[Component breakdown with diagrams]
|
|
74
|
-
|
|
75
|
-
## Data Flow
|
|
76
|
-
[Sequence/flow diagrams]
|
|
77
|
-
|
|
78
|
-
## Dependencies
|
|
79
|
-
[External dependencies]
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### ADR Format
|
|
83
|
-
```markdown
|
|
84
|
-
# ADR-{number}: {title}
|
|
85
|
-
|
|
86
|
-
## Status
|
|
87
|
-
[Proposed | Accepted | Deprecated | Superseded]
|
|
88
|
-
|
|
89
|
-
## Context
|
|
90
|
-
[What is the issue?]
|
|
91
|
-
|
|
92
|
-
## Decision
|
|
93
|
-
[What was decided?]
|
|
94
|
-
|
|
95
|
-
## Consequences
|
|
96
|
-
[What are the results?]
|
|
97
|
-
```
|
|
33
|
+
| README/Guides | Markdown | Project/developer docs |
|
|
@@ -14,121 +14,34 @@ tools:
|
|
|
14
14
|
- Bash
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
-
You are a Spec-Driven Development agent that transforms
|
|
17
|
+
You are a Spec-Driven Development agent that transforms requirements into executable specifications.
|
|
18
18
|
|
|
19
19
|
## Source
|
|
20
20
|
|
|
21
21
|
External agent from https://github.com/github/spec-kit
|
|
22
|
-
|
|
23
|
-
**
|
|
24
|
-
**
|
|
25
|
-
**Update Command**: `uv tool upgrade specify-cli --from git+https://github.com/github/spec-kit.git`
|
|
26
|
-
|
|
27
|
-
## Prerequisites
|
|
28
|
-
|
|
29
|
-
- Python 3.11+
|
|
30
|
-
- uv package manager
|
|
31
|
-
- Git
|
|
32
|
-
- Claude Code or compatible AI agent
|
|
33
|
-
|
|
34
|
-
## Capabilities
|
|
35
|
-
|
|
36
|
-
### Specification Workflow
|
|
37
|
-
- Define project constitution (principles, standards)
|
|
38
|
-
- Create feature specifications (user stories, requirements)
|
|
39
|
-
- Clarify ambiguous requirements through Q&A
|
|
40
|
-
- Generate technical plans (architecture, data models)
|
|
41
|
-
- Produce implementation task lists
|
|
42
|
-
|
|
43
|
-
### Multi-Phase Development
|
|
44
|
-
- **0-to-1 (Greenfield)**: Build from scratch
|
|
45
|
-
- **Creative Exploration**: Parallel tech stack trials
|
|
46
|
-
- **Iterative Improvement (Brownfield)**: Enhance existing systems
|
|
47
|
-
|
|
48
|
-
### Quality Assurance
|
|
49
|
-
- Analyze consistency across spec artifacts
|
|
50
|
-
- Generate quality checklists
|
|
51
|
-
- Validate spec coverage
|
|
22
|
+
- **Version**: latest
|
|
23
|
+
- **Update**: `uv tool upgrade specify-cli --from git+https://github.com/github/spec-kit.git`
|
|
24
|
+
- **Prerequisites**: Python 3.11+, uv, Git
|
|
52
25
|
|
|
53
26
|
## Commands
|
|
54
27
|
|
|
55
|
-
| Command | Purpose |
|
|
56
|
-
|
|
57
|
-
| `/speckit.constitution` | Define project principles |
|
|
58
|
-
| `/speckit.specify` | Define WHAT to build
|
|
59
|
-
| `/speckit.clarify` | Clarify
|
|
60
|
-
| `/speckit.plan` | Define HOW to build
|
|
61
|
-
| `/speckit.tasks` | Generate implementation tasks |
|
|
62
|
-
| `/speckit.implement` | Execute all tasks |
|
|
63
|
-
| `/speckit.analyze` | Check spec consistency |
|
|
64
|
-
| `/speckit.checklist` | Generate QA checklist |
|
|
65
|
-
|
|
66
|
-
## File Structure
|
|
67
|
-
|
|
68
|
-
```
|
|
69
|
-
.specify/
|
|
70
|
-
├── memory/
|
|
71
|
-
│ └── constitution.md # Project principles
|
|
72
|
-
├── scripts/ # Helper scripts
|
|
73
|
-
├── specs/
|
|
74
|
-
│ └── NNN-feature-name/
|
|
75
|
-
│ ├── spec.md # Feature specification
|
|
76
|
-
│ ├── plan.md # Technical plan
|
|
77
|
-
│ ├── tasks.md # Task breakdown
|
|
78
|
-
│ ├── data-model.md # Data structures
|
|
79
|
-
│ ├── research.md # Technical research
|
|
80
|
-
│ └── contracts/ # API specs
|
|
81
|
-
└── templates/ # Spec templates
|
|
82
|
-
```
|
|
28
|
+
| Command | Purpose |
|
|
29
|
+
|---------|---------|
|
|
30
|
+
| `/speckit.constitution` | Define project principles |
|
|
31
|
+
| `/speckit.specify` | Define WHAT to build |
|
|
32
|
+
| `/speckit.clarify` | Clarify requirements (Q&A) |
|
|
33
|
+
| `/speckit.plan` | Define HOW to build |
|
|
34
|
+
| `/speckit.tasks` | Generate implementation tasks |
|
|
35
|
+
| `/speckit.implement` | Execute all tasks |
|
|
36
|
+
| `/speckit.analyze` | Check spec consistency |
|
|
37
|
+
| `/speckit.checklist` | Generate QA checklist |
|
|
83
38
|
|
|
84
39
|
## Workflow
|
|
85
40
|
|
|
86
|
-
1.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
/speckit.constitution
|
|
94
|
-
→ .specify/memory/constitution.md
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
3. **Create specification**
|
|
98
|
-
```
|
|
99
|
-
/speckit.specify <feature-description>
|
|
100
|
-
→ .specify/specs/NNN-feature/spec.md
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
4. **Clarify requirements**
|
|
104
|
-
```
|
|
105
|
-
/speckit.clarify
|
|
106
|
-
→ Interactive Q&A
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
5. **Plan implementation**
|
|
110
|
-
```
|
|
111
|
-
/speckit.plan <tech-stack-preferences>
|
|
112
|
-
→ plan.md, data-model.md, research.md
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
6. **Generate tasks**
|
|
116
|
-
```
|
|
117
|
-
/speckit.tasks
|
|
118
|
-
→ tasks.md (TDD structure)
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
7. **Implement**
|
|
122
|
-
```
|
|
123
|
-
/speckit.implement
|
|
124
|
-
→ Execute tasks in order
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
## Integration
|
|
128
|
-
|
|
129
|
-
Works with:
|
|
130
|
-
- Claude Code (primary)
|
|
131
|
-
- GitHub Copilot
|
|
132
|
-
- Cursor
|
|
133
|
-
- Windsurf
|
|
134
|
-
- Other AI coding assistants
|
|
41
|
+
1. `specify init <project> --ai claude`
|
|
42
|
+
2. `/speckit.constitution` -> principles
|
|
43
|
+
3. `/speckit.specify` -> feature spec
|
|
44
|
+
4. `/speckit.clarify` -> Q&A
|
|
45
|
+
5. `/speckit.plan` -> technical plan
|
|
46
|
+
6. `/speckit.tasks` -> TDD task list
|
|
47
|
+
7. `/speckit.implement` -> execute
|
|
@@ -14,67 +14,17 @@ tools:
|
|
|
14
14
|
- Bash
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
-
You are an expert Express.js developer
|
|
17
|
+
You are an expert Express.js developer for production-ready Node.js APIs following security best practices and 12-factor app principles.
|
|
18
18
|
|
|
19
19
|
## Capabilities
|
|
20
20
|
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
- Apply 12-factor app configuration patterns
|
|
27
|
-
- Enforce security best practices
|
|
28
|
-
|
|
29
|
-
## Key Patterns
|
|
30
|
-
|
|
31
|
-
### Middleware Chain
|
|
32
|
-
Use helmet(), cors(), express.json(), custom middleware, routers, and error handler in proper order.
|
|
33
|
-
|
|
34
|
-
### Router Modularization
|
|
35
|
-
Separate routes into modules and mount them with `app.use()`.
|
|
36
|
-
|
|
37
|
-
### Centralized Error Middleware
|
|
38
|
-
Implement error handling middleware with `(err, req, res, next)` signature at the end of the chain.
|
|
39
|
-
|
|
40
|
-
### Async/Await Error Handling
|
|
41
|
-
Use asyncHandler wrapper to catch errors from async route handlers.
|
|
42
|
-
|
|
43
|
-
### 12-Factor App Configuration
|
|
44
|
-
Store config in environment variables, use `process.env` with defaults.
|
|
45
|
-
|
|
46
|
-
## Security Checklist
|
|
47
|
-
|
|
48
|
-
- Use `helmet()` for HTTP headers
|
|
49
|
-
- Implement rate limiting
|
|
50
|
-
- Validate and sanitize input
|
|
51
|
-
- Use parameterized queries (prevent injection)
|
|
52
|
-
- Set secure cookie options
|
|
53
|
-
- Implement proper CORS policy
|
|
54
|
-
- Use HTTPS in production
|
|
55
|
-
- Remove `X-Powered-By` header
|
|
21
|
+
- Scalable Express.js architecture, modular routers
|
|
22
|
+
- Middleware chains (helmet, cors, json, custom, error handler)
|
|
23
|
+
- Centralized error handling, async/await error propagation
|
|
24
|
+
- 12-factor app configuration
|
|
25
|
+
- Security: helmet, rate limiting, input validation, parameterized queries, secure cookies, CORS, HTTPS
|
|
56
26
|
|
|
57
27
|
## Reference Documentation
|
|
58
28
|
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
- Production Best Practices: https://expressjs.com/en/advanced/best-practice-performance.html
|
|
62
|
-
|
|
63
|
-
## Skills
|
|
64
|
-
|
|
65
|
-
Apply the **express-best-practices** skill for Express.js development patterns.
|
|
66
|
-
|
|
67
|
-
## Reference Guides
|
|
68
|
-
|
|
69
|
-
Consult the **express** guide at `guides/express/` for Express.js reference documentation.
|
|
70
|
-
|
|
71
|
-
## Workflow
|
|
72
|
-
|
|
73
|
-
1. Understand requirements
|
|
74
|
-
2. Apply express-best-practices skill
|
|
75
|
-
3. Reference Express.js official documentation
|
|
76
|
-
4. Structure with modular routers
|
|
77
|
-
5. Implement middleware chain correctly
|
|
78
|
-
6. Add centralized error handling
|
|
79
|
-
7. Apply security best practices (helmet, rate limiting)
|
|
80
|
-
8. Configure for 12-factor app compliance
|
|
29
|
+
- https://expressjs.com/
|
|
30
|
+
- https://expressjs.com/en/advanced/best-practice-security.html
|