universal-dev-standards 6.8.0 → 6.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/uds.js +12 -2
- package/bundled/ai/standards/acceptance-criteria-traceability.ai.yaml +14 -2
- package/bundled/ai/standards/adr-standards.ai.yaml +14 -2
- package/bundled/ai/standards/code-review.ai.yaml +13 -3
- package/bundled/ai/standards/commit-message.ai.yaml +8 -4
- package/bundled/ai/standards/deferred-item-exit.ai.yaml +225 -0
- package/bundled/ai/standards/feature-discovery-standards.ai.yaml +14 -2
- package/bundled/ai/standards/governance-layer.ai.yaml +128 -2
- package/bundled/ai/standards/logging.ai.yaml +2 -2
- package/bundled/ai/standards/retrospective-standards.ai.yaml +14 -2
- package/bundled/ai/standards/reverse-engineering-standards.ai.yaml +73 -2
- package/bundled/ai/standards/security-standards.ai.yaml +2 -2
- package/bundled/ai/standards/spec-driven-development.ai.yaml +14 -2
- package/bundled/ai/standards/tech-debt-standards.ai.yaml +87 -3
- package/bundled/ai/standards/turn-completion-integrity.ai.yaml +131 -0
- package/bundled/core/acceptance-criteria-traceability.md +5 -2
- package/bundled/core/adr-standards.md +26 -2
- package/bundled/core/agent-communication-protocol.md +8 -0
- package/bundled/core/branch-completion.md +8 -0
- package/bundled/core/change-batching-standards.md +8 -0
- package/bundled/core/code-review-checklist.md +5 -2
- package/bundled/core/context-aware-loading.md +1 -1
- package/bundled/core/deferred-item-exit.md +254 -0
- package/bundled/core/execution-history.md +8 -0
- package/bundled/core/feature-discovery-standards.md +5 -1
- package/bundled/core/governance-layer.md +114 -2
- package/bundled/core/pipeline-integration-standards.md +8 -0
- package/bundled/core/retrospective-standards.md +4 -2
- package/bundled/core/reverse-engineering-standards.md +81 -2
- package/bundled/core/spec-driven-development.md +8 -2
- package/bundled/core/tech-debt-standards.md +67 -8
- package/bundled/core/turn-completion-integrity.md +196 -0
- package/bundled/core/workflow-enforcement.md +8 -0
- package/bundled/core/workflow-state-protocol.md +8 -0
- package/bundled/hooks/check-dangerous-cmd.mjs +60 -0
- package/bundled/hooks/check-logging-standard.mjs +59 -0
- package/bundled/hooks/check-turn-completion.mjs +233 -0
- package/bundled/hooks/inject-standards.mjs +183 -0
- package/bundled/hooks/telemetry-wrapper.mjs +77 -0
- package/bundled/hooks/turn-completion/detect.mjs +99 -0
- package/bundled/hooks/turn-completion/locales/en.mjs +159 -0
- package/bundled/hooks/turn-completion/locales/zh-TW.mjs +166 -0
- package/bundled/hooks/validate-commit-msg.mjs +104 -0
- package/bundled/locales/zh-CN/CHANGELOG.md +73 -3
- package/bundled/locales/zh-CN/CLAUDE.md +1 -1
- package/bundled/locales/zh-CN/README.md +2 -2
- package/bundled/locales/zh-CN/SECURITY.md +1 -1
- package/bundled/locales/zh-CN/core/adr-standards.md +1 -1
- package/bundled/locales/zh-CN/core/agent-communication-protocol.md +7 -0
- package/bundled/locales/zh-CN/core/branch-completion.md +7 -0
- package/bundled/locales/zh-CN/core/change-batching-standards.md +7 -0
- package/bundled/locales/zh-CN/core/execution-history.md +7 -0
- package/bundled/locales/zh-CN/core/governance-layer.md +118 -6
- package/bundled/locales/zh-CN/core/pipeline-integration-standards.md +7 -0
- package/bundled/locales/zh-CN/core/retrospective-standards.md +1 -1
- package/bundled/locales/zh-CN/core/tech-debt-standards.md +71 -4
- package/bundled/locales/zh-CN/core/turn-completion-integrity.md +190 -0
- package/bundled/locales/zh-CN/core/workflow-enforcement.md +7 -0
- package/bundled/locales/zh-CN/core/workflow-state-protocol.md +7 -0
- package/bundled/locales/zh-CN/docs/CHEATSHEET.md +8 -1
- package/bundled/locales/zh-CN/docs/CLI-INIT-OPTIONS.md +29 -68
- package/bundled/locales/zh-CN/docs/FEATURE-REFERENCE.md +25 -15
- package/bundled/locales/zh-CN/docs/MIGRATION-v6.md +8 -4
- package/bundled/locales/zh-CN/docs/USAGE-MODES-COMPARISON.md +1 -2
- package/bundled/locales/zh-CN/integrations/google-antigravity/{INSTRUCTIONS.md → AGENTS.md} +1 -1
- package/bundled/locales/zh-CN/integrations/google-antigravity/README.md +3 -3
- package/bundled/locales/zh-CN/skills/atdd-assistant/SKILL.md +2 -0
- package/bundled/locales/zh-CN/skills/bdd-assistant/SKILL.md +2 -0
- package/bundled/locales/zh-CN/skills/brainstorm-assistant/SKILL.md +22 -12
- package/bundled/locales/zh-CN/skills/brainstorm-assistant/guide.md +12 -9
- package/bundled/locales/zh-CN/skills/code-review-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-CN/skills/commands/brainstorm.md +17 -13
- package/bundled/locales/zh-CN/skills/commands/config.md +0 -1
- package/bundled/locales/zh-CN/skills/commands/init.md +1 -2
- package/bundled/locales/zh-CN/skills/commit-standards/SKILL.md +2 -0
- package/bundled/locales/zh-CN/skills/contract-test-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-CN/skills/dev-methodology/SKILL.md +2 -0
- package/bundled/locales/zh-CN/skills/observability-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-CN/skills/project-structure-guide/SKILL.md +1 -0
- package/bundled/locales/zh-CN/skills/release-standards/SKILL.md +3 -0
- package/bundled/locales/zh-CN/skills/requirement-assistant/SKILL.md +2 -0
- package/bundled/locales/zh-CN/skills/reverse-engineer/SKILL.md +3 -0
- package/bundled/locales/zh-CN/skills/runbook-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-CN/skills/slo-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-CN/skills/tdd-assistant/SKILL.md +2 -0
- package/bundled/locales/zh-TW/CHANGELOG.md +74 -3
- package/bundled/locales/zh-TW/CLAUDE.md +1 -1
- package/bundled/locales/zh-TW/README.md +2 -2
- package/bundled/locales/zh-TW/SECURITY.md +1 -1
- package/bundled/locales/zh-TW/core/acceptance-criteria-traceability.md +2 -0
- package/bundled/locales/zh-TW/core/adr-standards.md +26 -5
- package/bundled/locales/zh-TW/core/agent-communication-protocol.md +7 -0
- package/bundled/locales/zh-TW/core/branch-completion.md +7 -0
- package/bundled/locales/zh-TW/core/change-batching-standards.md +7 -0
- package/bundled/locales/zh-TW/core/code-review-checklist.md +2 -0
- package/bundled/locales/zh-TW/core/container-image-standards.md +2 -2
- package/bundled/locales/zh-TW/core/contract-testing-standards.md +2 -2
- package/bundled/locales/zh-TW/core/cross-flow-regression.md +8 -7
- package/bundled/locales/zh-TW/core/data-contract.md +2 -2
- package/bundled/locales/zh-TW/core/data-migration-testing.md +2 -2
- package/bundled/locales/zh-TW/core/data-pipeline.md +2 -2
- package/bundled/locales/zh-TW/core/deferred-item-exit.md +251 -0
- package/bundled/locales/zh-TW/core/documentation-writing-standards.md +228 -3
- package/bundled/locales/zh-TW/core/execution-history.md +7 -0
- package/bundled/locales/zh-TW/core/full-coverage-testing.md +15 -2
- package/bundled/locales/zh-TW/core/governance-layer.md +118 -5
- package/bundled/locales/zh-TW/core/iac-design-principles.md +2 -2
- package/bundled/locales/zh-TW/core/incident-response.md +2 -2
- package/bundled/locales/zh-TW/core/model-provenance.md +4 -2
- package/bundled/locales/zh-TW/core/pii-classification.md +42 -6
- package/bundled/locales/zh-TW/core/pipeline-integration-standards.md +7 -0
- package/bundled/locales/zh-TW/core/prd-standards.md +4 -2
- package/bundled/locales/zh-TW/core/product-metrics-standards.md +4 -2
- package/bundled/locales/zh-TW/core/release-readiness-gate.md +2 -2
- package/bundled/locales/zh-TW/core/resource-cost-boundary.md +2 -2
- package/bundled/locales/zh-TW/core/retrospective-standards.md +5 -3
- package/bundled/locales/zh-TW/core/reverse-engineering-standards.md +83 -5
- package/bundled/locales/zh-TW/core/runbook.md +2 -2
- package/bundled/locales/zh-TW/core/schema-evolution.md +2 -2
- package/bundled/locales/zh-TW/core/secret-management-standards.md +2 -2
- package/bundled/locales/zh-TW/core/slo-sli.md +2 -2
- package/bundled/locales/zh-TW/core/spec-driven-development.md +2 -0
- package/bundled/locales/zh-TW/core/tech-debt-standards.md +71 -4
- package/bundled/locales/zh-TW/core/turn-completion-integrity.md +190 -0
- package/bundled/locales/zh-TW/core/user-journey-testing.md +2 -2
- package/bundled/locales/zh-TW/core/user-story-mapping.md +2 -2
- package/bundled/locales/zh-TW/core/verification-oracle.md +2 -2
- package/bundled/locales/zh-TW/core/workflow-enforcement.md +7 -0
- package/bundled/locales/zh-TW/core/workflow-state-protocol.md +7 -0
- package/bundled/locales/zh-TW/docs/CHEATSHEET.md +8 -1
- package/bundled/locales/zh-TW/docs/CLI-INIT-OPTIONS.md +29 -68
- package/bundled/locales/zh-TW/docs/FEATURE-REFERENCE.md +25 -15
- package/bundled/locales/zh-TW/docs/MIGRATION-v6.md +8 -4
- package/bundled/locales/zh-TW/docs/USAGE-MODES-COMPARISON.md +1 -2
- package/bundled/locales/zh-TW/integrations/google-antigravity/{INSTRUCTIONS.md → AGENTS.md} +1 -1
- package/bundled/locales/zh-TW/integrations/google-antigravity/README.md +3 -3
- package/bundled/locales/zh-TW/skills/adr-assistant/SKILL.md +1 -1
- package/bundled/locales/zh-TW/skills/atdd-assistant/SKILL.md +2 -0
- package/bundled/locales/zh-TW/skills/bdd-assistant/SKILL.md +2 -0
- package/bundled/locales/zh-TW/skills/brainstorm-assistant/SKILL.md +22 -12
- package/bundled/locales/zh-TW/skills/brainstorm-assistant/guide.md +12 -9
- package/bundled/locales/zh-TW/skills/code-review-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-TW/skills/commands/brainstorm.md +17 -13
- package/bundled/locales/zh-TW/skills/commands/config.md +0 -1
- package/bundled/locales/zh-TW/skills/commands/init.md +1 -2
- package/bundled/locales/zh-TW/skills/commit-standards/SKILL.md +2 -0
- package/bundled/locales/zh-TW/skills/contract-test-assistant/SKILL.md +2 -1
- package/bundled/locales/zh-TW/skills/dev-methodology/SKILL.md +2 -0
- package/bundled/locales/zh-TW/skills/dev-workflow-guide/SKILL.md +1 -1
- package/bundled/locales/zh-TW/skills/knowledge-graph/guide.md +2 -2
- package/bundled/locales/zh-TW/skills/migration-assistant/SKILL.md +1 -1
- package/bundled/locales/zh-TW/skills/observability-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-TW/skills/project-discovery/SKILL.md +1 -0
- package/bundled/locales/zh-TW/skills/project-structure-guide/SKILL.md +1 -0
- package/bundled/locales/zh-TW/skills/release-standards/SKILL.md +3 -0
- package/bundled/locales/zh-TW/skills/requirement-assistant/SKILL.md +2 -0
- package/bundled/locales/zh-TW/skills/reverse-engineer/SKILL.md +3 -0
- package/bundled/locales/zh-TW/skills/runbook-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-TW/skills/slo-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-TW/skills/tdd-assistant/SKILL.md +2 -0
- package/bundled/skills/atdd-assistant/SKILL.md +2 -0
- package/bundled/skills/bdd-assistant/SKILL.md +2 -0
- package/bundled/skills/brainstorm-assistant/SKILL.md +31 -13
- package/bundled/skills/brainstorm-assistant/guide.md +9 -6
- package/bundled/skills/code-review-assistant/SKILL.md +1 -0
- package/bundled/skills/commands/brainstorm.md +12 -9
- package/bundled/skills/commands/config.md +0 -1
- package/bundled/skills/commands/init.md +2 -3
- package/bundled/skills/commit-standards/SKILL.md +2 -0
- package/bundled/skills/contract-test-assistant/SKILL.md +1 -0
- package/bundled/skills/dev-methodology/SKILL.md +4 -0
- package/bundled/skills/observability-assistant/SKILL.md +1 -0
- package/bundled/skills/project-discovery/SKILL.md +1 -0
- package/bundled/skills/project-structure-guide/SKILL.md +1 -0
- package/bundled/skills/release-standards/SKILL.md +3 -0
- package/bundled/skills/requirement-assistant/SKILL.md +2 -0
- package/bundled/skills/reverse-engineer/SKILL.md +3 -0
- package/bundled/skills/runbook-assistant/SKILL.md +1 -0
- package/bundled/skills/slo-assistant/SKILL.md +1 -0
- package/bundled/skills/tdd-assistant/SKILL.md +2 -0
- package/bundled/templates/.ai-context.yaml.template +194 -0
- package/bundled/templates/CLAUDE.md.template +145 -0
- package/bundled/templates/DESIGN.md +237 -0
- package/bundled/templates/SKILL-BRIEF-TEMPLATE.md +57 -0
- package/bundled/templates/SKILL-CANDIDATES.md +39 -0
- package/bundled/templates/gates/check-error-exit.mjs +309 -0
- package/bundled/templates/mcp-config.json +10 -0
- package/bundled/templates/methodology-template.yaml +209 -0
- package/bundled/templates/migration-template.md +408 -0
- package/bundled/templates/requirement-checklist.md +410 -0
- package/bundled/templates/requirement-document-template.md +591 -0
- package/bundled/templates/requirement-template.md +881 -0
- package/bundled/templates/reverse-spec-template.md +409 -0
- package/bundled/templates/test-case-template.md +74 -0
- package/bundled/templates/test-plan-template.md +74 -0
- package/package.json +12 -9
- package/src/commands/audit.js +82 -0
- package/src/commands/check.js +227 -34
- package/src/commands/config.js +19 -19
- package/src/commands/init.js +174 -20
- package/src/commands/spec.js +2 -2
- package/src/commands/update.js +537 -43
- package/src/compilers/claude-code-compiler.js +4 -1
- package/src/config/ai-agent-paths.js +62 -17
- package/src/core/constants.js +42 -11
- package/src/core/manifest.js +201 -3
- package/src/core/paths.js +2 -2
- package/src/i18n/messages.js +42 -29
- package/src/installers/hooks-installer.js +167 -75
- package/src/installers/integration-installer.js +13 -9
- package/src/installers/skills-installer.js +4 -4
- package/src/installers/standards-installer.js +3 -3
- package/src/prompts/init.js +47 -18
- package/src/reconciler/diff-engine.js +57 -2
- package/src/reconciler/plan-executor.js +31 -11
- package/src/utils/detector.js +21 -1
- package/src/utils/effect-boundary.js +1093 -0
- package/src/utils/hasher.js +166 -1
- package/src/utils/hook-stats.js +1 -1
- package/src/utils/integration-generator.js +288 -82
- package/src/utils/reference-sync.js +107 -8
- package/src/utils/registry.js +57 -0
- package/src/utils/spinner.js +31 -0
- package/src/utils/yaml-generator.js +51 -9
- package/standards-registry.json +32 -9
package/src/i18n/messages.js
CHANGED
|
@@ -100,12 +100,10 @@ export const messages = {
|
|
|
100
100
|
question: 'Select content mode:',
|
|
101
101
|
labels: {
|
|
102
102
|
index: 'Standard',
|
|
103
|
-
full: 'Full Embed',
|
|
104
103
|
minimal: 'Minimal'
|
|
105
104
|
},
|
|
106
105
|
choices: {
|
|
107
106
|
index: 'Summary + task mapping, AI knows when to read which standard',
|
|
108
|
-
full: 'Embed all rules, AI can use immediately but larger file',
|
|
109
107
|
minimal: 'File references only, best with Skills'
|
|
110
108
|
},
|
|
111
109
|
explanations: {
|
|
@@ -114,11 +112,6 @@ export const messages = {
|
|
|
114
112
|
' → AI can determine "which standard to read for which task"',
|
|
115
113
|
' → Balance between context usage and compliance'
|
|
116
114
|
],
|
|
117
|
-
full: [
|
|
118
|
-
' → All rules embedded in config file (~10-15 KB)',
|
|
119
|
-
' → AI needs no extra file reads, highest compliance',
|
|
120
|
-
' → Best for short tasks or strict compliance projects'
|
|
121
|
-
],
|
|
122
115
|
minimal: [
|
|
123
116
|
' → Only contains .standards/ file list',
|
|
124
117
|
' → AI needs to actively read standard files',
|
|
@@ -328,7 +321,6 @@ export const messages = {
|
|
|
328
321
|
warning: 'Changing Content Mode will regenerate all AI tool config files',
|
|
329
322
|
explanations: {
|
|
330
323
|
index: ' → AI will determine when to read standards based on task mapping',
|
|
331
|
-
full: ' → All rules embedded directly, highest AI compliance',
|
|
332
324
|
minimal: ' → AI must actively read standards, recommend using with Skills'
|
|
333
325
|
}
|
|
334
326
|
},
|
|
@@ -751,6 +743,9 @@ export const messages = {
|
|
|
751
743
|
unchanged: 'unchanged',
|
|
752
744
|
modified: 'modified',
|
|
753
745
|
missing: 'missing',
|
|
746
|
+
retired: 'no longer shipped by UDS',
|
|
747
|
+
retiredHeader: '{count} tracked file(s) are gone because UDS stopped shipping them. That is the migration completed, not a fault:',
|
|
748
|
+
retiredHint: 'Run `uds update` to drop their manifest records. `--restore` cannot bring them back — there is no source upstream.',
|
|
754
749
|
existsNoHash: 'exists, no hash',
|
|
755
750
|
summary: 'Summary: {unchanged} unchanged, {modified} modified, {missing} missing',
|
|
756
751
|
// Actions available
|
|
@@ -849,6 +844,13 @@ export const messages = {
|
|
|
849
844
|
refsInSync: '{path}: references in sync ({count} refs)',
|
|
850
845
|
noIntegrationRefs: 'No integration files with standard references found.',
|
|
851
846
|
runSyncRefs: 'Run `uds update --sync-refs` to fix reference issues.',
|
|
847
|
+
runIntegrationsOnly: 'Run `uds update --integrations-only` to regenerate integration files.',
|
|
848
|
+
danglingRefs: 'references files that are not on disk:',
|
|
849
|
+
brokenMentions: 'mentions paths that do not exist in this project:',
|
|
850
|
+
brokenMentionsFix: 'These are usually outside the UDS block, left by an older install. UDS does not rewrite text it did not write — correct them by hand or delete the line.',
|
|
851
|
+
danglingRefsFix: 'Run `uds update --integrations-only` to regenerate them.',
|
|
852
|
+
commandsUntracked: '{count} installed command file(s) are covered by no hash — integrity is not checked for them',
|
|
853
|
+
commandsUntrackedFix: 'Run `uds update --commands` to record them again.',
|
|
852
854
|
// CLI update
|
|
853
855
|
checkingCliUpdates: 'Checking for CLI updates...',
|
|
854
856
|
couldNotCheckUpdates: 'ℹ Could not check for CLI updates (offline mode)',
|
|
@@ -934,7 +936,6 @@ export const messages = {
|
|
|
934
936
|
standardsScopeLean: 'Lean (Skills handle the rest)',
|
|
935
937
|
standardsScopeComplete: 'Complete',
|
|
936
938
|
contentModeLabel: 'Content Mode',
|
|
937
|
-
contentModeFull: 'Full Embed',
|
|
938
939
|
contentModeIndex: 'Standard (recommended)',
|
|
939
940
|
contentModeMinimal: 'Minimal (core only)',
|
|
940
941
|
displayLanguageLabel: 'Display Language',
|
|
@@ -969,7 +970,10 @@ export const messages = {
|
|
|
969
970
|
generatingAgentsMd: 'Generating AGENTS.md (universal summary)...',
|
|
970
971
|
generatedAgentsMd: 'Generated AGENTS.md (universal summary)',
|
|
971
972
|
couldNotGenerateAgentsMd: 'Could not generate AGENTS.md',
|
|
972
|
-
installingSkills: 'Installing
|
|
973
|
+
installingSkills: 'Installing Skills...',
|
|
974
|
+
// Named per detected tool, never per one tool: the install now goes to each
|
|
975
|
+
// tool's own path (XSPEC-408 §18.3), so a Claude-only label would be a lie.
|
|
976
|
+
skillsPathUnknown: 'no verified skills path for this tool — nothing was installed for it',
|
|
973
977
|
installedSkills: 'Installed {count} Skills to {locations}',
|
|
974
978
|
installedSkillsWithErrors: 'Installed {count} Skills with {errors} errors',
|
|
975
979
|
// P1-CLI-1: locale fallback summary (printed after install when some
|
|
@@ -1026,6 +1030,7 @@ export const messages = {
|
|
|
1026
1030
|
syncingIntegrations: 'Syncing integration files...',
|
|
1027
1031
|
syncedIntegrations: 'Synced {count} integration files',
|
|
1028
1032
|
prunedOrphanedBlockHashes: 'Pruned {count} orphaned integration hash(es): {files}',
|
|
1033
|
+
droppedRetiredHashes: 'Dropped {count} manifest record(s) for files UDS no longer ships and that are already gone:',
|
|
1029
1034
|
// Success
|
|
1030
1035
|
updateSuccess: '✓ Standards updated successfully!',
|
|
1031
1036
|
versionUpdated: 'Version: {current} → {latest}',
|
|
@@ -1053,6 +1058,7 @@ export const messages = {
|
|
|
1053
1058
|
// Sync refs
|
|
1054
1059
|
syncingRefs: 'Syncing integration references...',
|
|
1055
1060
|
noIntegrationConfigs: '⚠ No integration configurations found in manifest.',
|
|
1061
|
+
integrationConfigsBackfilled: 'Rebuilt integration config for {count} file(s) from the manifest.',
|
|
1056
1062
|
integrationConfigsRequired: 'Integration configs are required for reference sync.',
|
|
1057
1063
|
thisHappensWhen: 'This happens when:',
|
|
1058
1064
|
oldVersion: '- The project was initialized with an older version of UDS',
|
|
@@ -1334,12 +1340,10 @@ export const messages = {
|
|
|
1334
1340
|
question: '選擇內容模式:',
|
|
1335
1341
|
labels: {
|
|
1336
1342
|
index: '標準',
|
|
1337
|
-
full: '完整嵌入',
|
|
1338
1343
|
minimal: '最小化'
|
|
1339
1344
|
},
|
|
1340
1345
|
choices: {
|
|
1341
1346
|
index: '摘要 + 任務對照表,AI 知道何時讀哪個規範',
|
|
1342
|
-
full: '完整嵌入所有規則,AI 立即可用但檔案較大',
|
|
1343
1347
|
minimal: '僅檔案參考,適合搭配 Skills 使用'
|
|
1344
1348
|
},
|
|
1345
1349
|
explanations: {
|
|
@@ -1348,11 +1352,6 @@ export const messages = {
|
|
|
1348
1352
|
' → AI 能判斷「做什麼任務時要讀哪個規範」',
|
|
1349
1353
|
' → 平衡 Context 使用量和合規程度'
|
|
1350
1354
|
],
|
|
1351
|
-
full: [
|
|
1352
|
-
' → 所有規則直接嵌入設定檔(檔案約 10-15 KB)',
|
|
1353
|
-
' → AI 無需額外讀檔,合規率最高',
|
|
1354
|
-
' → 適合短期任務或需要嚴格遵循的專案'
|
|
1355
|
-
],
|
|
1356
1355
|
minimal: [
|
|
1357
1356
|
' → 僅包含 .standards/ 檔案清單',
|
|
1358
1357
|
' → AI 需要主動讀取規範檔案',
|
|
@@ -1562,7 +1561,6 @@ export const messages = {
|
|
|
1562
1561
|
warning: '變更 Content Mode 將重新生成所有 AI 工具設定檔',
|
|
1563
1562
|
explanations: {
|
|
1564
1563
|
index: ' → AI 會根據任務對照表判斷何時讀取規範',
|
|
1565
|
-
full: ' → 所有規則直接嵌入,AI 合規率最高',
|
|
1566
1564
|
minimal: ' → AI 需主動讀取規範,建議搭配 Skills'
|
|
1567
1565
|
}
|
|
1568
1566
|
},
|
|
@@ -1985,6 +1983,9 @@ export const messages = {
|
|
|
1985
1983
|
unchanged: '未變更',
|
|
1986
1984
|
modified: '已修改',
|
|
1987
1985
|
missing: '遺失',
|
|
1986
|
+
retired: 'UDS 已不再出貨',
|
|
1987
|
+
retiredHeader: '有 {count} 個被追蹤的檔案不見了,原因是 UDS 已不再出貨。那是遷移完成的樣子,不是故障:',
|
|
1988
|
+
retiredHint: '執行 `uds update` 清掉它們在 manifest 的紀錄。`--restore` 救不回來——上游已經沒有來源。',
|
|
1988
1989
|
existsNoHash: '存在,無 hash',
|
|
1989
1990
|
summary: '摘要:{unchanged} 未變更,{modified} 已修改,{missing} 遺失',
|
|
1990
1991
|
// Actions available
|
|
@@ -2083,6 +2084,13 @@ export const messages = {
|
|
|
2083
2084
|
refsInSync: '{path}:參考已同步({count} 個參考)',
|
|
2084
2085
|
noIntegrationRefs: '找不到有標準參考的整合檔案。',
|
|
2085
2086
|
runSyncRefs: '執行 `uds update --sync-refs` 修復參考問題。',
|
|
2087
|
+
runIntegrationsOnly: '執行 `uds update --integrations-only` 重新產生整合檔案。',
|
|
2088
|
+
danglingRefs: '引用了磁碟上不存在的檔案:',
|
|
2089
|
+
brokenMentions: '提到了本專案裡不存在的路徑:',
|
|
2090
|
+
brokenMentionsFix: '這些通常在 UDS 區塊之外,是舊版安裝留下的。UDS 不會改寫不是它寫的文字——請手動更正或刪掉那一行。',
|
|
2091
|
+
danglingRefsFix: '執行 `uds update --integrations-only` 重新產生。',
|
|
2092
|
+
commandsUntracked: '{count} 個已安裝的斜線命令沒有任何雜湊涵蓋——這些檔案的完整性沒有被檢查',
|
|
2093
|
+
commandsUntrackedFix: '執行 `uds update --commands` 重新記錄。',
|
|
2086
2094
|
// CLI update
|
|
2087
2095
|
checkingCliUpdates: '正在檢查 CLI 更新...',
|
|
2088
2096
|
couldNotCheckUpdates: 'ℹ 無法檢查 CLI 更新(離線模式)',
|
|
@@ -2168,7 +2176,6 @@ export const messages = {
|
|
|
2168
2176
|
standardsScopeLean: '精簡(Skills 處理其餘)',
|
|
2169
2177
|
standardsScopeComplete: '完整',
|
|
2170
2178
|
contentModeLabel: '內容模式',
|
|
2171
|
-
contentModeFull: '完整嵌入',
|
|
2172
2179
|
contentModeIndex: '標準(推薦)',
|
|
2173
2180
|
contentModeMinimal: '最小(僅核心)',
|
|
2174
2181
|
displayLanguageLabel: '顯示語言',
|
|
@@ -2203,7 +2210,8 @@ export const messages = {
|
|
|
2203
2210
|
generatingAgentsMd: '產生 AGENTS.md(通用摘要)中...',
|
|
2204
2211
|
generatedAgentsMd: '已產生 AGENTS.md(通用摘要)',
|
|
2205
2212
|
couldNotGenerateAgentsMd: '無法產生 AGENTS.md',
|
|
2206
|
-
installingSkills: '安裝
|
|
2213
|
+
installingSkills: '安裝 Skills 中...',
|
|
2214
|
+
skillsPathUnknown: '沒有查證過的 skills 路徑,這個工具沒有安裝任何東西',
|
|
2207
2215
|
installedSkills: '已安裝 {count} 個 Skills 到 {locations}',
|
|
2208
2216
|
installedSkillsWithErrors: '已安裝 {count} 個 Skills,有 {errors} 個錯誤',
|
|
2209
2217
|
// P1-CLI-1:locale fallback 摘要(安裝結束後顯示,列出沒有對應語系變體而退回英文來源的 skill)
|
|
@@ -2259,6 +2267,7 @@ export const messages = {
|
|
|
2259
2267
|
syncingIntegrations: '同步整合檔案中...',
|
|
2260
2268
|
syncedIntegrations: '已同步 {count} 個整合檔案',
|
|
2261
2269
|
prunedOrphanedBlockHashes: '已清除 {count} 個孤兒整合雜湊:{files}',
|
|
2270
|
+
droppedRetiredHashes: '已清掉 {count} 筆 manifest 紀錄——這些檔案 UDS 已不再出貨,而且本來就已經不在了:',
|
|
2262
2271
|
// Success
|
|
2263
2272
|
updateSuccess: '✓ 標準更新成功!',
|
|
2264
2273
|
versionUpdated: '版本:{current} → {latest}',
|
|
@@ -2286,6 +2295,7 @@ export const messages = {
|
|
|
2286
2295
|
// Sync refs
|
|
2287
2296
|
syncingRefs: '同步整合參考中...',
|
|
2288
2297
|
noIntegrationConfigs: '⚠ manifest 中找不到整合設定。',
|
|
2298
|
+
integrationConfigsBackfilled: '已從 manifest 重建 {count} 個整合檔的設定。',
|
|
2289
2299
|
integrationConfigsRequired: '參考同步需要整合設定。',
|
|
2290
2300
|
thisHappensWhen: '這會發生在:',
|
|
2291
2301
|
oldVersion: '- 專案使用較舊版本的 UDS 初始化',
|
|
@@ -2567,12 +2577,10 @@ export const messages = {
|
|
|
2567
2577
|
question: '选择内容模式:',
|
|
2568
2578
|
labels: {
|
|
2569
2579
|
index: '标准',
|
|
2570
|
-
full: '完整嵌入',
|
|
2571
2580
|
minimal: '最小化'
|
|
2572
2581
|
},
|
|
2573
2582
|
choices: {
|
|
2574
2583
|
index: '摘要 + 任务对照表,AI 知道何时读哪个规范',
|
|
2575
|
-
full: '完整嵌入所有规则,AI 立即可用但文件较大',
|
|
2576
2584
|
minimal: '仅文件参考,适合搭配 Skills 使用'
|
|
2577
2585
|
},
|
|
2578
2586
|
explanations: {
|
|
@@ -2581,11 +2589,6 @@ export const messages = {
|
|
|
2581
2589
|
' → AI 能判断"做什么任务时要读哪个规范"',
|
|
2582
2590
|
' → 平衡 Context 使用量和合规程度'
|
|
2583
2591
|
],
|
|
2584
|
-
full: [
|
|
2585
|
-
' → 所有规则直接嵌入配置文件(文件约 10-15 KB)',
|
|
2586
|
-
' → AI 无需额外读档,合规率最高',
|
|
2587
|
-
' → 适合短期任务或需要严格遵循的项目'
|
|
2588
|
-
],
|
|
2589
2592
|
minimal: [
|
|
2590
2593
|
' → 仅包含 .standards/ 文件清单',
|
|
2591
2594
|
' → AI 需要主动读取规范文件',
|
|
@@ -2795,7 +2798,6 @@ export const messages = {
|
|
|
2795
2798
|
warning: '变更 Content Mode 将重新生成所有 AI 工具配置文件',
|
|
2796
2799
|
explanations: {
|
|
2797
2800
|
index: ' → AI 会根据任务对照表判断何时读取规范',
|
|
2798
|
-
full: ' → 所有规则直接嵌入,AI 合规率最高',
|
|
2799
2801
|
minimal: ' → AI 需主动读取规范,建议搭配 Skills'
|
|
2800
2802
|
}
|
|
2801
2803
|
},
|
|
@@ -3144,7 +3146,6 @@ export const messages = {
|
|
|
3144
3146
|
standardsScopeLean: '精简(Skills 处理其余)',
|
|
3145
3147
|
standardsScopeComplete: '完整',
|
|
3146
3148
|
contentModeLabel: '内容模式',
|
|
3147
|
-
contentModeFull: '完整嵌入',
|
|
3148
3149
|
contentModeIndex: '标准(推荐)',
|
|
3149
3150
|
contentModeMinimal: '最小(仅核心)',
|
|
3150
3151
|
displayLanguageLabel: '显示语言',
|
|
@@ -3234,6 +3235,9 @@ export const messages = {
|
|
|
3234
3235
|
unchanged: '未更改',
|
|
3235
3236
|
modified: '已修改',
|
|
3236
3237
|
missing: '缺失',
|
|
3238
|
+
retired: 'UDS 已不再发布',
|
|
3239
|
+
retiredHeader: '有 {count} 个被追踪的文件不见了,原因是 UDS 已不再发布。那是迁移完成的样子,不是故障:',
|
|
3240
|
+
retiredHint: '执行 `uds update` 清掉它们在 manifest 的记录。`--restore` 救不回来——上游已经没有来源。',
|
|
3237
3241
|
existsNoHash: '存在,无哈希',
|
|
3238
3242
|
summary: '摘要:{unchanged} 未更改,{modified} 已修改,{missing} 缺失',
|
|
3239
3243
|
// Actions available
|
|
@@ -3332,6 +3336,13 @@ export const messages = {
|
|
|
3332
3336
|
refsInSync: '{path}:引用已同步({count} 个引用)',
|
|
3333
3337
|
noIntegrationRefs: '未找到包含标准引用的集成文件。',
|
|
3334
3338
|
runSyncRefs: '执行 `uds update --sync-refs` 修复引用问题。',
|
|
3339
|
+
runIntegrationsOnly: '执行 `uds update --integrations-only` 重新生成集成文件。',
|
|
3340
|
+
danglingRefs: '引用了磁盘上不存在的文件:',
|
|
3341
|
+
brokenMentions: '提到了本项目里不存在的路径:',
|
|
3342
|
+
brokenMentionsFix: '这些通常在 UDS 区块之外,是旧版安装留下的。UDS 不会改写不是它写的文字——请手动更正或删掉那一行。',
|
|
3343
|
+
danglingRefsFix: '执行 `uds update --integrations-only` 重新生成。',
|
|
3344
|
+
commandsUntracked: '{count} 个已安装的斜杠命令没有任何哈希覆盖——这些文件的完整性没有被检查',
|
|
3345
|
+
commandsUntrackedFix: '执行 `uds update --commands` 重新记录。',
|
|
3335
3346
|
// CLI update
|
|
3336
3347
|
checkingCliUpdates: '检查 CLI 更新...',
|
|
3337
3348
|
couldNotCheckUpdates: 'ℹ 无法检查 CLI 更新(离线模式)',
|
|
@@ -3421,6 +3432,7 @@ export const messages = {
|
|
|
3421
3432
|
syncingIntegrations: '正在同步集成文件...',
|
|
3422
3433
|
syncedIntegrations: '已同步 {count} 个集成文件',
|
|
3423
3434
|
prunedOrphanedBlockHashes: '已清除 {count} 个孤儿集成哈希:{files}',
|
|
3435
|
+
droppedRetiredHashes: '已清掉 {count} 笔 manifest 记录——这些文件 UDS 已不再发布,而且本来就已经不在了:',
|
|
3424
3436
|
// Success
|
|
3425
3437
|
updateSuccess: '✓ 标准更新成功!',
|
|
3426
3438
|
versionUpdated: '版本:{current} → {latest}',
|
|
@@ -3448,6 +3460,7 @@ export const messages = {
|
|
|
3448
3460
|
// Sync refs
|
|
3449
3461
|
syncingRefs: '正在同步集成引用...',
|
|
3450
3462
|
noIntegrationConfigs: '⚠ manifest 中未找到集成配置。',
|
|
3463
|
+
integrationConfigsBackfilled: '已从 manifest 重建 {count} 个集成文件的配置。',
|
|
3451
3464
|
integrationConfigsRequired: '引用同步需要集成配置。',
|
|
3452
3465
|
thisHappensWhen: '发生这种情况时:',
|
|
3453
3466
|
oldVersion: '- 项目使用旧版 UDS 初始化',
|
|
@@ -1,105 +1,197 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* UDS Hook Installer
|
|
3
3
|
*
|
|
4
|
-
* Copies hook scripts and
|
|
5
|
-
*
|
|
4
|
+
* Copies hook scripts and merges .claude/settings.json with hook configurations
|
|
5
|
+
* derived from the `enforcement:` blocks of the shipped standards.
|
|
6
6
|
*
|
|
7
7
|
* Key constraints:
|
|
8
8
|
* - MUST merge, never overwrite existing settings.json
|
|
9
9
|
* - MUST be idempotent (no duplicate hooks on re-install)
|
|
10
|
+
* - MUST emit the hook handler shape Claude Code actually executes
|
|
11
|
+
*
|
|
12
|
+
* 🔴 Three defects fixed here on 2026-09-08, each of which failed silently and
|
|
13
|
+
* all three of which were present at once:
|
|
14
|
+
*
|
|
15
|
+
* 1. Hook entries were written as bare strings (`hooks: ['node x.js']`).
|
|
16
|
+
* Measured with a two-arm run — a bare-string entry and an object entry
|
|
17
|
+
* side by side in the same event of the same session: the object ran, the
|
|
18
|
+
* bare string did not. Claude Code dispatches on `type`, and an entry
|
|
19
|
+
* without one is skipped. settings.json stays valid JSON, the install
|
|
20
|
+
* reports success, and nothing ever runs.
|
|
21
|
+
* 2. The hook scripts were resolved from `<repo>/scripts/hooks`, which is
|
|
22
|
+
* outside the published package (`npm pack` listed 1 file matching
|
|
23
|
+
* "hooks": this installer). Adopters installing from npm copied zero
|
|
24
|
+
* scripts and still got `installed: true`.
|
|
25
|
+
* 3. The event/script list was hardcoded here, so a standard declaring an
|
|
26
|
+
* `enforcement:` block got no hook unless someone also remembered to edit
|
|
27
|
+
* this file. It is now derived by walking the standards.
|
|
10
28
|
*
|
|
11
29
|
* @module installers/hooks-installer
|
|
12
30
|
* @see docs/specs/SPEC-HOOKS-001-core-standard-hooks.md (REQ-4)
|
|
31
|
+
* @see core/turn-completion-integrity.md
|
|
13
32
|
*/
|
|
14
33
|
|
|
15
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync,
|
|
16
|
-
import { join, dirname } from 'path';
|
|
34
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, cpSync, readdirSync } from 'fs';
|
|
35
|
+
import { join, dirname, basename } from 'path';
|
|
17
36
|
import { fileURLToPath } from 'url';
|
|
37
|
+
import { execFileSync } from 'child_process';
|
|
38
|
+
import { load as parseYaml } from 'js-yaml';
|
|
18
39
|
|
|
19
40
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
20
41
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
/** Prefer the bundled copy (present in the npm package), fall back to the repo. */
|
|
43
|
+
function resolveDir(bundledRel, repoRel) {
|
|
44
|
+
const bundled = join(__dirname, '..', '..', 'bundled', ...bundledRel);
|
|
45
|
+
if (existsSync(bundled)) return bundled;
|
|
46
|
+
const repo = join(__dirname, '..', '..', '..', ...repoRel);
|
|
47
|
+
return existsSync(repo) ? repo : null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const standardsSourceDir = () => resolveDir(['ai', 'standards'], ['ai', 'standards']);
|
|
51
|
+
export const hooksSourceDir = () => resolveDir(['hooks'], ['scripts', 'hooks']);
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Claude Code's matcher is a string. Some standards declare it as an object
|
|
55
|
+
* (`matcher: { tool: Bash }`), which would be written into settings.json
|
|
56
|
+
* verbatim and never match anything.
|
|
57
|
+
*/
|
|
58
|
+
function normalizeMatcher(matcher) {
|
|
59
|
+
if (typeof matcher === 'string') return matcher;
|
|
60
|
+
if (matcher && typeof matcher === 'object' && typeof matcher.tool === 'string') return matcher.tool;
|
|
61
|
+
return '';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Walk the shipped standards and build the hook configuration from every
|
|
66
|
+
* complete `enforcement:` block.
|
|
67
|
+
*
|
|
68
|
+
* @param {string|null} stdDir - directory of *.ai.yaml standards
|
|
69
|
+
* @param {string|null} hookDir - directory the hook scripts live in
|
|
70
|
+
* @returns {{ configs: Object, scripts: string[], skipped: Array<{id: string, why: string}> }}
|
|
71
|
+
*/
|
|
72
|
+
export function collectHookConfigs(stdDir, hookDir) {
|
|
73
|
+
const configs = {};
|
|
74
|
+
const scripts = [];
|
|
75
|
+
const skipped = [];
|
|
76
|
+
if (!stdDir) return { configs, scripts, skipped: [{ id: '*', why: 'standards directory not found' }] };
|
|
77
|
+
|
|
78
|
+
for (const file of readdirSync(stdDir).filter((f) => f.endsWith('.ai.yaml')).sort()) {
|
|
79
|
+
let std;
|
|
80
|
+
try {
|
|
81
|
+
std = parseYaml(readFileSync(join(stdDir, file), 'utf-8'));
|
|
82
|
+
} catch {
|
|
83
|
+
skipped.push({ id: file, why: 'unparseable YAML' });
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const e = std && std.enforcement;
|
|
87
|
+
if (!e) continue;
|
|
88
|
+
|
|
89
|
+
const id = (std && std.id) || file;
|
|
90
|
+
if (typeof e.trigger !== 'string' || !e.trigger || typeof e.hook_script !== 'string' || !e.hook_script) {
|
|
91
|
+
// A block missing either field used to compile to hooks["undefined"]:
|
|
92
|
+
// [{ hooks: ["node undefined"] }] with no error at any layer.
|
|
93
|
+
skipped.push({ id, why: 'enforcement block missing trigger or hook_script' });
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const rel = e.hook_script.replace(/^scripts\/hooks\//, '');
|
|
98
|
+
if (hookDir && !existsSync(join(hookDir, rel))) {
|
|
99
|
+
skipped.push({ id, why: `hook script not found: ${e.hook_script}` });
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
(configs[e.trigger] ||= []).push({
|
|
104
|
+
matcher: normalizeMatcher(e.matcher),
|
|
105
|
+
hooks: [{ type: 'command', command: `node scripts/hooks/${rel}` }],
|
|
106
|
+
});
|
|
107
|
+
scripts.push(rel);
|
|
108
|
+
}
|
|
109
|
+
return { configs, scripts, skipped };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** The command string an entry runs, whatever shape it is stored in. */
|
|
113
|
+
function commandOf(entry) {
|
|
114
|
+
const h = entry && entry.hooks && entry.hooks[0];
|
|
115
|
+
if (typeof h === 'string') return h;
|
|
116
|
+
return h && typeof h.command === 'string' ? h.command : undefined;
|
|
117
|
+
}
|
|
47
118
|
|
|
48
119
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* @param {Array} incoming - New hook entries to merge
|
|
52
|
-
* @returns {Array} Merged array without duplicates
|
|
120
|
+
* Merge hook arrays, deduplicating by (command, matcher).
|
|
121
|
+
* Existing entries are never rewritten — an adopter may have edited them.
|
|
53
122
|
*/
|
|
54
|
-
function mergeHookArray(existing, incoming) {
|
|
123
|
+
export function mergeHookArray(existing, incoming) {
|
|
55
124
|
const result = [...existing];
|
|
56
125
|
for (const entry of incoming) {
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
);
|
|
61
|
-
if (!isDuplicate) {
|
|
62
|
-
result.push(entry);
|
|
63
|
-
}
|
|
126
|
+
const cmd = commandOf(entry);
|
|
127
|
+
const dup = result.some((e) => commandOf(e) === cmd && e.matcher === entry.matcher);
|
|
128
|
+
if (!dup) result.push(entry);
|
|
64
129
|
}
|
|
65
130
|
return result;
|
|
66
131
|
}
|
|
67
132
|
|
|
68
133
|
/**
|
|
69
134
|
* Install UDS hooks into a target project.
|
|
70
|
-
* - Copies hook scripts to scripts/hooks/
|
|
71
|
-
* - Creates or merges .claude/settings.json with hook configs
|
|
72
135
|
*
|
|
73
136
|
* @param {string} projectPath - Target project root path
|
|
74
|
-
* @returns {{ installed: boolean, scriptsCount: number, settingsPath: string }}
|
|
137
|
+
* @returns {{ installed: boolean, scriptsCount: number, settingsPath: string, events: string[], skipped: Array }}
|
|
138
|
+
*/
|
|
139
|
+
/**
|
|
140
|
+
* Which installed hooks only work in some languages, asked of the hooks themselves.
|
|
141
|
+
*
|
|
142
|
+
* turn-completion-integrity R8 says an unsupported language must be declared,
|
|
143
|
+
* and the hook already answers `--languages`. Restating that list here would
|
|
144
|
+
* make a second hand-maintained copy of it, and the copy would drift — quietly,
|
|
145
|
+
* because both halves keep looking like valid data.
|
|
146
|
+
*
|
|
147
|
+
* 🔴 Why it matters at all: a prose-reading hook in a language it does not ship
|
|
148
|
+
* is installed, running, and structurally unable to fire. Its output is
|
|
149
|
+
* byte-identical to a turn with nothing wrong. Without this line the adopter
|
|
150
|
+
* has no way to tell those apart, ever.
|
|
151
|
+
*
|
|
152
|
+
* A hook with no such flag simply produces nothing here; failure is not an
|
|
153
|
+
* error, because "cannot introspect" must not block an install.
|
|
75
154
|
*/
|
|
155
|
+
function probeLanguageLimits(hooksDir, scripts) {
|
|
156
|
+
const out = [];
|
|
157
|
+
for (const rel of new Set(scripts)) {
|
|
158
|
+
const abs = join(hooksDir, basename(rel));
|
|
159
|
+
if (!existsSync(abs)) continue;
|
|
160
|
+
try {
|
|
161
|
+
const text = execFileSync(process.execPath, [abs, '--languages'], {
|
|
162
|
+
encoding: 'utf-8',
|
|
163
|
+
timeout: 5000,
|
|
164
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
165
|
+
}).trim();
|
|
166
|
+
if (text) out.push({ script: basename(rel), languages: text });
|
|
167
|
+
} catch {
|
|
168
|
+
// no --languages, or it refused: nothing to declare.
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return out;
|
|
172
|
+
}
|
|
173
|
+
|
|
76
174
|
export function installHooks(projectPath) {
|
|
77
175
|
const claudeDir = join(projectPath, '.claude');
|
|
78
176
|
const settingsPath = join(claudeDir, 'settings.json');
|
|
177
|
+
const hooksDir = join(projectPath, 'scripts', 'hooks');
|
|
79
178
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
179
|
+
const stdDir = standardsSourceDir();
|
|
180
|
+
const hookDir = hooksSourceDir();
|
|
181
|
+
const { configs, scripts, skipped } = collectHookConfigs(stdDir, hookDir);
|
|
182
|
+
const events = Object.keys(configs);
|
|
84
183
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
mkdirSync(hooksDir, { recursive: true });
|
|
184
|
+
if (events.length === 0) {
|
|
185
|
+
// Reporting success here is what let three separate breakages ship.
|
|
186
|
+
return { installed: false, scriptsCount: 0, settingsPath, events, skipped };
|
|
89
187
|
}
|
|
90
188
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (existsSync(src)) {
|
|
97
|
-
copyFileSync(src, dest);
|
|
98
|
-
scriptsCount++;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
189
|
+
if (!existsSync(claudeDir)) mkdirSync(claudeDir, { recursive: true });
|
|
190
|
+
if (!existsSync(hooksDir)) mkdirSync(hooksDir, { recursive: true });
|
|
191
|
+
|
|
192
|
+
// Recursive: a hook may ship a directory beside it (locale packs, fixtures).
|
|
193
|
+
cpSync(hookDir, hooksDir, { recursive: true });
|
|
101
194
|
|
|
102
|
-
// Read or create settings.json
|
|
103
195
|
let settings = {};
|
|
104
196
|
if (existsSync(settingsPath)) {
|
|
105
197
|
try {
|
|
@@ -108,21 +200,21 @@ export function installHooks(projectPath) {
|
|
|
108
200
|
settings = {};
|
|
109
201
|
}
|
|
110
202
|
}
|
|
203
|
+
if (!settings.hooks) settings.hooks = {};
|
|
111
204
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
settings.hooks = {};
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
for (const [event, entries] of Object.entries(HOOK_CONFIGS)) {
|
|
118
|
-
if (!settings.hooks[event]) {
|
|
119
|
-
settings.hooks[event] = [];
|
|
120
|
-
}
|
|
205
|
+
for (const [event, entries] of Object.entries(configs)) {
|
|
206
|
+
if (!settings.hooks[event]) settings.hooks[event] = [];
|
|
121
207
|
settings.hooks[event] = mergeHookArray(settings.hooks[event], entries);
|
|
122
208
|
}
|
|
123
209
|
|
|
124
|
-
// Write settings.json
|
|
125
210
|
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
126
211
|
|
|
127
|
-
return {
|
|
212
|
+
return {
|
|
213
|
+
installed: true,
|
|
214
|
+
scriptsCount: new Set(scripts).size,
|
|
215
|
+
settingsPath,
|
|
216
|
+
events,
|
|
217
|
+
skipped,
|
|
218
|
+
languageLimits: probeLanguageLimits(hooksDir, scripts),
|
|
219
|
+
};
|
|
128
220
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createSpinner } from '../utils/spinner.js';
|
|
2
2
|
import { copyIntegration } from '../utils/copier.js';
|
|
3
3
|
import {
|
|
4
4
|
writeIntegrationFile,
|
|
@@ -32,11 +32,15 @@ export const INTEGRATION_MAPPINGS = {
|
|
|
32
32
|
target: '.github/copilot-instructions.md'
|
|
33
33
|
},
|
|
34
34
|
antigravity: {
|
|
35
|
-
source: 'integrations/google-antigravity/
|
|
36
|
-
target: '
|
|
35
|
+
source: 'integrations/google-antigravity/AGENTS.md',
|
|
36
|
+
target: '.agents/AGENTS.md'
|
|
37
37
|
},
|
|
38
38
|
codex: {
|
|
39
|
-
|
|
39
|
+
// 🔴 Was 'integrations/openai-codex/AGENTS.md'; that directory does not exist.
|
|
40
|
+
// This map is only reached when generation fails, so a broken entry here is a
|
|
41
|
+
// fallback that fails exactly when it is needed. Found by walking the map and
|
|
42
|
+
// stat-ing every source — nothing was checking that these paths resolve.
|
|
43
|
+
source: 'integrations/codex/AGENTS.md',
|
|
40
44
|
target: 'AGENTS.md'
|
|
41
45
|
},
|
|
42
46
|
'gemini-cli': {
|
|
@@ -56,7 +60,7 @@ export const INTEGRATION_MAPPINGS = {
|
|
|
56
60
|
* @param {Array<string>} config.integrations - List of AI tool names (e.g., ['cursor', 'windsurf'])
|
|
57
61
|
* @param {Object} config.integrationConfigs - Tool-specific configurations
|
|
58
62
|
* @param {Array<string>} config.installedStandards - List of installed standard file names
|
|
59
|
-
* @param {string} config.contentMode - Content mode ('minimal', 'index'
|
|
63
|
+
* @param {string} config.contentMode - Content mode ('minimal', 'index'; 'full' retired — XSPEC-357 R7)
|
|
60
64
|
* @param {number} config.level - Adoption level (1-3)
|
|
61
65
|
* @param {string} config.commonLanguage - Language setting ('en', 'zh-tw', 'zh-cn', 'bilingual')
|
|
62
66
|
* @param {string} config.outputLanguage - Output language preference
|
|
@@ -95,7 +99,7 @@ export async function installIntegrations(config, projectPath) {
|
|
|
95
99
|
}
|
|
96
100
|
|
|
97
101
|
// Start installation spinner
|
|
98
|
-
const intSpinner =
|
|
102
|
+
const intSpinner = createSpinner(msg.generatingIntegrations).start();
|
|
99
103
|
|
|
100
104
|
// Track generated files to handle AGENTS.md sharing (codex + opencode)
|
|
101
105
|
const generatedFiles = new Set();
|
|
@@ -191,7 +195,7 @@ export async function installIntegrations(config, projectPath) {
|
|
|
191
195
|
* @param {Object} config - Claude Code configuration
|
|
192
196
|
* @param {Array<string>} config.aiTools - List of selected AI tools
|
|
193
197
|
* @param {Array<string>} config.installedStandards - List of installed standard file names
|
|
194
|
-
* @param {string} config.contentMode - Content mode ('minimal', 'index'
|
|
198
|
+
* @param {string} config.contentMode - Content mode ('minimal', 'index'; 'full' retired — XSPEC-357 R7)
|
|
195
199
|
* @param {number} config.level - Adoption level (1-3)
|
|
196
200
|
* @param {string} config.commonLanguage - Language setting ('en', 'zh-tw', 'zh-cn', 'bilingual')
|
|
197
201
|
* @param {string} config.outputLanguage - Output language preference
|
|
@@ -220,7 +224,7 @@ export async function generateClaudeMd(config, projectPath) {
|
|
|
220
224
|
return { path: null, error: null };
|
|
221
225
|
}
|
|
222
226
|
|
|
223
|
-
const claudeSpinner =
|
|
227
|
+
const claudeSpinner = createSpinner(msg.generatingClaudeMd).start();
|
|
224
228
|
|
|
225
229
|
// Derive categories from installedStandards to avoid referencing non-installed standards
|
|
226
230
|
const categories = installedStandards.length > 0
|
|
@@ -281,7 +285,7 @@ export async function generateUniversalAgentsMd(config, integrationResults, proj
|
|
|
281
285
|
}
|
|
282
286
|
|
|
283
287
|
const msg = t().commands.init;
|
|
284
|
-
const spinner =
|
|
288
|
+
const spinner = createSpinner(msg.generatingAgentsMd || 'Generating AGENTS.md...').start();
|
|
285
289
|
|
|
286
290
|
const outputLanguage = config.outputLanguage || config.commitLanguage ||
|
|
287
291
|
config.standardOptions?.output_language || config.standardOptions?.commit_language ||
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* @version 1.0.0
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import
|
|
16
|
+
import { createSpinner } from '../utils/spinner.js';
|
|
17
17
|
import chalk from 'chalk';
|
|
18
18
|
import {
|
|
19
19
|
installSkillsToMultipleAgents,
|
|
@@ -115,7 +115,7 @@ function getSkillFiles() {
|
|
|
115
115
|
export async function installSkills(skillsConfig, projectPath, messages, results) {
|
|
116
116
|
// Modern unified multi-agent installation
|
|
117
117
|
if (skillsConfig.needsInstall && skillsConfig.skillsInstallations?.length > 0) {
|
|
118
|
-
const skillSpinner =
|
|
118
|
+
const skillSpinner = createSpinner(messages.installingSkills).start();
|
|
119
119
|
|
|
120
120
|
// Use new unified installer for multi-agent support
|
|
121
121
|
const installResult = await installSkillsToMultipleAgents(
|
|
@@ -186,7 +186,7 @@ export async function installSkills(skillsConfig, projectPath, messages, results
|
|
|
186
186
|
* @returns {Promise<void>}
|
|
187
187
|
*/
|
|
188
188
|
async function installSkillsLegacy(skillsConfig, projectPath, messages, results) {
|
|
189
|
-
const skillSpinner =
|
|
189
|
+
const skillSpinner = createSpinner(messages.installingSkills).start();
|
|
190
190
|
|
|
191
191
|
const skillFiles = getSkillFiles();
|
|
192
192
|
let successCount = 0;
|
|
@@ -255,7 +255,7 @@ export async function installCommands(skillsConfig, projectPath, messages, resul
|
|
|
255
255
|
return;
|
|
256
256
|
}
|
|
257
257
|
|
|
258
|
-
const cmdSpinner =
|
|
258
|
+
const cmdSpinner = createSpinner(messages.installingCommands || 'Installing slash commands...').start();
|
|
259
259
|
|
|
260
260
|
const cmdResult = await installCommandsToMultipleAgents(
|
|
261
261
|
skillsConfig.commandsInstallations,
|