@chinhae/atw-cli 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +128 -451
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +24 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/channel/adapters/claude.d.ts +44 -2
- package/dist/commands/channel/adapters/claude.d.ts.map +1 -1
- package/dist/commands/channel/adapters/claude.js +124 -23
- package/dist/commands/channel/adapters/claude.js.map +1 -1
- package/dist/commands/channel/adapters/codex.d.ts +36 -6
- package/dist/commands/channel/adapters/codex.d.ts.map +1 -1
- package/dist/commands/channel/adapters/codex.js +150 -10
- package/dist/commands/channel/adapters/codex.js.map +1 -1
- package/dist/commands/channel/adapters/index.d.ts +33 -4
- package/dist/commands/channel/adapters/index.d.ts.map +1 -1
- package/dist/commands/channel/adapters/index.js +159 -6
- package/dist/commands/channel/adapters/index.js.map +1 -1
- package/dist/commands/channel/adapters/omp.d.ts +106 -0
- package/dist/commands/channel/adapters/omp.d.ts.map +1 -0
- package/dist/commands/channel/adapters/omp.js +405 -0
- package/dist/commands/channel/adapters/omp.js.map +1 -0
- package/dist/commands/channel/adapters/pi.d.ts +123 -0
- package/dist/commands/channel/adapters/pi.d.ts.map +1 -0
- package/dist/commands/channel/adapters/pi.js +387 -0
- package/dist/commands/channel/adapters/pi.js.map +1 -0
- package/dist/commands/channel/adapters/types.d.ts +16 -0
- package/dist/commands/channel/adapters/types.d.ts.map +1 -1
- package/dist/commands/channel/agent-loader.d.ts +1 -0
- package/dist/commands/channel/agent-loader.d.ts.map +1 -1
- package/dist/commands/channel/agent-loader.js +45 -5
- package/dist/commands/channel/agent-loader.js.map +1 -1
- package/dist/commands/channel/dev-parse-trace.d.ts +1 -1
- package/dist/commands/channel/dev-parse-trace.d.ts.map +1 -1
- package/dist/commands/channel/dev-parse-trace.js +25 -2
- package/dist/commands/channel/dev-parse-trace.js.map +1 -1
- package/dist/commands/channel/index.d.ts.map +1 -1
- package/dist/commands/channel/index.js +44 -12
- package/dist/commands/channel/index.js.map +1 -1
- package/dist/commands/channel/run.d.ts +39 -2
- package/dist/commands/channel/run.d.ts.map +1 -1
- package/dist/commands/channel/run.js +227 -68
- package/dist/commands/channel/run.js.map +1 -1
- package/dist/commands/channel/spawn.d.ts +7 -2
- package/dist/commands/channel/spawn.d.ts.map +1 -1
- package/dist/commands/channel/spawn.js +35 -1
- package/dist/commands/channel/spawn.js.map +1 -1
- package/dist/commands/channel/store/events.d.ts +2 -2
- package/dist/commands/channel/store/events.d.ts.map +1 -1
- package/dist/commands/channel/store/events.js +1 -1
- package/dist/commands/channel/store/events.js.map +1 -1
- package/dist/commands/channel/supervisor/shutdown.d.ts +2 -0
- package/dist/commands/channel/supervisor/shutdown.d.ts.map +1 -1
- package/dist/commands/channel/supervisor/shutdown.js +6 -1
- package/dist/commands/channel/supervisor/shutdown.js.map +1 -1
- package/dist/commands/channel/supervisor.d.ts +2 -2
- package/dist/commands/channel/supervisor.d.ts.map +1 -1
- package/dist/commands/channel/supervisor.js +26 -3
- package/dist/commands/channel/supervisor.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +6 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mem.d.ts +2 -1
- package/dist/commands/mem.d.ts.map +1 -1
- package/dist/commands/mem.js +162 -13
- package/dist/commands/mem.js.map +1 -1
- package/dist/commands/mode.d.ts.map +1 -1
- package/dist/commands/mode.js +5 -3
- package/dist/commands/mode.js.map +1 -1
- package/dist/commands/uninstall.d.ts +5 -3
- package/dist/commands/uninstall.d.ts.map +1 -1
- package/dist/commands/uninstall.js +40 -16
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.d.ts +34 -0
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +209 -11
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/verify.d.ts +18 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +75 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/configurators/index.d.ts.map +1 -1
- package/dist/configurators/index.js +3 -2
- package/dist/configurators/index.js.map +1 -1
- package/dist/configurators/omp.d.ts +22 -0
- package/dist/configurators/omp.d.ts.map +1 -1
- package/dist/configurators/omp.js +101 -2
- package/dist/configurators/omp.js.map +1 -1
- package/dist/configurators/shared.d.ts.map +1 -1
- package/dist/configurators/shared.js +39 -7
- package/dist/configurators/shared.js.map +1 -1
- package/dist/configurators/workflow.d.ts.map +1 -1
- package/dist/configurators/workflow.js +5 -1
- package/dist/configurators/workflow.js.map +1 -1
- package/dist/constants/paths.d.ts +4 -0
- package/dist/constants/paths.d.ts.map +1 -1
- package/dist/constants/paths.js +4 -0
- package/dist/constants/paths.js.map +1 -1
- package/dist/migrations/manifests/0.6.0.json +442 -0
- package/dist/migrations/manifests/0.7.0.json +1378 -0
- package/dist/templates/atw/definition-of-done.md +65 -0
- package/dist/templates/atw/gitignore.txt +7 -0
- package/dist/templates/atw/index.d.ts +11 -0
- package/dist/templates/atw/index.d.ts.map +1 -1
- package/dist/templates/atw/index.js +22 -0
- package/dist/templates/atw/index.js.map +1 -1
- package/dist/templates/atw/scripts/common/active_task.py +2 -2
- package/dist/templates/atw/scripts/common/workflow_phase.py +33 -0
- package/dist/templates/atw/scripts/cross_model_review.py +3312 -0
- package/dist/templates/atw/scripts/decision_log.py +2002 -0
- package/dist/templates/atw/scripts/floor_guard.py +642 -0
- package/dist/templates/atw/scripts/task.py +25 -6
- package/dist/templates/atw/scripts/tickets.py +480 -10
- package/dist/templates/atw/workflow-general.md +6 -1
- package/dist/templates/atw/workflow.md +346 -26
- package/dist/templates/claude/settings.json +12 -0
- package/dist/templates/codex/hooks/session-start.py +2 -2
- package/dist/templates/common/bundled-skills/atw-askme/SKILL.md +1 -1
- package/dist/templates/common/bundled-skills/atw-askme-with-docs/SKILL.md +1 -1
- package/dist/templates/common/bundled-skills/atw-channel/SKILL.md +5 -2
- package/dist/templates/common/bundled-skills/atw-channel/references/command-reference.md +44 -5
- package/dist/templates/common/bundled-skills/atw-channel/references/progress-debugging.md +9 -0
- package/dist/templates/common/bundled-skills/atw-channel/references/workers.md +48 -4
- package/dist/templates/common/bundled-skills/atw-code-review/SKILL.md +78 -3
- package/dist/templates/common/bundled-skills/atw-codebase-design/SKILL.md +2 -2
- package/dist/templates/common/bundled-skills/atw-codebase-design/{DESIGN-IT-TWICE.md → design-it-twice.md} +3 -3
- package/dist/templates/common/bundled-skills/atw-cross-model-review/SKILL.md +361 -0
- package/dist/templates/common/bundled-skills/atw-cross-model-review/agents/openai.yaml +5 -0
- package/dist/templates/common/bundled-skills/atw-cross-model-review/references/four-tiers.md +42 -0
- package/dist/templates/common/bundled-skills/atw-cross-model-review/references/log-review-questions.md +38 -0
- package/dist/templates/common/bundled-skills/atw-cross-model-review/references/questions.md +54 -0
- package/dist/templates/common/bundled-skills/atw-cross-model-review/references/recheck-questions.md +42 -0
- package/dist/templates/common/bundled-skills/atw-cross-model-review/references/report-format.md +22 -0
- package/dist/templates/common/bundled-skills/atw-diagnosing-bugs/SKILL.md +13 -2
- package/dist/templates/common/bundled-skills/atw-domain-modeling/SKILL.md +2 -2
- package/dist/templates/common/bundled-skills/atw-handoff/SKILL.md +1 -1
- package/dist/templates/common/bundled-skills/atw-implement/SKILL.md +37 -1
- package/dist/templates/common/bundled-skills/atw-implement-all/SKILL.md +219 -24
- package/dist/templates/common/bundled-skills/atw-implement-spec/SKILL.md +237 -18
- package/dist/templates/common/bundled-skills/atw-improve-codebase-architecture/SKILL.md +2 -2
- package/dist/templates/common/bundled-skills/atw-init-repo/SKILL.md +1 -1
- package/dist/templates/common/bundled-skills/atw-init-repo/references/issue-tracker-atw-local.md +7 -1
- package/dist/templates/common/bundled-skills/atw-init-repo/references/issue-tracker-atw.md +7 -1
- package/dist/templates/common/bundled-skills/atw-map/SKILL.md +1 -1
- package/dist/templates/common/bundled-skills/atw-meta/SKILL.md +1 -1
- package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/add-project-local-conventions.md +4 -3
- package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/change-skills-or-commands.md +21 -16
- package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/change-task-lifecycle.md +1 -1
- package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/overview.md +1 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/local-architecture/task-system.md +2 -1
- package/dist/templates/common/bundled-skills/atw-meta/references/platform-files/hooks-and-settings.md +1 -0
- package/dist/templates/common/bundled-skills/atw-noob-mode/SKILL.md +1 -1
- package/dist/templates/common/bundled-skills/atw-performance/SKILL.md +134 -0
- package/dist/templates/common/bundled-skills/atw-performance/agents/openai.yaml +3 -0
- package/dist/templates/common/bundled-skills/atw-performance/references/optimization-patterns.md +250 -0
- package/dist/templates/common/bundled-skills/atw-performance/references/performance-checklist.md +238 -0
- package/dist/templates/common/bundled-skills/atw-performance/references/performance-optimization.md +264 -0
- package/dist/templates/common/bundled-skills/atw-prototype/SKILL.md +3 -3
- package/dist/templates/common/bundled-skills/atw-prototype/{LOGIC.md → logic.md} +1 -1
- package/dist/templates/common/bundled-skills/atw-prototype/references/design-direction.md +91 -58
- package/dist/templates/common/bundled-skills/atw-prototype/references/direction-persuasion.md +25 -0
- package/dist/templates/common/bundled-skills/atw-prototype/references/style-explorer.md +1 -1
- package/dist/templates/common/bundled-skills/atw-prototype/ui.md +194 -0
- package/dist/templates/common/bundled-skills/atw-reflect/SKILL.md +77 -0
- package/dist/templates/common/bundled-skills/atw-reflect/agents/openai.yaml +5 -0
- package/dist/templates/common/bundled-skills/atw-reflect/references/divergent-reviewer.md +38 -0
- package/dist/templates/common/bundled-skills/atw-reflect/references/judgment-reviewer.md +37 -0
- package/dist/templates/common/bundled-skills/atw-reflect/references/synthesizer.md +63 -0
- package/dist/templates/common/bundled-skills/atw-reflect/references/tooling-reviewer.md +48 -0
- package/dist/templates/common/bundled-skills/atw-security/SKILL.md +248 -0
- package/dist/templates/common/bundled-skills/atw-security/agents/openai.yaml +3 -0
- package/dist/templates/common/bundled-skills/atw-security/references/hardening-patterns.md +324 -0
- package/dist/templates/common/bundled-skills/atw-security/references/security-checklist.md +248 -0
- package/dist/templates/common/bundled-skills/atw-session-insight/SKILL.md +1 -1
- package/dist/templates/common/bundled-skills/atw-session-insight/references/cli-quick-reference.md +11 -2
- package/dist/templates/common/bundled-skills/atw-spec/SKILL.md +1 -1
- package/dist/templates/common/bundled-skills/atw-tdd/SKILL.md +25 -0
- package/dist/templates/common/bundled-skills/atw-tickets/SKILL.md +1 -1
- package/dist/templates/common/bundled-skills/atw-triage/SKILL.md +5 -5
- package/dist/templates/common/bundled-skills/atw-ui/SKILL.md +99 -31
- package/dist/templates/common/bundled-skills/atw-ui/references/accessibility-checklist.md +160 -0
- package/dist/templates/common/bundled-skills/atw-ui/references/layout-and-viewport.md +7 -5
- package/dist/templates/common/bundled-skills/atw-ui/references/media.md +117 -20
- package/dist/templates/common/bundled-skills/atw-ui/references/motion.md +47 -23
- package/dist/templates/common/bundled-skills/atw-ui/references/play.md +18 -0
- package/dist/templates/common/bundled-skills/atw-ui/references/reviewer-manual.md +73 -0
- package/dist/templates/common/bundled-skills/atw-ui/references/scroll-narrative.md +98 -0
- package/dist/templates/common/bundled-skills/atw-ui/references/tools.md +46 -0
- package/dist/templates/common/bundled-skills/atw-ui/references/visual-language.md +40 -24
- package/dist/templates/common/bundled-skills/atw-ui/references/visual-review.md +26 -82
- package/dist/templates/common/bundled-skills/atw-ui/scripts/shoot.mjs +1721 -0
- package/dist/templates/common/bundled-skills/atw-verify-skill/SKILL.md +58 -0
- package/dist/templates/common/bundled-skills/atw-verify-skill/agents/openai.yaml +5 -0
- package/dist/templates/common/bundled-skills/atw-verify-skill/references/feature-map-example/README.md +47 -0
- package/dist/templates/common/bundled-skills/atw-verify-skill/references/feature-map-example/create-note.md +39 -0
- package/dist/templates/common/bundled-skills/atw-verify-skill/references/feature-map-example/search.md +45 -0
- package/dist/templates/common/bundled-skills/atw-verify-skill/references/generate.md +107 -0
- package/dist/templates/common/bundled-skills/atw-verify-skill/references/health-check.md +100 -0
- package/dist/templates/common/bundled-skills/atw-verify-skill/references/verify-skill-template.md +99 -0
- package/dist/templates/common/bundled-skills/atw-what-happened/SKILL.md +49 -0
- package/dist/templates/common/bundled-skills/atw-what-happened/agents/openai.yaml +5 -0
- package/dist/templates/common/commands/finish-work.md +10 -1
- package/dist/templates/common/commands/start.md +3 -1
- package/dist/templates/common/skills/update-spec.md +40 -4
- package/dist/templates/copilot/hooks/session-start.py +2 -2
- package/dist/templates/dsh/DSH.md +2 -2
- package/dist/templates/markdown/spec/backend/quality-guidelines.md.txt +10 -0
- package/dist/templates/markdown/spec/frontend/quality-guidelines.md.txt +10 -0
- package/dist/templates/omp/config.yml +15 -0
- package/dist/templates/omp/extensions/atw/index.ts.txt +135 -18
- package/dist/templates/omp/index.d.ts +1 -0
- package/dist/templates/omp/index.d.ts.map +1 -1
- package/dist/templates/omp/index.js +3 -0
- package/dist/templates/omp/index.js.map +1 -1
- package/dist/templates/opencode/lib/session-utils.js +4 -2
- package/dist/templates/opencode/plugins/inject-workflow-state.js +5 -1
- package/dist/templates/pi/extensions/atw/index.ts.txt +80 -7
- package/dist/templates/shared-hooks/index.d.ts +8 -1
- package/dist/templates/shared-hooks/index.d.ts.map +1 -1
- package/dist/templates/shared-hooks/index.js +8 -0
- package/dist/templates/shared-hooks/index.js.map +1 -1
- package/dist/templates/shared-hooks/inject-workflow-state.py +131 -14
- package/dist/templates/shared-hooks/session-start.py +4 -2
- package/dist/templates/shared-hooks/show-notice.py +135 -0
- package/dist/templates/snow/SNOW.md +1 -1
- package/dist/utils/initialized.d.ts +9 -0
- package/dist/utils/initialized.d.ts.map +1 -0
- package/dist/utils/initialized.js +24 -0
- package/dist/utils/initialized.js.map +1 -0
- package/dist/utils/managed-removal.d.ts +2 -0
- package/dist/utils/managed-removal.d.ts.map +1 -1
- package/dist/utils/managed-removal.js +23 -3
- package/dist/utils/managed-removal.js.map +1 -1
- package/dist/utils/optional-skills.d.ts +2 -0
- package/dist/utils/optional-skills.d.ts.map +1 -1
- package/dist/utils/optional-skills.js +1 -1
- package/dist/utils/optional-skills.js.map +1 -1
- package/dist/utils/template-hash.d.ts.map +1 -1
- package/dist/utils/template-hash.js +3 -0
- package/dist/utils/template-hash.js.map +1 -1
- package/dist/utils/uninstall-scrubbers.d.ts +10 -0
- package/dist/utils/uninstall-scrubbers.d.ts.map +1 -1
- package/dist/utils/uninstall-scrubbers.js +50 -0
- package/dist/utils/uninstall-scrubbers.js.map +1 -1
- package/dist/utils/verify-entries.d.ts +51 -0
- package/dist/utils/verify-entries.d.ts.map +1 -0
- package/dist/utils/verify-entries.js +399 -0
- package/dist/utils/verify-entries.js.map +1 -0
- package/package.json +2 -2
- package/dist/templates/common/bundled-skills/atw-prototype/UI.md +0 -174
- package/dist/templates/common/bundled-skills/atw-prototype/references/visual-language.md +0 -88
- package/dist/templates/common/bundled-skills/atw-prototype/references/visual-review.md +0 -63
- package/dist/templates/common/bundled-skills/atw-ui/references/imagery.md +0 -69
- /package/dist/templates/common/bundled-skills/atw-codebase-design/{DEEPENING.md → deepening.md} +0 -0
- /package/dist/templates/common/bundled-skills/atw-domain-modeling/{ADR-FORMAT.md → adr-format.md} +0 -0
- /package/dist/templates/common/bundled-skills/atw-domain-modeling/{GLOSSARY-FORMAT.md → glossary-format.md} +0 -0
- /package/dist/templates/common/bundled-skills/atw-improve-codebase-architecture/{HTML-REPORT.md → html-report.md} +0 -0
- /package/dist/templates/common/bundled-skills/atw-triage/{AGENT-BRIEF.md → agent-brief.md} +0 -0
- /package/dist/templates/common/bundled-skills/atw-triage/{OUT-OF-SCOPE.md → out-of-scope.md} +0 -0
package/dist/commands/update.js
CHANGED
|
@@ -20,20 +20,23 @@ const BATCH_FLAG_HINT = "Pass --force to overwrite, --skip-all to keep your vers
|
|
|
20
20
|
// Import templates for comparison
|
|
21
21
|
import { getAllScripts, getAllAgents,
|
|
22
22
|
// Configuration
|
|
23
|
-
configYamlTemplate, gitignoreTemplate, bundledWorkflowFor, } from "../templates/atw/index.js";
|
|
23
|
+
configYamlTemplate, gitignoreTemplate, bundledWorkflowFor, getModeAtwFiles, } from "../templates/atw/index.js";
|
|
24
24
|
import { agentsMdFor } from "../templates/markdown/index.js";
|
|
25
25
|
import { COPILOT_INSTRUCTIONS_BLOCK_END, COPILOT_INSTRUCTIONS_BLOCK_START, COPILOT_INSTRUCTIONS_PATH, getCopilotInstructions, } from "../templates/copilot/index.js";
|
|
26
26
|
import { ALL_MANAGED_DIRS, getConfiguredPlatforms, collectPlatformTemplates, } from "../configurators/index.js";
|
|
27
27
|
import { replacePythonCommandLiterals } from "../configurators/shared.js";
|
|
28
28
|
import { preserveCodexAgentModelKeys } from "../configurators/codex.js";
|
|
29
|
+
import { preserveOmpProjectConfig } from "../configurators/omp.js";
|
|
29
30
|
import { ensureGitattributes } from "../configurators/workflow.js";
|
|
30
31
|
import { pruneOrphanManifestKeys } from "../utils/manifest-prune.js";
|
|
31
32
|
import { loadProjectMode } from "../utils/project-mode.js";
|
|
32
33
|
import { fetchRegistrySpecTemplates, collectDirectoryFiles, removeDirectory, parseRegistrySource, probeRegistryIndex, downloadTemplateById, } from "../utils/template-fetcher.js";
|
|
33
34
|
import { loadSpecRegistryConfig } from "../utils/registry-config.js";
|
|
34
35
|
import { fetchOptionalSkills, getInstalledOptionalSkillDirs, installOptionalSkills, loadOptionalSkillRecord, } from "../utils/optional-skills.js";
|
|
36
|
+
import { syncVerifyEntriesAfterInstall } from "./verify.js";
|
|
35
37
|
import { cleanupEmptyDirs, ATW_BLOCK_END, ATW_BLOCK_START, } from "../utils/managed-paths.js";
|
|
36
38
|
export { cleanupEmptyDirs, ATW_BLOCK_END, ATW_BLOCK_START, } from "../utils/managed-paths.js";
|
|
39
|
+
import { isAtwInitialized } from "../utils/initialized.js";
|
|
37
40
|
const CLAUDE_SETTINGS_PATH = ".claude/settings.json";
|
|
38
41
|
const LEGACY_UNTRACKED_AGENTS_MD_BLOCK_HASHES = new Set([
|
|
39
42
|
// Older installs wrote AGENTS.md without hash-tracking it.
|
|
@@ -42,12 +45,26 @@ const LEGACY_UNTRACKED_AGENTS_MD_BLOCK_HASHES = new Set([
|
|
|
42
45
|
// false "modified by you" conflict.
|
|
43
46
|
"c1f511b1cfc1902f2147da159f09cc51f380b0c9e341cdb3ac5dea5233f3e307",
|
|
44
47
|
]);
|
|
48
|
+
// `.atw/.gitignore` is never hash-tracked (EXCLUDE_FROM_HASH), so a copy that
|
|
49
|
+
// is byte-identical to an earlier template is recognised by these hashes and
|
|
50
|
+
// upgraded like an unedited file instead of being reported as "modified by you".
|
|
51
|
+
const LEGACY_ATW_GITIGNORE_HASHES = new Set([
|
|
52
|
+
// The only content released before the verify skill evidence line: every
|
|
53
|
+
// tag v0.1.0–v0.6.0 ships this same templates/atw/gitignore.txt, written
|
|
54
|
+
// verbatim by init (checked with `git show <tag>:…/gitignore.txt`).
|
|
55
|
+
"3bc42434cbe61c937a1c26ea3c880b496bfad4e7d683750169e27ade509aa798",
|
|
56
|
+
// Second version, with verify/*/evidence/ (commit 6a7d491, unreleased but
|
|
57
|
+
// installed in this repo), before the task folders' verify-evidence/ lines.
|
|
58
|
+
"cf51d374198c4a2bac0cba41e59fdacb95cff70be781636de92f3dbd68945c2e",
|
|
59
|
+
]);
|
|
45
60
|
// Paths that should never be touched (true user data)
|
|
46
61
|
// spec/ is user-customized content created during init; update should never modify it
|
|
47
62
|
const PROTECTED_PATHS = [
|
|
48
63
|
`${DIR_NAMES.WORKFLOW}/${DIR_NAMES.WORKSPACE}`, // workspace/
|
|
49
64
|
`${DIR_NAMES.WORKFLOW}/${DIR_NAMES.TASKS}`, // tasks/
|
|
50
65
|
`${DIR_NAMES.WORKFLOW}/${DIR_NAMES.SPEC}`, // spec/
|
|
66
|
+
`${DIR_NAMES.WORKFLOW}/${DIR_NAMES.VERIFY}`, // verify/
|
|
67
|
+
`${DIR_NAMES.WORKFLOW}/${DIR_NAMES.SKILL_NOTES}`, // skill-notes/
|
|
51
68
|
`${DIR_NAMES.WORKFLOW}/.developer`,
|
|
52
69
|
`${DIR_NAMES.WORKFLOW}/.current-task`,
|
|
53
70
|
];
|
|
@@ -113,6 +130,9 @@ function buildCopilotInstructionsTemplate(cwd) {
|
|
|
113
130
|
return buildManagedBlockTemplate(cwd, COPILOT_INSTRUCTIONS_PATH, getCopilotInstructions(), COPILOT_INSTRUCTIONS_BLOCK_START, COPILOT_INSTRUCTIONS_BLOCK_END);
|
|
114
131
|
}
|
|
115
132
|
function isKnownUntrackedTemplate(relativePath, existingContent) {
|
|
133
|
+
if (relativePath === `${DIR_NAMES.WORKFLOW}/.gitignore`) {
|
|
134
|
+
return LEGACY_ATW_GITIGNORE_HASHES.has(computeHash(existingContent));
|
|
135
|
+
}
|
|
116
136
|
if (relativePath !== FILE_NAMES.AGENTS) {
|
|
117
137
|
return false;
|
|
118
138
|
}
|
|
@@ -137,6 +157,110 @@ function isSafeUntrackedCopilotInstructionsMerge(relativePath, existingContent,
|
|
|
137
157
|
function isProtectedPath(filePath) {
|
|
138
158
|
return PROTECTED_PATHS.some((pp) => filePath === pp || filePath.startsWith(pp.endsWith("/") ? pp : pp + "/"));
|
|
139
159
|
}
|
|
160
|
+
/** Temporary name of a case-only rename between its two steps. */
|
|
161
|
+
const CASE_RENAME_SUFFIX = ".atw-case-rename";
|
|
162
|
+
/** The current template path that differs from `relativePath` only in case. */
|
|
163
|
+
function caseOnlyVariant(relativePath, currentTemplatePaths) {
|
|
164
|
+
const lower = relativePath.toLowerCase();
|
|
165
|
+
for (const candidate of currentTemplatePaths) {
|
|
166
|
+
if (candidate !== relativePath && candidate.toLowerCase() === lower) {
|
|
167
|
+
return candidate;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Receipt rule for a case-only rename, used both in memory and on disk: the
|
|
174
|
+
* old name's record moves to the new name unless the new name already has
|
|
175
|
+
* one. Both describe the same file; the new name's is the later write.
|
|
176
|
+
*/
|
|
177
|
+
function moveCaseRenameRecord(hashes, from, to) {
|
|
178
|
+
const result = { ...hashes };
|
|
179
|
+
const recorded = result[from];
|
|
180
|
+
if (recorded !== undefined && result[to] === undefined) {
|
|
181
|
+
result[to] = recorded;
|
|
182
|
+
}
|
|
183
|
+
Reflect.deleteProperty(result, from);
|
|
184
|
+
return result;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Finish case-only renames a previous run left between its two steps: the
|
|
188
|
+
* file sits under `<old>.atw-case-rename` and neither name exists. Runs before
|
|
189
|
+
* the change analysis so the file is judged under its new name; a dry run only
|
|
190
|
+
* reports. A temp file next to an existing file is left alone and reported.
|
|
191
|
+
*/
|
|
192
|
+
function finishInterruptedCaseRenames(migrations, cwd, currentTemplatePaths, hashes, dryRun) {
|
|
193
|
+
let result = hashes;
|
|
194
|
+
for (const item of migrations) {
|
|
195
|
+
if (item.type !== "safe-file-delete")
|
|
196
|
+
continue;
|
|
197
|
+
const to = caseOnlyVariant(item.from, currentTemplatePaths);
|
|
198
|
+
if (!to)
|
|
199
|
+
continue;
|
|
200
|
+
const temp = path.join(cwd, item.from + CASE_RENAME_SUFFIX);
|
|
201
|
+
if (!fs.existsSync(temp))
|
|
202
|
+
continue;
|
|
203
|
+
const target = path.join(cwd, to);
|
|
204
|
+
if (fs.existsSync(path.join(cwd, item.from)) || fs.existsSync(target)) {
|
|
205
|
+
console.log(chalk.yellow(` ! ${item.from}${CASE_RENAME_SUFFIX} is left from an interrupted rename, but ${to} exists; compare the two and delete the one you do not need`));
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
console.log(chalk.cyan(` ↻ ${item.from}${CASE_RENAME_SUFFIX} → ${to} (finishing an interrupted case-only rename)`));
|
|
209
|
+
result = moveCaseRenameRecord(result, item.from, to);
|
|
210
|
+
if (!dryRun) {
|
|
211
|
+
fs.renameSync(temp, target);
|
|
212
|
+
saveHashes(cwd, moveCaseRenameRecord(loadHashes(cwd), item.from, to));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return result;
|
|
216
|
+
}
|
|
217
|
+
/** Whether a file with exactly this name (case included) is in its directory. */
|
|
218
|
+
function existsWithExactName(fullPath) {
|
|
219
|
+
try {
|
|
220
|
+
return fs
|
|
221
|
+
.readdirSync(path.dirname(fullPath))
|
|
222
|
+
.includes(path.basename(fullPath));
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* The current template path that differs from `relativePath` only in case and
|
|
230
|
+
* is the same file on disk — which happens only on a case-insensitive
|
|
231
|
+
* filesystem (macOS and Windows by default), where `UI.md` and `ui.md` name
|
|
232
|
+
* one file.
|
|
233
|
+
*/
|
|
234
|
+
function findCaseOnlyTwin(cwd, relativePath, currentTemplatePaths) {
|
|
235
|
+
const candidate = caseOnlyVariant(relativePath, currentTemplatePaths);
|
|
236
|
+
if (!candidate)
|
|
237
|
+
return undefined;
|
|
238
|
+
try {
|
|
239
|
+
const a = fs.statSync(path.join(cwd, relativePath));
|
|
240
|
+
const b = fs.statSync(path.join(cwd, candidate));
|
|
241
|
+
return a.ino === b.ino && a.dev === b.dev ? candidate : undefined;
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
// 只有「新名字不存在」说明是两个文件;别的读不了的错误不能当成不是同一个文件
|
|
245
|
+
if (error.code === "ENOENT")
|
|
246
|
+
return undefined;
|
|
247
|
+
throw error;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Move the receipt entry of each case-only rename to the new name in memory,
|
|
252
|
+
* so `analyzeChanges` judges the file under its new name by the hash recorded
|
|
253
|
+
* for it: pristine → auto-update, edited → the usual conflict prompt.
|
|
254
|
+
*/
|
|
255
|
+
function applyCaseRenamesToHashes(classified, hashes) {
|
|
256
|
+
let result = hashes;
|
|
257
|
+
for (const c of classified) {
|
|
258
|
+
if (c.action !== "case-rename" || !c.caseRenameTo)
|
|
259
|
+
continue;
|
|
260
|
+
result = moveCaseRenameRecord(result, c.item.from, c.caseRenameTo);
|
|
261
|
+
}
|
|
262
|
+
return result;
|
|
263
|
+
}
|
|
140
264
|
/**
|
|
141
265
|
* Collect and classify safe-file-delete migrations
|
|
142
266
|
*
|
|
@@ -169,8 +293,9 @@ bypassUpdateSkip = false) {
|
|
|
169
293
|
const results = [];
|
|
170
294
|
for (const item of safeDeletes) {
|
|
171
295
|
const fullPath = path.join(cwd, item.from);
|
|
172
|
-
// Check: file exists?
|
|
173
|
-
|
|
296
|
+
// Check: file exists? On a case-insensitive disk `UI.md` also "exists"
|
|
297
|
+
// once the file is `ui.md`, so the exact name has to be in the listing.
|
|
298
|
+
if (!fs.existsSync(fullPath) || !existsWithExactName(fullPath)) {
|
|
174
299
|
results.push({ item, action: "skip-missing" });
|
|
175
300
|
continue;
|
|
176
301
|
}
|
|
@@ -188,7 +313,21 @@ bypassUpdateSkip = false) {
|
|
|
188
313
|
if (!bypassUpdateSkip &&
|
|
189
314
|
skipPaths.some((skip) => item.from === skip ||
|
|
190
315
|
item.from.startsWith(skip.endsWith("/") ? skip : skip + "/"))) {
|
|
191
|
-
results.push({
|
|
316
|
+
results.push({
|
|
317
|
+
item,
|
|
318
|
+
action: "skip-update-skip",
|
|
319
|
+
renamedUpstreamTo: caseOnlyVariant(item.from, currentTemplatePaths),
|
|
320
|
+
});
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
// Check: is this the same file as a current template that differs only in
|
|
324
|
+
// case? Deleting it would delete the template too — its write was already
|
|
325
|
+
// judged "unchanged" or "changed" against this very file. Rename it to the
|
|
326
|
+
// template's case instead, whatever its content: no content changes here,
|
|
327
|
+
// the template write that follows applies the usual edited-file rules.
|
|
328
|
+
const caseRenameTo = findCaseOnlyTwin(cwd, item.from, currentTemplatePaths);
|
|
329
|
+
if (caseRenameTo) {
|
|
330
|
+
results.push({ item, action: "case-rename", caseRenameTo });
|
|
192
331
|
continue;
|
|
193
332
|
}
|
|
194
333
|
// Check: hash matches allowed_hashes?
|
|
@@ -204,7 +343,11 @@ bypassUpdateSkip = false) {
|
|
|
204
343
|
results.push({ item, action: "delete" });
|
|
205
344
|
}
|
|
206
345
|
else {
|
|
207
|
-
results.push({
|
|
346
|
+
results.push({
|
|
347
|
+
item,
|
|
348
|
+
action: "skip-modified",
|
|
349
|
+
renamedUpstreamTo: caseOnlyVariant(item.from, currentTemplatePaths),
|
|
350
|
+
});
|
|
208
351
|
}
|
|
209
352
|
}
|
|
210
353
|
catch {
|
|
@@ -218,14 +361,19 @@ bypassUpdateSkip = false) {
|
|
|
218
361
|
*/
|
|
219
362
|
function printSafeFileDeleteSummary(classified) {
|
|
220
363
|
const toDelete = classified.filter((c) => c.action === "delete");
|
|
364
|
+
const caseRenames = classified.filter((c) => c.action === "case-rename");
|
|
221
365
|
const modified = classified.filter((c) => c.action === "skip-modified");
|
|
222
366
|
const updateSkip = classified.filter((c) => c.action === "skip-update-skip");
|
|
223
367
|
if (toDelete.length === 0 &&
|
|
368
|
+
caseRenames.length === 0 &&
|
|
224
369
|
modified.length === 0 &&
|
|
225
370
|
updateSkip.length === 0) {
|
|
226
371
|
return;
|
|
227
372
|
}
|
|
228
373
|
console.log(chalk.cyan(" Deprecated commands cleanup:"));
|
|
374
|
+
for (const c of caseRenames) {
|
|
375
|
+
console.log(chalk.green(` ↻ ${c.item.from} → ${c.caseRenameTo ?? ""} (case-only rename)`));
|
|
376
|
+
}
|
|
229
377
|
if (toDelete.length > 0) {
|
|
230
378
|
for (const c of toDelete) {
|
|
231
379
|
console.log(chalk.green(` ✕ ${c.item.from}${c.item.description ? ` (${c.item.description})` : ""}`));
|
|
@@ -233,12 +381,16 @@ function printSafeFileDeleteSummary(classified) {
|
|
|
233
381
|
}
|
|
234
382
|
if (modified.length > 0) {
|
|
235
383
|
for (const c of modified) {
|
|
236
|
-
console.log(chalk.yellow(
|
|
384
|
+
console.log(chalk.yellow(c.renamedUpstreamTo
|
|
385
|
+
? ` ? ${c.item.from} (modified, kept): ${c.item.from} was renamed upstream to ${c.renamedUpstreamTo}; your edits in ${c.item.from} no longer take effect — move them into ${c.renamedUpstreamTo} if you still want them`
|
|
386
|
+
: ` ? ${c.item.from} (modified, skipped)`));
|
|
237
387
|
}
|
|
238
388
|
}
|
|
239
389
|
if (updateSkip.length > 0) {
|
|
240
390
|
for (const c of updateSkip) {
|
|
241
|
-
console.log(chalk.gray(
|
|
391
|
+
console.log(chalk.gray(c.renamedUpstreamTo
|
|
392
|
+
? ` ○ ${c.item.from} (skipped, update.skip): renamed upstream to ${c.renamedUpstreamTo}, which is skipped too`
|
|
393
|
+
: ` ○ ${c.item.from} (skipped, update.skip)`));
|
|
242
394
|
}
|
|
243
395
|
}
|
|
244
396
|
console.log("");
|
|
@@ -249,6 +401,30 @@ function printSafeFileDeleteSummary(classified) {
|
|
|
249
401
|
function executeSafeFileDeletes(classified, cwd) {
|
|
250
402
|
const toDelete = classified.filter((c) => c.action === "delete");
|
|
251
403
|
let deleted = 0;
|
|
404
|
+
for (const c of classified) {
|
|
405
|
+
if (c.action !== "case-rename" || !c.caseRenameTo)
|
|
406
|
+
continue;
|
|
407
|
+
const from = path.join(cwd, c.item.from);
|
|
408
|
+
// Through a temporary name: a direct case-only rename is not honoured by
|
|
409
|
+
// every case-insensitive filesystem. An interruption between the two
|
|
410
|
+
// steps is finished by the next update (finishInterruptedCaseRenames).
|
|
411
|
+
const temp = from + CASE_RENAME_SUFFIX;
|
|
412
|
+
try {
|
|
413
|
+
fs.renameSync(from, temp);
|
|
414
|
+
}
|
|
415
|
+
catch {
|
|
416
|
+
// File may have been removed between classify and execute
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
try {
|
|
420
|
+
fs.renameSync(temp, path.join(cwd, c.caseRenameTo));
|
|
421
|
+
}
|
|
422
|
+
catch (error) {
|
|
423
|
+
fs.renameSync(temp, from);
|
|
424
|
+
throw error;
|
|
425
|
+
}
|
|
426
|
+
saveHashes(cwd, moveCaseRenameRecord(loadHashes(cwd), c.item.from, c.caseRenameTo));
|
|
427
|
+
}
|
|
252
428
|
for (const c of toDelete) {
|
|
253
429
|
const fullPath = path.join(cwd, c.item.from);
|
|
254
430
|
try {
|
|
@@ -651,7 +827,7 @@ async function collectRegistrySpecTemplates(cwd) {
|
|
|
651
827
|
}
|
|
652
828
|
return result.files;
|
|
653
829
|
}
|
|
654
|
-
async function collectTemplateFiles(cwd, mode, extraPlatforms,
|
|
830
|
+
export async function collectTemplateFiles(cwd, mode, extraPlatforms,
|
|
655
831
|
/**
|
|
656
832
|
* Bypass `update.skip` when collecting templates. Enable this for breaking
|
|
657
833
|
* releases so newly added files (e.g. a new `continue.md`) and template
|
|
@@ -692,6 +868,11 @@ bypassUpdateSkip = false) {
|
|
|
692
868
|
// platform routing markers outside [workflow-state:*] blocks are also
|
|
693
869
|
// script-consumed.
|
|
694
870
|
files.set(`${DIR_NAMES.WORKFLOW}/workflow.md`, bundledWorkflowFor(mode));
|
|
871
|
+
// Mode-only .atw/ files (dev: the default definition of done). The project's
|
|
872
|
+
// own .atw/spec/definition-of-done.md is user content and never collected.
|
|
873
|
+
for (const [file, content] of getModeAtwFiles(mode)) {
|
|
874
|
+
files.set(file, content);
|
|
875
|
+
}
|
|
695
876
|
// workspace/index.md stays excluded — it's runtime-appended by add_session.py
|
|
696
877
|
// (journal index) and has no script-parsed structure.
|
|
697
878
|
files.set(FILE_NAMES.AGENTS, buildAgentsMdTemplate(cwd, mode));
|
|
@@ -715,6 +896,11 @@ bypassUpdateSkip = false) {
|
|
|
715
896
|
if (platforms.has("codex")) {
|
|
716
897
|
preserveCodexAgentModelKeys(cwd, files);
|
|
717
898
|
}
|
|
899
|
+
// `.omp/config.yml` may be the project's own omp config: compare against
|
|
900
|
+
// ATW's settings merged into it, not against the bare template.
|
|
901
|
+
if (platforms.has("omp")) {
|
|
902
|
+
preserveOmpProjectConfig(cwd, files);
|
|
903
|
+
}
|
|
718
904
|
preserveExistingClaudeStatusLine(cwd, files);
|
|
719
905
|
for (const [filePath, content] of await collectRegistrySpecTemplates(cwd)) {
|
|
720
906
|
files.set(filePath, content);
|
|
@@ -745,7 +931,7 @@ bypassUpdateSkip = false) {
|
|
|
745
931
|
* - User didn't modify + template updated = auto-update (autoUpdateFiles)
|
|
746
932
|
* - User modified = needs confirmation (changedFiles)
|
|
747
933
|
*/
|
|
748
|
-
function analyzeChanges(cwd, hashes, templates) {
|
|
934
|
+
export function analyzeChanges(cwd, hashes, templates) {
|
|
749
935
|
const result = {
|
|
750
936
|
newFiles: [],
|
|
751
937
|
unchangedFiles: [],
|
|
@@ -1772,7 +1958,7 @@ async function updateOptionalSkills(cwd, dryRun) {
|
|
|
1772
1958
|
export async function update(options) {
|
|
1773
1959
|
const cwd = process.cwd();
|
|
1774
1960
|
// Check if ATW is initialized
|
|
1775
|
-
if (!
|
|
1961
|
+
if (!isAtwInitialized(cwd)) {
|
|
1776
1962
|
console.log(chalk.red("Error: ATW not initialized in this directory."));
|
|
1777
1963
|
console.log(chalk.gray("Run 'atw init' first."));
|
|
1778
1964
|
return;
|
|
@@ -1876,8 +2062,17 @@ export async function update(options) {
|
|
|
1876
2062
|
// Collect safe-file-delete items from ALL manifests (hash match is the safety net)
|
|
1877
2063
|
// This runs regardless of version — unknown version still gets safe cleanup
|
|
1878
2064
|
const allMigrations = getAllMigrations();
|
|
2065
|
+
hashes = finishInterruptedCaseRenames(allMigrations, cwd, new Set(templates.keys()), hashes, options.dryRun === true);
|
|
1879
2066
|
const safeFileDeletes = collectSafeFileDeletes(allMigrations, cwd, skipPaths, new Set(templates.keys()), getInstalledOptionalSkillDirs(cwd), breakingBypass);
|
|
1880
|
-
const hasSafeDeletes = safeFileDeletes.
|
|
2067
|
+
const hasSafeDeletes = safeFileDeletes.some((c) => c.action === "delete" || c.action === "case-rename");
|
|
2068
|
+
hashes = applyCaseRenamesToHashes(safeFileDeletes, hashes);
|
|
2069
|
+
// update.skip 里的旧名字:用户要 ATW 别碰这个文件,只改大小写的新名字是同一个文件
|
|
2070
|
+
// (不分大小写的磁盘)或它的接班(分大小写的磁盘),一并跳过
|
|
2071
|
+
for (const c of safeFileDeletes) {
|
|
2072
|
+
if (c.action === "skip-update-skip" && c.renamedUpstreamTo) {
|
|
2073
|
+
templates.delete(c.renamedUpstreamTo);
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
1881
2076
|
// Check for pending regular migrations (skip if unknown version)
|
|
1882
2077
|
let pendingMigrations = isUnknownVersion
|
|
1883
2078
|
? []
|
|
@@ -2011,6 +2206,7 @@ export async function update(options) {
|
|
|
2011
2206
|
}
|
|
2012
2207
|
}
|
|
2013
2208
|
await updateOptionalSkills(cwd, options.dryRun);
|
|
2209
|
+
syncVerifyEntriesAfterInstall(cwd, options.dryRun);
|
|
2014
2210
|
return;
|
|
2015
2211
|
}
|
|
2016
2212
|
// Show what this operation will do
|
|
@@ -2056,6 +2252,7 @@ export async function update(options) {
|
|
|
2056
2252
|
// Dry run mode
|
|
2057
2253
|
if (options.dryRun) {
|
|
2058
2254
|
await updateOptionalSkills(cwd, true);
|
|
2255
|
+
syncVerifyEntriesAfterInstall(cwd, true);
|
|
2059
2256
|
console.log(chalk.gray("[Dry run] No changes made."));
|
|
2060
2257
|
return;
|
|
2061
2258
|
}
|
|
@@ -2242,6 +2439,7 @@ export async function update(options) {
|
|
|
2242
2439
|
console.log(chalk.gray("\nTip: Review .new files and merge changes manually if needed."));
|
|
2243
2440
|
}
|
|
2244
2441
|
await updateOptionalSkills(cwd);
|
|
2442
|
+
syncVerifyEntriesAfterInstall(cwd);
|
|
2245
2443
|
// Create migration task if there are breaking changes with migration guides
|
|
2246
2444
|
if (cliVsProject > 0 && projectVersion !== "unknown") {
|
|
2247
2445
|
const metadata = getMigrationMetadata(projectVersion, cliVersion);
|