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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import
|
|
2
|
+
import { createSpinner } from '../utils/spinner.js';
|
|
3
3
|
import { basename, join } from 'path';
|
|
4
4
|
import {
|
|
5
5
|
getAllStandards,
|
|
@@ -75,7 +75,7 @@ export async function installStandards(config, projectPath) {
|
|
|
75
75
|
};
|
|
76
76
|
|
|
77
77
|
// Start copying standards
|
|
78
|
-
const copySpinner =
|
|
78
|
+
const copySpinner = createSpinner(msg.copyingStandards).start();
|
|
79
79
|
|
|
80
80
|
// Copy standards based on format
|
|
81
81
|
const formatsToUse = config.format === 'both' ? ['ai', 'human'] : [config.format];
|
|
@@ -113,7 +113,7 @@ export async function installStandards(config, projectPath) {
|
|
|
113
113
|
const localeExtension = (config.displayLanguage === 'zh-tw' || config.displayLanguage === 'zh-cn') ? config.displayLanguage : null;
|
|
114
114
|
|
|
115
115
|
if (config.languages.length > 0 || config.frameworks.length > 0 || localeExtension) {
|
|
116
|
-
const extSpinner =
|
|
116
|
+
const extSpinner = createSpinner(msg.copyingExtensions).start();
|
|
117
117
|
|
|
118
118
|
for (const lang of config.languages) {
|
|
119
119
|
if (EXTENSION_MAPPINGS[lang]) {
|
package/src/prompts/init.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { select, checkbox, confirm as inquirerConfirm, Separator, input } from '@inquirer/prompts';
|
|
2
|
-
import { existsSync, writeFileSync, readdirSync } from 'fs';
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync, readdirSync } from 'fs';
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import os from 'os';
|
|
@@ -109,7 +109,7 @@ export async function promptAITools(detected = {}) {
|
|
|
109
109
|
checked: detected.copilot || false
|
|
110
110
|
},
|
|
111
111
|
{
|
|
112
|
-
name: `Google Antigravity ${chalk.gray('(
|
|
112
|
+
name: `Google Antigravity ${chalk.gray('(.agents/AGENTS.md)')}`,
|
|
113
113
|
value: 'antigravity',
|
|
114
114
|
checked: detected.antigravity || false
|
|
115
115
|
},
|
|
@@ -1053,10 +1053,14 @@ export async function promptConfirm(message) {
|
|
|
1053
1053
|
* Best with Skills (which provide real-time guidance).
|
|
1054
1054
|
* - index: Summary + MUST/SHOULD task mapping. AI knows when to read which file.
|
|
1055
1055
|
* Best balance of context usage and compliance.
|
|
1056
|
-
* - full: All rules embedded. AI has everything in context immediately.
|
|
1057
|
-
* Highest compliance but uses more context space.
|
|
1058
1056
|
*
|
|
1059
|
-
*
|
|
1057
|
+
* A third choice, `full` ("all rules embedded, highest compliance, uses more
|
|
1058
|
+
* context"), was removed in XSPEC-357 R7. None of that was true: it shared the
|
|
1059
|
+
* `index` branch in the generator and produced identical bytes. Offering it
|
|
1060
|
+
* asked adopters to trade context budget for compliance in a menu where both
|
|
1061
|
+
* options were the same file. (XSPEC-357 R7)
|
|
1062
|
+
*
|
|
1063
|
+
* @returns {Promise<string>} 'index' or 'minimal'
|
|
1060
1064
|
*/
|
|
1061
1065
|
export async function promptContentMode() {
|
|
1062
1066
|
const msg = t().contentMode;
|
|
@@ -1075,10 +1079,6 @@ export async function promptContentMode() {
|
|
|
1075
1079
|
name: `${chalk.green(msg.labels.index)} ${chalk.gray(`(${t().recommended})`)} - ${msg.choices.index}`,
|
|
1076
1080
|
value: 'index'
|
|
1077
1081
|
},
|
|
1078
|
-
{
|
|
1079
|
-
name: `${chalk.blue(msg.labels.full)} - ${msg.choices.full}`,
|
|
1080
|
-
value: 'full'
|
|
1081
|
-
},
|
|
1082
1082
|
{
|
|
1083
1083
|
name: `${chalk.gray(msg.labels.minimal)} - ${msg.choices.minimal}`,
|
|
1084
1084
|
value: 'minimal'
|
|
@@ -1159,7 +1159,7 @@ const AI_TOOL_DEFINITIONS = {
|
|
|
1159
1159
|
windsurf: { name: 'Windsurf', file: '.windsurfrules' },
|
|
1160
1160
|
cline: { name: 'Cline', file: '.clinerules' },
|
|
1161
1161
|
copilot: { name: 'GitHub Copilot', file: '.github/copilot-instructions.md' },
|
|
1162
|
-
antigravity: { name: 'Google Antigravity', file: '
|
|
1162
|
+
antigravity: { name: 'Google Antigravity', file: '.agents/AGENTS.md' },
|
|
1163
1163
|
codex: { name: 'OpenAI Codex', file: 'AGENTS.md' },
|
|
1164
1164
|
'gemini-cli': { name: 'Gemini CLI', file: 'GEMINI.md' },
|
|
1165
1165
|
opencode: { name: 'OpenCode', file: 'AGENTS.md' }
|
|
@@ -1286,16 +1286,16 @@ export async function promptContentModeChange(currentMode) {
|
|
|
1286
1286
|
name: `${chalk.green(msg.labels.index)} ${chalk.gray(`(${t().recommended})`)} - ${msg.choices.index}`,
|
|
1287
1287
|
value: 'index'
|
|
1288
1288
|
},
|
|
1289
|
-
{
|
|
1290
|
-
name: `${chalk.blue(msg.labels.full)} - ${msg.choices.full}`,
|
|
1291
|
-
value: 'full'
|
|
1292
|
-
},
|
|
1293
1289
|
{
|
|
1294
1290
|
name: `${chalk.gray(msg.labels.minimal)} - ${msg.choices.minimal}`,
|
|
1295
1291
|
value: 'minimal'
|
|
1296
1292
|
}
|
|
1297
1293
|
],
|
|
1298
|
-
|
|
1294
|
+
// A stored `full` lands on `index`, which is the mode it was already
|
|
1295
|
+
// getting. Indices shifted when the middle choice went, so this is
|
|
1296
|
+
// recomputed rather than adjusted — an off-by-one here silently
|
|
1297
|
+
// preselects the wrong mode.
|
|
1298
|
+
default: currentMode === 'minimal' ? 1 : 0
|
|
1299
1299
|
});
|
|
1300
1300
|
|
|
1301
1301
|
if (mode !== currentMode) {
|
|
@@ -1385,11 +1385,40 @@ export function suggestCommands(projectPath) {
|
|
|
1385
1385
|
if (existsSync(p('Gemfile')))
|
|
1386
1386
|
return { test: 'bundle exec rspec', lint: 'bundle exec rubocop', build: 'gem build *.gemspec', security: 'bundle audit' };
|
|
1387
1387
|
|
|
1388
|
-
// C# — glob for .csproj / .sln
|
|
1388
|
+
// C# — glob for .csproj / .sln.
|
|
1389
|
+
//
|
|
1390
|
+
// `.csproj` has named two incompatible build systems since 2017. An SDK-style
|
|
1391
|
+
// project (`<Project Sdk="…">`, `<TargetFramework>`) builds with the `dotnet`
|
|
1392
|
+
// CLI. An old-style one (`<TargetFrameworkVersion>`, no Sdk attribute) needs
|
|
1393
|
+
// MSBuild and Visual Studio's targets, and handing it `dotnet build` produces
|
|
1394
|
+
// `MSB4019: could not find Import project …Microsoft.WebApplication.targets`
|
|
1395
|
+
// — reported 2026-09-16 from a .NET Framework 4.8 Web App, which also got
|
|
1396
|
+
// `dotnet list package --vulnerable`, a command that silently reports nothing
|
|
1397
|
+
// for a `packages.config` project because it only reads `PackageReference`.
|
|
1398
|
+
//
|
|
1399
|
+
// For the old style only `build` gets an answer. `dotnet format` requires an
|
|
1400
|
+
// SDK-style project and there is no drop-in equivalent; test discovery
|
|
1401
|
+
// depends on which runner the solution uses. The unknown-ecosystem branch
|
|
1402
|
+
// below already returns blanks "so user fills them in", and a blank a human
|
|
1403
|
+
// completes beats a command that looks authoritative and fails on first use.
|
|
1389
1404
|
try {
|
|
1390
1405
|
const files = readdirSync(projectPath);
|
|
1391
|
-
|
|
1392
|
-
|
|
1406
|
+
const projectFiles = files.filter(f => f.endsWith('.csproj') || f.endsWith('.vbproj'));
|
|
1407
|
+
if (projectFiles.length > 0 || files.some(f => f.endsWith('.sln'))) {
|
|
1408
|
+
const oldStyle = projectFiles.some(f => {
|
|
1409
|
+
try {
|
|
1410
|
+
const xml = readFileSync(join(projectPath, f), 'utf-8');
|
|
1411
|
+
if (/<Project[^>]*\sSdk\s*=/i.test(xml)) return false;
|
|
1412
|
+
return /<TargetFrameworkVersion\s*>/i.test(xml);
|
|
1413
|
+
} catch {
|
|
1414
|
+
return false;
|
|
1415
|
+
}
|
|
1416
|
+
});
|
|
1417
|
+
|
|
1418
|
+
return oldStyle
|
|
1419
|
+
? { test: '', lint: '', build: 'msbuild /t:Build /p:Configuration=Release', security: '' }
|
|
1420
|
+
: { test: 'dotnet test', lint: 'dotnet format --verify-no-changes', build: 'dotnet build', security: 'dotnet list package --vulnerable' };
|
|
1421
|
+
}
|
|
1393
1422
|
} catch {
|
|
1394
1423
|
// ignore read errors
|
|
1395
1424
|
}
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
* Integration files use migrate_block: only the UDS marker block is replaced.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import { isShippedFilename } from '../utils/registry.js';
|
|
18
|
+
|
|
17
19
|
/**
|
|
18
20
|
* @typedef {Object} PlanAction
|
|
19
21
|
* @property {'create'|'update'|'delete'|'migrate_block'|'patch_hook'} type
|
|
@@ -205,12 +207,18 @@ function diffCategory(desiredMap, actualMap, category, actions, warnings, summar
|
|
|
205
207
|
// Check actual entries not in desired → delete (only if UDS-managed)
|
|
206
208
|
for (const [key, actualEntry] of actualMap) {
|
|
207
209
|
if (!desiredMap.has(key)) {
|
|
208
|
-
if (
|
|
210
|
+
if (isUserConfigPath(actualEntry.relativePath)) {
|
|
211
|
+
// Said out loud rather than skipped quietly: a plan that silently omits
|
|
212
|
+
// things is how the previous round of deletion bugs stayed invisible.
|
|
213
|
+
warnings.push(
|
|
214
|
+
`Keeping ${actualEntry.relativePath}: it holds a setting you chose (uds config writes it), not content UDS ships`
|
|
215
|
+
);
|
|
216
|
+
} else if (isUDSManaged(actualEntry)) {
|
|
209
217
|
actions.push({
|
|
210
218
|
type: 'delete',
|
|
211
219
|
category,
|
|
212
220
|
path: actualEntry.relativePath,
|
|
213
|
-
reason:
|
|
221
|
+
reason: describeDeletion(actualEntry.relativePath, category),
|
|
214
222
|
details: {
|
|
215
223
|
currentHash: actualEntry.hash,
|
|
216
224
|
metadata: actualEntry.metadata
|
|
@@ -330,6 +338,53 @@ function diffIntegrations(desiredMap, actualMap, actions, warnings, summary, for
|
|
|
330
338
|
* Files in .standards/ are always UDS-managed.
|
|
331
339
|
* Skill/command entries from manifest installations are UDS-managed.
|
|
332
340
|
*/
|
|
341
|
+
/**
|
|
342
|
+
* Files under `.standards/` that hold a choice the user made, not content UDS
|
|
343
|
+
* ships.
|
|
344
|
+
*
|
|
345
|
+
* `release-config.yaml` is written by `uds init` from the release mode the user
|
|
346
|
+
* picked and rewritten by `uds config`. Nothing in the desired-state calculator
|
|
347
|
+
* models it, so it fell out of every diff as "no longer in desired state" and
|
|
348
|
+
* into the delete plan — a plan that discards a user setting and calls that
|
|
349
|
+
* reconciliation. Reported 2026-09-16 by an adopter who could not tell from the
|
|
350
|
+
* plan whether the file held anything of theirs. It did.
|
|
351
|
+
*
|
|
352
|
+
* @param {string} relativePath
|
|
353
|
+
* @returns {boolean}
|
|
354
|
+
*/
|
|
355
|
+
export function isUserConfigPath(relativePath) {
|
|
356
|
+
const normalized = String(relativePath || '').replace(/\\/g, '/');
|
|
357
|
+
return normalized === '.standards/release-config.yaml';
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Why this file is being deleted, in terms the adopter can act on.
|
|
362
|
+
*
|
|
363
|
+
* "no longer in desired state" was the reason given for a standard UDS retired
|
|
364
|
+
* upstream, an option the project deselected, and a path the desired state does
|
|
365
|
+
* not model — three different situations, three different right responses, one
|
|
366
|
+
* sentence. The distinction that matters most is the first one: if UDS still
|
|
367
|
+
* ships the file, the change came from this project and is reversible by
|
|
368
|
+
* re-selecting it; if UDS does not, it is gone upstream and re-selecting it will
|
|
369
|
+
* not bring it back.
|
|
370
|
+
*
|
|
371
|
+
* @param {string} relativePath
|
|
372
|
+
* @param {string} category - 'standard' | 'option' | 'skill' | 'command' | …
|
|
373
|
+
* @returns {string}
|
|
374
|
+
*/
|
|
375
|
+
export function describeDeletion(relativePath, category) {
|
|
376
|
+
const normalized = String(relativePath || '').replace(/\\/g, '/');
|
|
377
|
+
|
|
378
|
+
if (category === 'standard' || category === 'option') {
|
|
379
|
+
const fileName = normalized.split('/').pop();
|
|
380
|
+
return isShippedFilename(fileName)
|
|
381
|
+
? 'this project no longer selects it (UDS still ships it, so re-selecting restores it)'
|
|
382
|
+
: 'UDS no longer ships this file (re-selecting will not bring it back)';
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return `not part of what this project's manifest asks for (category: ${category})`;
|
|
386
|
+
}
|
|
387
|
+
|
|
333
388
|
function isUDSManaged(entry) {
|
|
334
389
|
// Files in .standards/ are always UDS-managed
|
|
335
390
|
if (entry.relativePath.startsWith('.standards/')) return true;
|
|
@@ -436,6 +436,22 @@ async function executeSkillBatch(projectPath, skillActions, manifest) {
|
|
|
436
436
|
return results;
|
|
437
437
|
}
|
|
438
438
|
|
|
439
|
+
/**
|
|
440
|
+
* Hash-map key for a command action: `<agent>/<file>`.
|
|
441
|
+
*
|
|
442
|
+
* `commandHashes` is keyed by agent and filename; a plan action carries a
|
|
443
|
+
* project-relative path (`.opencode/command/atdd.md`). Deleting by the wrong key
|
|
444
|
+
* leaves the entry behind and the next `check` reports the file missing.
|
|
445
|
+
*/
|
|
446
|
+
function commandHashKey(action) {
|
|
447
|
+
const meta = action.details?.metadata;
|
|
448
|
+
if (meta?.agent && meta?.commandName) return `${meta.agent}/${meta.commandName}.md`;
|
|
449
|
+
const parts = action.path.split('/').filter(Boolean);
|
|
450
|
+
const agent = parts[0] ? parts[0].replace(/^\./, '') : null;
|
|
451
|
+
const file = parts[parts.length - 1];
|
|
452
|
+
return agent && file ? `${agent}/${file}` : action.path;
|
|
453
|
+
}
|
|
454
|
+
|
|
439
455
|
/**
|
|
440
456
|
* Batch execute command installations.
|
|
441
457
|
*/
|
|
@@ -452,6 +468,9 @@ async function executeCommandBatch(projectPath, commandActions, manifest) {
|
|
|
452
468
|
if (existsSync(targetPath)) {
|
|
453
469
|
rmSync(targetPath, { recursive: true, force: true });
|
|
454
470
|
}
|
|
471
|
+
// A deleted file must also lose its hash entry, or the next check calls
|
|
472
|
+
// it missing for good.
|
|
473
|
+
delete manifest.commandHashes[commandHashKey(action)];
|
|
455
474
|
results.push({ action, success: true });
|
|
456
475
|
} catch (err) {
|
|
457
476
|
results.push({ action, success: false, error: err.message });
|
|
@@ -475,17 +494,18 @@ async function executeCommandBatch(projectPath, commandActions, manifest) {
|
|
|
475
494
|
);
|
|
476
495
|
|
|
477
496
|
if (installResult.allFileHashes) {
|
|
478
|
-
//
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
497
|
+
// Merge, exactly as the skill path above does.
|
|
498
|
+
//
|
|
499
|
+
// 🔴 This used to delete every key whose prefix matched an agent in the
|
|
500
|
+
// result before merging. That is correct only when the installer
|
|
501
|
+
// reinstalled ALL of that agent's commands — which `uds update`'s own
|
|
502
|
+
// call sites do (they pass `commandNames = null`). Here the plan names a
|
|
503
|
+
// subset, so the wipe threw away the entry for every command the plan did
|
|
504
|
+
// not mention. Measured on 6.9.0 (2026-09-16): a three-file drift turned
|
|
505
|
+
// 51 tracked commands into 3, the other 48 stayed on disk untracked, and
|
|
506
|
+
// `uds check` printed "All command files intact (3 files)" in the same run
|
|
507
|
+
// as "Commands: 51 installed" — tampering with one of the 48 changed
|
|
508
|
+
// neither line.
|
|
489
509
|
Object.assign(manifest.commandHashes, installResult.allFileHashes);
|
|
490
510
|
}
|
|
491
511
|
|
package/src/utils/detector.js
CHANGED
|
@@ -126,7 +126,27 @@ export function detectAITools(projectPath) {
|
|
|
126
126
|
copilot: existsSync(join(projectPath, '.github', 'copilot-instructions.md')),
|
|
127
127
|
claudeCode: existsSync(join(projectPath, '.claude')) ||
|
|
128
128
|
existsSync(join(projectPath, 'CLAUDE.md')),
|
|
129
|
-
|
|
129
|
+
// Antigravity never read INSTRUCTIONS.md.
|
|
130
|
+
// Measured 2026-09-08 with two positive controls in the same run: tokens planted in `AGENTS.md` and `.agents/AGENTS.md` both came back with correct attribution; the one in INSTRUCTIONS.md did not.
|
|
131
|
+
// `.agents/AGENTS.md` is used rather than the repo root so it does not collide with Codex/OpenCode, which both target root AGENTS.md.
|
|
132
|
+
antigravity: existsSync(join(projectPath, '.agents', 'AGENTS.md')),
|
|
133
|
+
// 🔴 Roo Code had a full entry in the path table (`.roo/skills/`, tier "complete"
|
|
134
|
+
// in REGISTRY.json) and NO line here, so `uds init` could never install for it —
|
|
135
|
+
// however correct those paths were. Found by `check:install-paths`, which walks
|
|
136
|
+
// the path table instead of naming tools; nothing else was looking.
|
|
137
|
+
//
|
|
138
|
+
// Markers are the ones Roo Code's own docs name, not a guess from the tool name:
|
|
139
|
+
// `.roo/rules/` — "Workspace-wide rules", the current directory-based method
|
|
140
|
+
// `.roorules` — the legacy single-file fallback, still read
|
|
141
|
+
// (roocodeinc.github.io/Roo-Code/features/custom-instructions, read 2026-09-08)
|
|
142
|
+
// `.roo` is matched rather than `.roo/rules` because Roo also uses `.roo/skills/`
|
|
143
|
+
// and `.roo/rules-{mode}/`; the directory is what marks the tool.
|
|
144
|
+
//
|
|
145
|
+
// ⚠️ Deliberately NOT `.clinerules`. REGISTRY.json lists it under Roo Code as
|
|
146
|
+
// legacy backward-compat, and it is also Cline's own marker — detecting on it
|
|
147
|
+
// would make the two tools indistinguishable.
|
|
148
|
+
'roo-code': existsSync(join(projectPath, '.roo')) ||
|
|
149
|
+
existsSync(join(projectPath, '.roorules')),
|
|
130
150
|
codex: hasAgentsMd,
|
|
131
151
|
opencode: hasAgentsMd,
|
|
132
152
|
geminiCli: existsSync(join(projectPath, 'GEMINI.md'))
|