sauron-cli 1.2.0 → 1.3.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/.agents/rules/memory.md +156 -0
- package/.agents/skills/wiki/SKILL.md +172 -0
- package/.aider.instructions.md +152 -0
- package/.cursor/rules/sauron-memory.mdc +157 -0
- package/.genesis/prompts/prompt-onboarding-inteligente.md +45 -0
- package/.genesis/prompts/prompt-sauron-vs-openspec-arquitetura.md +106 -0
- package/.github/workflows/ci.yml +27 -0
- package/.sauron/.manifest.json +2 -1
- package/.sauron/wiki/history/implementacao-scanner-inteligente.md +29 -0
- package/.sauron/wiki/history/reestruturacao-arquitetural-core.md +29 -0
- package/.sauron/wiki/history/resiliencia-caminho-templates.md +29 -0
- package/.sauron/wiki/standards/typescript.rules.md +21 -0
- package/.sauron/wiki/summary.json +81 -0
- package/.windsurfrules +160 -0
- package/55ea973d-e255-4f08-a313-a5d68243bd2d.png +0 -0
- package/Evolu/303/247/303/243o Arquitetural do Sauron CLI.md" +97 -0
- package/OpenSpec-main/.actrc +1 -0
- package/OpenSpec-main/.changeset/README.md +97 -0
- package/OpenSpec-main/.changeset/config.json +15 -0
- package/OpenSpec-main/.coderabbit.yaml +11 -0
- package/OpenSpec-main/.devcontainer/README.md +92 -0
- package/OpenSpec-main/.devcontainer/devcontainer.json +68 -0
- package/OpenSpec-main/.github/CODEOWNERS +2 -0
- package/OpenSpec-main/.github/workflows/README.md +20 -0
- package/OpenSpec-main/.github/workflows/ci.yml +346 -0
- package/OpenSpec-main/.github/workflows/release-prepare.yml +60 -0
- package/OpenSpec-main/CHANGELOG.md +594 -0
- package/OpenSpec-main/LICENSE +22 -0
- package/OpenSpec-main/MAINTAINERS.md +17 -0
- package/OpenSpec-main/README.md +206 -0
- package/OpenSpec-main/README_OLD.md +475 -0
- package/OpenSpec-main/assets/openspec_bg.png +0 -0
- package/OpenSpec-main/assets/openspec_dashboard.png +0 -0
- package/OpenSpec-main/assets/openspec_pixel_dark.svg +89 -0
- package/OpenSpec-main/assets/openspec_pixel_light.svg +89 -0
- package/OpenSpec-main/bin/openspec.js +5 -0
- package/OpenSpec-main/build.js +31 -0
- package/OpenSpec-main/eslint.config.js +42 -0
- package/OpenSpec-main/flake.lock +27 -0
- package/OpenSpec-main/flake.nix +114 -0
- package/OpenSpec-main/openspec/changes/IMPLEMENTATION_ORDER.md +68 -0
- package/OpenSpec-main/openspec/changes/add-artifact-regeneration-support/proposal.md +136 -0
- package/OpenSpec-main/openspec/changes/add-change-stacking-awareness/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/add-change-stacking-awareness/proposal.md +93 -0
- package/OpenSpec-main/openspec/changes/add-change-stacking-awareness/specs/change-creation/spec.md +15 -0
- package/OpenSpec-main/openspec/changes/add-change-stacking-awareness/specs/change-stacking-workflow/spec.md +65 -0
- package/OpenSpec-main/openspec/changes/add-change-stacking-awareness/specs/cli-change/spec.md +27 -0
- package/OpenSpec-main/openspec/changes/add-change-stacking-awareness/specs/openspec-conventions/spec.md +29 -0
- package/OpenSpec-main/openspec/changes/add-change-stacking-awareness/tasks.md +39 -0
- package/OpenSpec-main/openspec/changes/add-global-install-scope/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/add-global-install-scope/design.md +161 -0
- package/OpenSpec-main/openspec/changes/add-global-install-scope/proposal.md +101 -0
- package/OpenSpec-main/openspec/changes/add-global-install-scope/specs/ai-tool-paths/spec.md +35 -0
- package/OpenSpec-main/openspec/changes/add-global-install-scope/specs/cli-config/spec.md +21 -0
- package/OpenSpec-main/openspec/changes/add-global-install-scope/specs/cli-init/spec.md +28 -0
- package/OpenSpec-main/openspec/changes/add-global-install-scope/specs/cli-update/spec.md +34 -0
- package/OpenSpec-main/openspec/changes/add-global-install-scope/specs/command-generation/spec.md +22 -0
- package/OpenSpec-main/openspec/changes/add-global-install-scope/specs/global-config/spec.md +24 -0
- package/OpenSpec-main/openspec/changes/add-global-install-scope/specs/installation-scope/spec.md +71 -0
- package/OpenSpec-main/openspec/changes/add-global-install-scope/tasks.md +61 -0
- package/OpenSpec-main/openspec/changes/add-qa-smoke-harness/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/add-qa-smoke-harness/proposal.md +45 -0
- package/OpenSpec-main/openspec/changes/add-qa-smoke-harness/specs/developer-qa-workflow/spec.md +49 -0
- package/OpenSpec-main/openspec/changes/add-tool-command-surface-capabilities/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/add-tool-command-surface-capabilities/proposal.md +111 -0
- package/OpenSpec-main/openspec/changes/add-tool-command-surface-capabilities/specs/cli-init/spec.md +121 -0
- package/OpenSpec-main/openspec/changes/add-tool-command-surface-capabilities/specs/cli-update/spec.md +48 -0
- package/OpenSpec-main/openspec/changes/add-tool-command-surface-capabilities/tasks.md +53 -0
- package/OpenSpec-main/openspec/changes/archive/2025-01-11-add-update-command/design.md +86 -0
- package/OpenSpec-main/openspec/changes/archive/2025-01-11-add-update-command/proposal.md +29 -0
- package/OpenSpec-main/openspec/changes/archive/2025-01-11-add-update-command/specs/cli-update/spec.md +59 -0
- package/OpenSpec-main/openspec/changes/archive/2025-01-11-add-update-command/tasks.md +20 -0
- package/OpenSpec-main/openspec/changes/archive/2025-01-13-add-list-command/proposal.md +20 -0
- package/OpenSpec-main/openspec/changes/archive/2025-01-13-add-list-command/specs/cli-list/spec.md +69 -0
- package/OpenSpec-main/openspec/changes/archive/2025-01-13-add-list-command/tasks.md +26 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-05-initialize-typescript-project/design.md +64 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-05-initialize-typescript-project/proposal.md +18 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-05-initialize-typescript-project/tasks.md +25 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-06-add-init-command/design.md +104 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-06-add-init-command/proposal.md +30 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-06-add-init-command/specs/cli-init/spec.md +148 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-06-add-init-command/tasks.md +38 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-06-adopt-future-state-storage/proposal.md +24 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-06-adopt-future-state-storage/specs/openspec-conventions/spec.md +120 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-06-adopt-future-state-storage/tasks.md +38 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-11-add-complexity-guidelines/proposal.md +13 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-11-add-complexity-guidelines/specs/openspec-docs/README.md +472 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-11-add-complexity-guidelines/tasks.md +9 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-13-add-archive-command/proposal.md +15 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-13-add-archive-command/specs/cli-archive/spec.md +111 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-13-add-archive-command/tasks.md +44 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-13-add-diff-command/proposal.md +19 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-13-add-diff-command/specs/cli-diff/spec.md +77 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-13-add-diff-command/tasks.md +23 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-change-commands/design.md +56 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-change-commands/proposal.md +17 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-change-commands/specs/cli-change/spec.md +48 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-change-commands/specs/cli-list/spec.md +12 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-change-commands/tasks.md +34 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-interactive-show-command/proposal.md +20 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-interactive-show-command/specs/cli-change/spec.md +23 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-interactive-show-command/specs/cli-show/spec.md +83 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-interactive-show-command/specs/cli-spec/spec.md +23 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-interactive-show-command/tasks.md +142 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-skip-specs-archive-option/proposal.md +13 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-skip-specs-archive-option/specs/cli-archive/spec.md +191 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-skip-specs-archive-option/tasks.md +57 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-spec-commands/design.md +45 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-spec-commands/proposal.md +19 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-spec-commands/specs/cli-spec/spec.md +43 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-spec-commands/tasks.md +22 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-zod-validation/design.md +104 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-zod-validation/proposal.md +22 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-zod-validation/specs/cli-archive/spec.md +18 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-zod-validation/specs/cli-diff/spec.md +12 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-zod-validation/tasks.md +59 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-delta-based-changes/proposal.md +93 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-delta-based-changes/specs/cli-archive/spec.md +48 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-delta-based-changes/specs/cli-diff/spec.md +45 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-delta-based-changes/specs/openspec-conventions/spec.md +101 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-delta-based-changes/tasks.md +55 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-verb-noun-cli-structure/design.md +19 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-verb-noun-cli-structure/proposal.md +67 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-verb-noun-cli-structure/specs/cli-list/spec.md +57 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-verb-noun-cli-structure/specs/openspec-conventions/spec.md +23 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-verb-noun-cli-structure/tasks.md +27 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-bulk-validation-interactive-selection/proposal.md +20 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-bulk-validation-interactive-selection/specs/cli-change/spec.md +22 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-bulk-validation-interactive-selection/specs/cli-spec/spec.md +23 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-bulk-validation-interactive-selection/specs/cli-validate/spec.md +149 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-bulk-validation-interactive-selection/tasks.md +81 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-fix-update-tool-selection/proposal.md +40 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-fix-update-tool-selection/specs/cli-update/spec.md +23 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-fix-update-tool-selection/tasks.md +21 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-improve-validate-error-messages/proposal.md +25 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-improve-validate-error-messages/specs/cli-validate/spec.md +55 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-improve-validate-error-messages/tasks.md +21 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-structured-spec-format/proposal.md +36 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-structured-spec-format/specs/openspec-conventions/spec.md +192 -0
- package/OpenSpec-main/openspec/changes/archive/2025-08-19-structured-spec-format/tasks.md +19 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-12-add-view-dashboard-command/proposal.md +38 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-12-add-view-dashboard-command/specs/cli-view/spec.md +109 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-12-add-view-dashboard-command/tasks.md +47 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-agents-md-config/proposal.md +28 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-agents-md-config/specs/cli-init/spec.md +71 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-agents-md-config/specs/cli-update/spec.md +41 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-agents-md-config/tasks.md +17 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-multi-agent-init/proposal.md +35 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-multi-agent-init/specs/cli-init/spec.md +45 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-multi-agent-init/tasks.md +16 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-slash-command-support/proposal.md +119 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-slash-command-support/specs/cli-init/spec.md +21 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-slash-command-support/specs/cli-update/spec.md +22 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-slash-command-support/tasks.md +20 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-improve-cli-e2e-plan/proposal.md +19 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-improve-cli-e2e-plan/tasks.md +9 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-improve-deterministic-tests/proposal.md +78 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-improve-deterministic-tests/tasks.md +25 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-improve-init-onboarding/proposal.md +13 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-improve-init-onboarding/specs/cli-init/spec.md +92 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-improve-init-onboarding/tasks.md +12 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-remove-diff-command/proposal.md +81 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-remove-diff-command/tasks.md +37 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-sort-active-changes-by-progress/proposal.md +25 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-sort-active-changes-by-progress/specs/cli-view/spec.md +9 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-sort-active-changes-by-progress/tasks.md +8 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-agent-file-name/proposal.md +29 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-agent-file-name/specs/cli-init/spec.md +40 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-agent-file-name/specs/cli-update/spec.md +22 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-agent-file-name/specs/openspec-conventions/spec.md +27 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-agent-file-name/tasks.md +22 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-agent-instructions/design.md +130 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-agent-instructions/proposal.md +117 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-agent-instructions/tasks.md +69 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-markdown-parser-crlf/proposal.md +19 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-markdown-parser-crlf/specs/cli-validate/spec.md +9 -0
- package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-markdown-parser-crlf/tasks.md +11 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-codex-slash-command-support/proposal.md +25 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-codex-slash-command-support/specs/cli-init/spec.md +56 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-codex-slash-command-support/specs/cli-update/spec.md +41 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-codex-slash-command-support/tasks.md +19 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-github-copilot-prompts/proposal.md +25 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-github-copilot-prompts/specs/cli-init/spec.md +48 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-github-copilot-prompts/specs/cli-update/spec.md +48 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-github-copilot-prompts/tasks.md +30 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-kilocode-workflows/proposal.md +17 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-kilocode-workflows/specs/cli-init/spec.md +43 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-kilocode-workflows/specs/cli-update/spec.md +27 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-kilocode-workflows/tasks.md +15 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-non-interactive-init-options/proposal.md +12 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-non-interactive-init-options/specs/cli-init/spec.md +39 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-non-interactive-init-options/tasks.md +17 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-windsurf-workflows/proposal.md +17 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-windsurf-workflows/specs/cli-init/spec.md +42 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-windsurf-workflows/specs/cli-update/spec.md +27 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-windsurf-workflows/tasks.md +17 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-enhance-validation-error-messages/proposal.md +12 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-enhance-validation-error-messages/specs/cli-validate/spec.md +39 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-enhance-validation-error-messages/tasks.md +12 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-improve-agent-instruction-usability/proposal.md +12 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-improve-agent-instruction-usability/specs/docs-agent-instructions/spec.md +33 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-improve-agent-instruction-usability/tasks.md +11 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-slim-root-agents-file/proposal.md +13 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-slim-root-agents-file/tasks.md +15 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-cli-init-enter-selection/proposal.md +14 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-cli-init-enter-selection/specs/cli-init/spec.md +10 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-cli-init-enter-selection/tasks.md +8 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-cli-init-root-agents/proposal.md +15 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-cli-init-root-agents/specs/cli-init/spec.md +32 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-cli-init-root-agents/specs/cli-update/spec.md +10 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-cli-init-root-agents/tasks.md +11 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-release-automation/proposal.md +49 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-release-automation/tasks.md +12 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-archive-command-arguments/proposal.md +17 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-archive-command-arguments/specs/cli-update/spec.md +32 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-archive-command-arguments/tasks.md +15 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-cline-support/proposal.md +15 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-cline-support/specs/cli-init/spec.md +97 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-cline-support/tasks.md +19 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-crush-support/proposal.md +13 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-crush-support/specs/cli-init/spec.md +67 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-crush-support/tasks.md +7 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-factory-slash-commands/proposal.md +12 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-factory-slash-commands/specs/cli-init/spec.md +54 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-factory-slash-commands/specs/cli-update/spec.md +54 -0
- package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-factory-slash-commands/tasks.md +11 -0
- package/OpenSpec-main/openspec/changes/archive/2025-11-06-add-shell-completions/design.md +525 -0
- package/OpenSpec-main/openspec/changes/archive/2025-11-06-add-shell-completions/proposal.md +29 -0
- package/OpenSpec-main/openspec/changes/archive/2025-11-06-add-shell-completions/specs/cli-completion/spec.md +300 -0
- package/OpenSpec-main/openspec/changes/archive/2025-11-06-add-shell-completions/tasks.md +81 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-20-add-global-config-dir/design.md +105 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-20-add-global-config-dir/proposal.md +20 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-20-add-global-config-dir/specs/global-config/spec.md +76 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-20-add-global-config-dir/tasks.md +26 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-21-add-config-command/design.md +89 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-21-add-config-command/proposal.md +60 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-21-add-config-command/specs/cli-config/spec.md +213 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-21-add-config-command/tasks.md +28 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-23-extend-shell-completions/proposal.md +15 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-23-extend-shell-completions/specs/cli-completion/spec.md +328 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-23-extend-shell-completions/tasks.md +49 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-24-add-artifact-graph-core/design.md +197 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-24-add-artifact-graph-core/proposal.md +18 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-24-add-artifact-graph-core/specs/artifact-graph/spec.md +103 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-24-add-artifact-graph-core/tasks.md +61 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-25-add-change-manager/design.md +74 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-25-add-change-manager/proposal.md +45 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-25-add-change-manager/specs/change-creation/spec.md +63 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-25-add-change-manager/tasks.md +30 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-28-add-artifact-workflow-cli/design.md +112 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-28-add-artifact-workflow-cli/proposal.md +33 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-28-add-artifact-workflow-cli/specs/cli-artifact-workflow/spec.md +153 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-28-add-artifact-workflow-cli/tasks.md +48 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-28-add-instruction-loader/design.md +149 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-28-add-instruction-loader/proposal.md +20 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-28-add-instruction-loader/specs/instruction-loader/spec.md +70 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-28-add-instruction-loader/tasks.md +13 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-28-restructure-schema-directories/design.md +129 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-28-restructure-schema-directories/proposal.md +20 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-28-restructure-schema-directories/specs/artifact-graph/spec.md +49 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-28-restructure-schema-directories/tasks.md +32 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-29-unify-change-state-model/design.md +151 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-29-unify-change-state-model/proposal.md +101 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-29-unify-change-state-model/specs/cli-artifact-workflow/spec.md +109 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-29-unify-change-state-model/specs/cli-view/spec.md +60 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-29-unify-change-state-model/tasks.md +25 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-30-add-antigravity-support/proposal.md +11 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-30-add-antigravity-support/specs/cli-init/spec.md +105 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-30-add-antigravity-support/specs/cli-update/spec.md +92 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-30-add-antigravity-support/tasks.md +12 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-30-fix-cline-workflows-implementation/proposal.md +13 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-30-fix-cline-workflows-implementation/specs/cli-init/spec.md +105 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-30-fix-cline-workflows-implementation/specs/cli-update/spec.md +92 -0
- package/OpenSpec-main/openspec/changes/archive/2025-12-30-fix-cline-workflows-implementation/tasks.md +13 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-agent-schema-selection/proposal.md +26 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-agent-schema-selection/tasks.md +32 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-per-change-schema-metadata/design.md +147 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-per-change-schema-metadata/proposal.md +29 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-per-change-schema-metadata/specs/cli-artifact-workflow/spec.md +98 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-per-change-schema-metadata/tasks.md +29 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-specs-apply-command/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-specs-apply-command/design.md +77 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-specs-apply-command/proposal.md +32 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-specs-apply-command/specs/specs-sync-skill/spec.md +67 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-specs-apply-command/tasks.md +40 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-make-apply-instructions-schema-aware/proposal.md +138 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-make-apply-instructions-schema-aware/specs/cli-artifact-workflow/spec.md +60 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-make-apply-instructions-schema-aware/tasks.md +35 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-opsx-archive-command/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-opsx-archive-command/design.md +84 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-opsx-archive-command/proposal.md +28 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-opsx-archive-command/specs/opsx-archive-skill/spec.md +122 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-06-opsx-archive-command/tasks.md +23 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-07-add-nix-flake-support/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-07-add-nix-flake-support/design.md +94 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-07-add-nix-flake-support/proposal.md +25 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-07-add-nix-flake-support/specs/nix-flake-support/spec.md +79 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-07-add-nix-flake-support/tasks.md +65 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-flake-update-script/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-flake-update-script/design.md +117 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-flake-update-script/proposal.md +23 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-flake-update-script/specs/flake-update-script/spec.md +93 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-flake-update-script/tasks.md +55 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-posthog-analytics/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-posthog-analytics/design.md +175 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-posthog-analytics/proposal.md +37 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-posthog-analytics/specs/global-config/spec.md +21 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-posthog-analytics/specs/telemetry/spec.md +116 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-posthog-analytics/tasks.md +47 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-09-fix-codebuddy-frontmatter-fields/proposal.md +16 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-09-fix-codebuddy-frontmatter-fields/specs/cli-init/spec.md +75 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-09-fix-codebuddy-frontmatter-fields/specs/cli-update/spec.md +56 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-09-fix-codebuddy-frontmatter-fields/tasks.md +6 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-15-add-nix-ci-validation/design.md +206 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-15-add-nix-ci-validation/proposal.md +21 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-15-add-nix-ci-validation/specs/ci-nix-validation/spec.md +104 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-15-add-nix-ci-validation/tasks.md +49 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-30-opencode-command-references/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-30-opencode-command-references/README.md +3 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-30-opencode-command-references/design.md +70 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-30-opencode-command-references/proposal.md +32 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-30-opencode-command-references/specs/no-changes.md +9 -0
- package/OpenSpec-main/openspec/changes/archive/2026-01-30-opencode-command-references/tasks.md +22 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-feedback-command/proposal.md +20 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-feedback-command/specs/cli-feedback/spec.md +188 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-feedback-command/tasks.md +30 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-opsx-onboard-skill/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-opsx-onboard-skill/design.md +115 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-opsx-onboard-skill/proposal.md +27 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-opsx-onboard-skill/specs/opsx-onboard-skill/spec.md +162 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-opsx-onboard-skill/tasks.md +21 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-verify-skill/design.md +96 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-verify-skill/proposal.md +48 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-verify-skill/specs/opsx-verify-skill/spec.md +190 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-verify-skill/tasks.md +15 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-merge-init-experimental/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-merge-init-experimental/design.md +193 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-merge-init-experimental/proposal.md +32 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-merge-init-experimental/specs/cli-init/spec.md +176 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-merge-init-experimental/specs/legacy-cleanup/spec.md +158 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-merge-init-experimental/tasks.md +67 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-multi-provider-skill-generation/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-multi-provider-skill-generation/design.md +144 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-multi-provider-skill-generation/proposal.md +36 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-multi-provider-skill-generation/specs/ai-tool-paths/spec.md +63 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-multi-provider-skill-generation/specs/cli-artifact-workflow/spec.md +60 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-multi-provider-skill-generation/specs/command-generation/spec.md +98 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-multi-provider-skill-generation/tasks.md +55 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-config/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-config/design.md +665 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-config/proposal.md +774 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-config/specs/config-loading/spec.md +119 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-config/specs/context-injection/spec.md +51 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-config/specs/rules-injection/spec.md +99 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-config/specs/schema-resolution/spec.md +83 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-config/tasks.md +72 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-local-schemas/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-local-schemas/design.md +117 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-local-schemas/proposal.md +167 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-local-schemas/specs/schema-resolution/spec.md +88 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-local-schemas/tasks.md +28 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-schema-management-cli/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-schema-management-cli/design.md +113 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-schema-management-cli/proposal.md +55 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-schema-management-cli/specs/schema-fork-command/spec.md +66 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-schema-management-cli/specs/schema-init-command/spec.md +71 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-schema-management-cli/specs/schema-validate-command/spec.md +86 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-schema-management-cli/specs/schema-which-command/spec.md +65 -0
- package/OpenSpec-main/openspec/changes/archive/2026-02-17-schema-management-cli/tasks.md +67 -0
- package/OpenSpec-main/openspec/changes/archive/2026-04-23-add-kimi-cli-skills-only-support/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/archive/2026-04-23-add-kimi-cli-skills-only-support/README.md +3 -0
- package/OpenSpec-main/openspec/changes/archive/2026-04-23-add-kimi-cli-skills-only-support/design.md +85 -0
- package/OpenSpec-main/openspec/changes/archive/2026-04-23-add-kimi-cli-skills-only-support/proposal.md +38 -0
- package/OpenSpec-main/openspec/changes/archive/2026-04-23-add-kimi-cli-skills-only-support/specs/ai-tool-paths/spec.md +12 -0
- package/OpenSpec-main/openspec/changes/archive/2026-04-23-add-kimi-cli-skills-only-support/specs/cli-init/spec.md +37 -0
- package/OpenSpec-main/openspec/changes/archive/2026-04-23-add-kimi-cli-skills-only-support/tasks.md +22 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-04-workspace-foundation/design.md +208 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-04-workspace-foundation/proposal.md +142 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-04-workspace-foundation/specs/openspec-conventions/spec.md +29 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-04-workspace-foundation/specs/workspace-foundation/spec.md +199 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-04-workspace-foundation/tasks.md +56 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-create-and-register-repos/design.md +356 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-create-and-register-repos/proposal.md +128 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-create-and-register-repos/specs/cli-artifact-workflow/spec.md +24 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-create-and-register-repos/specs/workspace-foundation/spec.md +35 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-create-and-register-repos/specs/workspace-links/spec.md +356 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-create-and-register-repos/tasks.md +121 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-open-agent-context/design.md +266 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-open-agent-context/proposal.md +65 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-open-agent-context/specs/workspace-foundation/spec.md +76 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-open-agent-context/specs/workspace-open/spec.md +199 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-open-agent-context/tasks.md +89 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/design.md +242 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/proposal.md +78 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/artifact-graph/spec.md +36 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/change-creation/spec.md +42 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/cli-artifact-workflow/spec.md +100 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/cli-config/spec.md +55 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/cli-update/spec.md +21 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/openspec-conventions/spec.md +32 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/schema-resolution/spec.md +25 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/workspace-change-planning/spec.md +67 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/workspace-links/spec.md +163 -0
- package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/tasks.md +133 -0
- package/OpenSpec-main/openspec/changes/fix-opencode-commands-directory/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/fix-opencode-commands-directory/design.md +48 -0
- package/OpenSpec-main/openspec/changes/fix-opencode-commands-directory/proposal.md +26 -0
- package/OpenSpec-main/openspec/changes/fix-opencode-commands-directory/specs/command-generation/spec.md +63 -0
- package/OpenSpec-main/openspec/changes/fix-opencode-commands-directory/tasks.md +19 -0
- package/OpenSpec-main/openspec/changes/graceful-status-no-changes/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/graceful-status-no-changes/design.md +38 -0
- package/OpenSpec-main/openspec/changes/graceful-status-no-changes/proposal.md +25 -0
- package/OpenSpec-main/openspec/changes/graceful-status-no-changes/specs/graceful-status-empty/spec.md +27 -0
- package/OpenSpec-main/openspec/changes/graceful-status-no-changes/tasks.md +16 -0
- package/OpenSpec-main/openspec/changes/schema-alias-support/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/schema-alias-support/proposal.md +28 -0
- package/OpenSpec-main/openspec/changes/simplify-skill-installation/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/simplify-skill-installation/design.md +288 -0
- package/OpenSpec-main/openspec/changes/simplify-skill-installation/proposal.md +202 -0
- package/OpenSpec-main/openspec/changes/simplify-skill-installation/specs/cli-init/spec.md +199 -0
- package/OpenSpec-main/openspec/changes/simplify-skill-installation/specs/cli-update/spec.md +177 -0
- package/OpenSpec-main/openspec/changes/simplify-skill-installation/specs/profiles/spec.md +142 -0
- package/OpenSpec-main/openspec/changes/simplify-skill-installation/specs/propose-workflow/spec.md +42 -0
- package/OpenSpec-main/openspec/changes/simplify-skill-installation/tasks.md +132 -0
- package/OpenSpec-main/openspec/changes/unify-template-generation-pipeline/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/unify-template-generation-pipeline/design.md +149 -0
- package/OpenSpec-main/openspec/changes/unify-template-generation-pipeline/proposal.md +47 -0
- package/OpenSpec-main/openspec/changes/unify-template-generation-pipeline/specs/template-artifact-pipeline/spec.md +89 -0
- package/OpenSpec-main/openspec/changes/unify-template-generation-pipeline/tasks.md +41 -0
- package/OpenSpec-main/openspec/changes/workspace-agent-guidance/.openspec.yaml +2 -0
- package/OpenSpec-main/openspec/changes/workspace-agent-guidance/proposal.md +100 -0
- package/OpenSpec-main/openspec/changes/workspace-apply-repo-slice/proposal.md +58 -0
- package/OpenSpec-main/openspec/changes/workspace-reimplementation-roadmap/HISTORICAL_DIRECTION.md +511 -0
- package/OpenSpec-main/openspec/changes/workspace-reimplementation-roadmap/POC_REFERENCE_GUIDE.md +266 -0
- package/OpenSpec-main/openspec/changes/workspace-reimplementation-roadmap/README.md +107 -0
- package/OpenSpec-main/openspec/changes/workspace-reimplementation-roadmap/START_HERE.md +105 -0
- package/OpenSpec-main/openspec/changes/workspace-reimplementation-roadmap/proposal.md +62 -0
- package/OpenSpec-main/openspec/changes/workspace-verify-and-archive/proposal.md +57 -0
- package/OpenSpec-main/openspec/config.yaml +36 -0
- package/OpenSpec-main/openspec/explorations/explore-workflow-ux.md +116 -0
- package/OpenSpec-main/openspec/explorations/workspace-architecture.md +857 -0
- package/OpenSpec-main/openspec/explorations/workspace-roadmap.md +367 -0
- package/OpenSpec-main/openspec/explorations/workspace-user-journeys.md +2259 -0
- package/OpenSpec-main/openspec/explorations/workspace-ux-simplification.md +491 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/.initiative.yaml +27 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/README.md +33 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/decisions.md +204 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/direction.md +447 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/questions.md +23 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/roadmap.md +759 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/tasks.md +308 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/01-lock-the-direction/evidence.md +154 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/01-lock-the-direction/plan.md +90 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/01-lock-the-direction/tasks.md +44 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/02-stabilize-workspace-as-local-view/evidence.md +68 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/02-stabilize-workspace-as-local-view/plan.md +80 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/02-stabilize-workspace-as-local-view/tasks.md +23 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/03-add-context-store-foundation/evidence.md +43 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/03-add-context-store-foundation/plan.md +85 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/03-add-context-store-foundation/tasks.md +17 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/04-add-collection-foundation/evidence.md +77 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/04-add-collection-foundation/plan.md +198 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/04-add-collection-foundation/tasks.md +14 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/05-ship-initiative-mvp/evidence.md +99 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/05-ship-initiative-mvp/plan.md +236 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/05-ship-initiative-mvp/tasks.md +21 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/06-add-minimal-context-store-ux/evidence.md +97 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/06-add-minimal-context-store-ux/plan.md +333 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/06-add-minimal-context-store-ux/tasks.md +29 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/07-add-agent-first-initiative-discovery/evidence.md +97 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/07-add-agent-first-initiative-discovery/plan.md +184 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/07-add-agent-first-initiative-discovery/tasks.md +27 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/08-connect-repo-local-changes-to-initiatives/evidence.md +239 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/08-connect-repo-local-changes-to-initiatives/plan.md +279 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/08-connect-repo-local-changes-to-initiatives/tasks.md +22 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/09-add-initiative-resolve/decision-review.md +64 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/09-add-initiative-resolve/evidence.md +106 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/09-add-initiative-resolve/plan.md +141 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/09-add-initiative-resolve/tasks.md +22 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/10-let-workspaces-open-initiatives/plan.md +430 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/10-let-workspaces-open-initiatives/tasks.md +43 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/11-manual-beta-reality-pass/notes.md +289 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/11-manual-beta-reality-pass/plan.md +39 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/11-manual-beta-reality-pass/tasks.md +8 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/12-context-store-first-run-and-cleanup-ux/evidence.md +45 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/12-context-store-first-run-and-cleanup-ux/plan.md +150 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/12-context-store-first-run-and-cleanup-ux/tasks.md +23 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/13-agent-handoff-output-and-delivery-polish/evidence.md +25 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/13-agent-handoff-output-and-delivery-polish/plan.md +98 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/13-agent-handoff-output-and-delivery-polish/tasks.md +25 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/14-workspaces-beta-guide-split/plan.md +37 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/14-workspaces-beta-guide-split/tasks.md +9 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/15-context-store-project-roots-and-schema-led-initiatives/evidence.md +140 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/15-context-store-project-roots-and-schema-led-initiatives/plan.md +344 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/15-context-store-project-roots-and-schema-led-initiatives/tasks.md +39 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/16-add-escalation-ux/plan.md +26 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/16-add-escalation-ux/tasks.md +7 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/17-harden-team-shared-coordination/plan.md +25 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/17-harden-team-shared-coordination/tasks.md +7 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/18-explore-initiative-hosted-target-bound-change-artifacts/evidence.md +397 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/18-explore-initiative-hosted-target-bound-change-artifacts/plan.md +180 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/18-explore-initiative-hosted-target-bound-change-artifacts/tasks.md +28 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/19-review-workspace-beta-compatibility-before-public-release/plan.md +62 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/19-review-workspace-beta-compatibility-before-public-release/tasks.md +16 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/proposed-initiative-next-agent-handoff-ux/evidence.md +47 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/proposed-initiative-next-agent-handoff-ux/plan.md +90 -0
- package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/proposed-initiative-next-agent-handoff-ux/tasks.md +18 -0
- package/OpenSpec-main/openspec/specs/ai-tool-paths/spec.md +63 -0
- package/OpenSpec-main/openspec/specs/artifact-graph/spec.md +165 -0
- package/OpenSpec-main/openspec/specs/change-creation/spec.md +108 -0
- package/OpenSpec-main/openspec/specs/ci-nix-validation/spec.md +107 -0
- package/OpenSpec-main/openspec/specs/cli-archive/spec.md +210 -0
- package/OpenSpec-main/openspec/specs/cli-artifact-workflow/spec.md +398 -0
- package/OpenSpec-main/openspec/specs/cli-change/spec.md +92 -0
- package/OpenSpec-main/openspec/specs/cli-completion/spec.md +432 -0
- package/OpenSpec-main/openspec/specs/cli-config/spec.md +318 -0
- package/OpenSpec-main/openspec/specs/cli-feedback/spec.md +193 -0
- package/OpenSpec-main/openspec/specs/cli-init/spec.md +269 -0
- package/OpenSpec-main/openspec/specs/cli-list/spec.md +103 -0
- package/OpenSpec-main/openspec/specs/cli-show/spec.md +86 -0
- package/OpenSpec-main/openspec/specs/cli-spec/spec.md +88 -0
- package/OpenSpec-main/openspec/specs/cli-update/spec.md +229 -0
- package/OpenSpec-main/openspec/specs/cli-validate/spec.md +219 -0
- package/OpenSpec-main/openspec/specs/cli-view/spec.md +129 -0
- package/OpenSpec-main/openspec/specs/command-generation/spec.md +97 -0
- package/OpenSpec-main/openspec/specs/config-loading/spec.md +122 -0
- package/OpenSpec-main/openspec/specs/context-injection/spec.md +53 -0
- package/OpenSpec-main/openspec/specs/docs-agent-instructions/spec.md +62 -0
- package/OpenSpec-main/openspec/specs/global-config/spec.md +101 -0
- package/OpenSpec-main/openspec/specs/instruction-loader/spec.md +70 -0
- package/OpenSpec-main/openspec/specs/legacy-cleanup/spec.md +163 -0
- package/OpenSpec-main/openspec/specs/openspec-conventions/spec.md +556 -0
- package/OpenSpec-main/openspec/specs/opsx-archive-skill/spec.md +128 -0
- package/OpenSpec-main/openspec/specs/opsx-onboard-skill/spec.md +167 -0
- package/OpenSpec-main/openspec/specs/opsx-verify-skill/spec.md +189 -0
- package/OpenSpec-main/openspec/specs/rules-injection/spec.md +102 -0
- package/OpenSpec-main/openspec/specs/schema-fork-command/spec.md +71 -0
- package/OpenSpec-main/openspec/specs/schema-init-command/spec.md +76 -0
- package/OpenSpec-main/openspec/specs/schema-resolution/spec.md +201 -0
- package/OpenSpec-main/openspec/specs/schema-validate-command/spec.md +91 -0
- package/OpenSpec-main/openspec/specs/schema-which-command/spec.md +70 -0
- package/OpenSpec-main/openspec/specs/specs-sync-skill/spec.md +72 -0
- package/OpenSpec-main/openspec/specs/telemetry/spec.md +122 -0
- package/OpenSpec-main/openspec/specs/workspace-change-planning/spec.md +71 -0
- package/OpenSpec-main/openspec/specs/workspace-foundation/spec.md +279 -0
- package/OpenSpec-main/openspec/specs/workspace-links/spec.md +529 -0
- package/OpenSpec-main/openspec/specs/workspace-open/spec.md +205 -0
- package/OpenSpec-main/openspec-parallel-merge-plan.md +98 -0
- package/OpenSpec-main/package-lock.json +4978 -0
- package/OpenSpec-main/package.json +84 -0
- package/OpenSpec-main/pnpm-lock.yaml +3187 -0
- package/OpenSpec-main/schemas/spec-driven/schema.yaml +153 -0
- package/OpenSpec-main/schemas/spec-driven/templates/design.md +19 -0
- package/OpenSpec-main/schemas/spec-driven/templates/proposal.md +23 -0
- package/OpenSpec-main/schemas/spec-driven/templates/spec.md +8 -0
- package/OpenSpec-main/schemas/spec-driven/templates/tasks.md +9 -0
- package/OpenSpec-main/schemas/workspace-planning/schema.yaml +72 -0
- package/OpenSpec-main/schemas/workspace-planning/templates/design.md +33 -0
- package/OpenSpec-main/schemas/workspace-planning/templates/proposal.md +28 -0
- package/OpenSpec-main/schemas/workspace-planning/templates/spec.md +9 -0
- package/OpenSpec-main/schemas/workspace-planning/templates/tasks.md +15 -0
- package/OpenSpec-main/scripts/README.md +37 -0
- package/OpenSpec-main/scripts/pack-version-check.mjs +111 -0
- package/OpenSpec-main/scripts/postinstall.js +83 -0
- package/OpenSpec-main/scripts/test-postinstall.sh +57 -0
- package/OpenSpec-main/scripts/update-flake.sh +128 -0
- package/OpenSpec-main/test/cli-e2e/basic.test.ts +205 -0
- package/OpenSpec-main/test/commands/artifact-workflow.test.ts +1063 -0
- package/OpenSpec-main/test/commands/change-initiative-link.test.ts +532 -0
- package/OpenSpec-main/test/commands/change.interactive-show.test.ts +45 -0
- package/OpenSpec-main/test/commands/change.interactive-validate.test.ts +48 -0
- package/OpenSpec-main/test/commands/completion.test.ts +278 -0
- package/OpenSpec-main/test/commands/config-profile.test.ts +532 -0
- package/OpenSpec-main/test/commands/config.test.ts +285 -0
- package/OpenSpec-main/test/commands/context-store.test.ts +692 -0
- package/OpenSpec-main/test/commands/feedback.test.ts +429 -0
- package/OpenSpec-main/test/commands/initiative.test.ts +907 -0
- package/OpenSpec-main/test/commands/schema.test.ts +467 -0
- package/OpenSpec-main/test/commands/show.test.ts +123 -0
- package/OpenSpec-main/test/commands/spec.interactive-show.test.ts +44 -0
- package/OpenSpec-main/test/commands/spec.interactive-validate.test.ts +44 -0
- package/OpenSpec-main/test/commands/spec.test.ts +324 -0
- package/OpenSpec-main/test/commands/validate.enriched-output.test.ts +49 -0
- package/OpenSpec-main/test/commands/validate.test.ts +147 -0
- package/OpenSpec-main/test/commands/workspace-initiative-open.test.ts +638 -0
- package/OpenSpec-main/test/commands/workspace-open.test.ts +123 -0
- package/OpenSpec-main/test/commands/workspace.interactive.test.ts +696 -0
- package/OpenSpec-main/test/commands/workspace.test.ts +1812 -0
- package/OpenSpec-main/test/core/archive.test.ts +869 -0
- package/OpenSpec-main/test/core/artifact-graph/graph.test.ts +268 -0
- package/OpenSpec-main/test/core/artifact-graph/instruction-loader.test.ts +609 -0
- package/OpenSpec-main/test/core/artifact-graph/outputs.test.ts +175 -0
- package/OpenSpec-main/test/core/artifact-graph/resolver.test.ts +651 -0
- package/OpenSpec-main/test/core/artifact-graph/schema.test.ts +207 -0
- package/OpenSpec-main/test/core/artifact-graph/state.test.ts +174 -0
- package/OpenSpec-main/test/core/artifact-graph/workflow.integration.test.ts +182 -0
- package/OpenSpec-main/test/core/available-tools.test.ts +167 -0
- package/OpenSpec-main/test/core/collections/initiatives/operations.test.ts +342 -0
- package/OpenSpec-main/test/core/collections/initiatives/resolution.test.ts +21 -0
- package/OpenSpec-main/test/core/collections/initiatives/schema.test.ts +201 -0
- package/OpenSpec-main/test/core/collections/initiatives/templates.test.ts +74 -0
- package/OpenSpec-main/test/core/collections/runtime.test.ts +214 -0
- package/OpenSpec-main/test/core/command-generation/adapters.test.ts +710 -0
- package/OpenSpec-main/test/core/command-generation/generator.test.ts +110 -0
- package/OpenSpec-main/test/core/command-generation/registry.test.ts +108 -0
- package/OpenSpec-main/test/core/command-generation/types.test.ts +79 -0
- package/OpenSpec-main/test/core/commands/change-command.list.test.ts +76 -0
- package/OpenSpec-main/test/core/commands/change-command.show-validate.test.ts +111 -0
- package/OpenSpec-main/test/core/completions/command-registry.test.ts +201 -0
- package/OpenSpec-main/test/core/completions/completion-provider.test.ts +288 -0
- package/OpenSpec-main/test/core/completions/generators/bash-generator.test.ts +586 -0
- package/OpenSpec-main/test/core/completions/generators/fish-generator.test.ts +549 -0
- package/OpenSpec-main/test/core/completions/generators/powershell-generator.test.ts +621 -0
- package/OpenSpec-main/test/core/completions/generators/zsh-generator.test.ts +425 -0
- package/OpenSpec-main/test/core/completions/installers/bash-installer.test.ts +484 -0
- package/OpenSpec-main/test/core/completions/installers/fish-installer.test.ts +321 -0
- package/OpenSpec-main/test/core/completions/installers/powershell-installer.test.ts +824 -0
- package/OpenSpec-main/test/core/completions/installers/zsh-installer.test.ts +750 -0
- package/OpenSpec-main/test/core/config-schema.test.ts +340 -0
- package/OpenSpec-main/test/core/context-store/foundation.test.ts +364 -0
- package/OpenSpec-main/test/core/context-store/registry.test.ts +599 -0
- package/OpenSpec-main/test/core/converters/json-converter.test.ts +184 -0
- package/OpenSpec-main/test/core/global-config.test.ts +371 -0
- package/OpenSpec-main/test/core/init.test.ts +786 -0
- package/OpenSpec-main/test/core/legacy-cleanup.test.ts +1162 -0
- package/OpenSpec-main/test/core/list.test.ts +165 -0
- package/OpenSpec-main/test/core/migration.test.ts +150 -0
- package/OpenSpec-main/test/core/parsers/change-parser.test.ts +52 -0
- package/OpenSpec-main/test/core/parsers/markdown-parser.test.ts +355 -0
- package/OpenSpec-main/test/core/parsers/requirement-blocks.test.ts +46 -0
- package/OpenSpec-main/test/core/planning-home.test.ts +120 -0
- package/OpenSpec-main/test/core/profile-sync-drift.test.ts +92 -0
- package/OpenSpec-main/test/core/profiles.test.ts +63 -0
- package/OpenSpec-main/test/core/project-config.test.ts +610 -0
- package/OpenSpec-main/test/core/shared/skill-generation.test.ts +301 -0
- package/OpenSpec-main/test/core/shared/tool-detection.test.ts +333 -0
- package/OpenSpec-main/test/core/templates/skill-templates-parity.test.ts +172 -0
- package/OpenSpec-main/test/core/update.test.ts +1810 -0
- package/OpenSpec-main/test/core/validation.enriched-messages.test.ts +74 -0
- package/OpenSpec-main/test/core/validation.test.ts +680 -0
- package/OpenSpec-main/test/core/view.test.ts +129 -0
- package/OpenSpec-main/test/core/workspace/foundation.test.ts +694 -0
- package/OpenSpec-main/test/core/workspace/legacy-state.test.ts +221 -0
- package/OpenSpec-main/test/core/workspace/skills.test.ts +69 -0
- package/OpenSpec-main/test/fixtures/tmp-init/openspec/changes/c1/proposal.md +7 -0
- package/OpenSpec-main/test/fixtures/tmp-init/openspec/changes/c1/specs/alpha/spec.md +8 -0
- package/OpenSpec-main/test/fixtures/tmp-init/openspec/specs/alpha/spec.md +12 -0
- package/OpenSpec-main/test/helpers/path-env.ts +26 -0
- package/OpenSpec-main/test/helpers/run-cli.ts +150 -0
- package/OpenSpec-main/test/prompts/searchable-multi-select.test.ts +220 -0
- package/OpenSpec-main/test/specs/source-specs-normalization.test.ts +63 -0
- package/OpenSpec-main/test/telemetry/config.test.ts +298 -0
- package/OpenSpec-main/test/telemetry/index.test.ts +219 -0
- package/OpenSpec-main/test/utils/change-metadata.test.ts +368 -0
- package/OpenSpec-main/test/utils/change-utils.test.ts +201 -0
- package/OpenSpec-main/test/utils/command-references.test.ts +83 -0
- package/OpenSpec-main/test/utils/file-system.test.ts +322 -0
- package/OpenSpec-main/test/utils/interactive.test.ts +125 -0
- package/OpenSpec-main/test/utils/marker-updates.test.ts +448 -0
- package/OpenSpec-main/test/utils/shell-detection.test.ts +185 -0
- package/OpenSpec-main/vitest.config.ts +47 -0
- package/OpenSpec-main/vitest.setup.ts +15 -0
- package/README.md +37 -4
- package/Scanner CLI Inteligente para Projetos.md +433 -0
- package/dist/index.js +1178 -139
- package/package.json +1 -1
- package/templates/wiki-recipes/nextjs.rules.md +21 -0
- package/templates/wiki-recipes/postgresql.rules.md +20 -0
- package/templates/wiki-recipes/react.rules.md +18 -0
- package/templates/wiki-recipes/tailwindcss.rules.md +18 -0
- package/templates/wiki-recipes/typescript.rules.md +21 -0
|
@@ -0,0 +1,824 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
+
import { PowerShellInstaller } from '../../../../src/core/completions/installers/powershell-installer.js';
|
|
3
|
+
import { promises as fs } from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import os from 'os';
|
|
6
|
+
import { randomUUID } from 'crypto';
|
|
7
|
+
|
|
8
|
+
describe('PowerShellInstaller', () => {
|
|
9
|
+
let testHomeDir: string;
|
|
10
|
+
let installer: PowerShellInstaller;
|
|
11
|
+
let originalPlatform: NodeJS.Platform;
|
|
12
|
+
let originalEnv: NodeJS.ProcessEnv;
|
|
13
|
+
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
testHomeDir = path.join(os.tmpdir(), `openspec-powershell-test-${randomUUID()}`);
|
|
16
|
+
await fs.mkdir(testHomeDir, { recursive: true });
|
|
17
|
+
installer = new PowerShellInstaller(testHomeDir);
|
|
18
|
+
originalPlatform = process.platform;
|
|
19
|
+
originalEnv = { ...process.env };
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
afterEach(async () => {
|
|
23
|
+
await fs.rm(testHomeDir, { recursive: true, force: true });
|
|
24
|
+
// Restore platform and environment
|
|
25
|
+
Object.defineProperty(process, 'platform', {
|
|
26
|
+
value: originalPlatform,
|
|
27
|
+
});
|
|
28
|
+
process.env = originalEnv;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('getProfilePath', () => {
|
|
32
|
+
it('should prefer PROFILE environment variable when set', () => {
|
|
33
|
+
process.env.PROFILE = '/custom/profile/path.ps1';
|
|
34
|
+
const result = installer.getProfilePath();
|
|
35
|
+
expect(result).toBe('/custom/profile/path.ps1');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should return Windows default path when on win32 platform', () => {
|
|
39
|
+
delete process.env.PROFILE;
|
|
40
|
+
Object.defineProperty(process, 'platform', {
|
|
41
|
+
value: 'win32',
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const result = installer.getProfilePath();
|
|
45
|
+
expect(result).toBe(path.join(testHomeDir, 'Documents', 'PowerShell', 'Microsoft.PowerShell_profile.ps1'));
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should return Unix default path when on darwin platform', () => {
|
|
49
|
+
delete process.env.PROFILE;
|
|
50
|
+
Object.defineProperty(process, 'platform', {
|
|
51
|
+
value: 'darwin',
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const result = installer.getProfilePath();
|
|
55
|
+
expect(result).toBe(path.join(testHomeDir, '.config', 'powershell', 'Microsoft.PowerShell_profile.ps1'));
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should return Unix default path when on linux platform', () => {
|
|
59
|
+
delete process.env.PROFILE;
|
|
60
|
+
Object.defineProperty(process, 'platform', {
|
|
61
|
+
value: 'linux',
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const result = installer.getProfilePath();
|
|
65
|
+
expect(result).toBe(path.join(testHomeDir, '.config', 'powershell', 'Microsoft.PowerShell_profile.ps1'));
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('getInstallationPath', () => {
|
|
70
|
+
it('should return path relative to profile directory', () => {
|
|
71
|
+
delete process.env.PROFILE;
|
|
72
|
+
Object.defineProperty(process, 'platform', {
|
|
73
|
+
value: 'darwin',
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const result = installer.getInstallationPath();
|
|
77
|
+
expect(result).toBe(path.join(testHomeDir, '.config', 'powershell', 'OpenSpecCompletion.ps1'));
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should work with custom PROFILE environment variable', () => {
|
|
81
|
+
process.env.PROFILE = path.join(testHomeDir, 'custom', 'profile.ps1');
|
|
82
|
+
const result = installer.getInstallationPath();
|
|
83
|
+
expect(result).toBe(path.join(testHomeDir, 'custom', 'OpenSpecCompletion.ps1'));
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should return Windows path when on Windows platform', () => {
|
|
87
|
+
delete process.env.PROFILE;
|
|
88
|
+
Object.defineProperty(process, 'platform', {
|
|
89
|
+
value: 'win32',
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const result = installer.getInstallationPath();
|
|
93
|
+
expect(result).toBe(path.join(testHomeDir, 'Documents', 'PowerShell', 'OpenSpecCompletion.ps1'));
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
describe('backupExistingFile', () => {
|
|
98
|
+
it('should return undefined when file does not exist', async () => {
|
|
99
|
+
const nonExistentPath = path.join(testHomeDir, 'does-not-exist.ps1');
|
|
100
|
+
const backupPath = await installer.backupExistingFile(nonExistentPath);
|
|
101
|
+
expect(backupPath).toBeUndefined();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('should create backup with timestamp in filename', async () => {
|
|
105
|
+
const filePath = path.join(testHomeDir, 'test.ps1');
|
|
106
|
+
await fs.writeFile(filePath, 'test content');
|
|
107
|
+
|
|
108
|
+
const backupPath = await installer.backupExistingFile(filePath);
|
|
109
|
+
|
|
110
|
+
expect(backupPath).toBeDefined();
|
|
111
|
+
expect(backupPath).toMatch(/\.backup-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}/);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should copy file content to backup', async () => {
|
|
115
|
+
const filePath = path.join(testHomeDir, 'test.ps1');
|
|
116
|
+
const originalContent = '# Original PowerShell completion script\n$completer = {}';
|
|
117
|
+
await fs.writeFile(filePath, originalContent);
|
|
118
|
+
|
|
119
|
+
const backupPath = await installer.backupExistingFile(filePath);
|
|
120
|
+
|
|
121
|
+
expect(backupPath).toBeDefined();
|
|
122
|
+
const backupContent = await fs.readFile(backupPath!, 'utf-8');
|
|
123
|
+
expect(backupContent).toBe(originalContent);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should create backup next to original file', async () => {
|
|
127
|
+
const filePath = path.join(testHomeDir, 'subdir', 'test.ps1');
|
|
128
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
129
|
+
await fs.writeFile(filePath, 'content');
|
|
130
|
+
|
|
131
|
+
const backupPath = await installer.backupExistingFile(filePath);
|
|
132
|
+
|
|
133
|
+
expect(backupPath).toBeDefined();
|
|
134
|
+
expect(path.dirname(backupPath!)).toBe(path.dirname(filePath));
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
describe('configureProfile', () => {
|
|
139
|
+
const mockScriptPath = '/path/to/OpenSpecCompletion.ps1';
|
|
140
|
+
|
|
141
|
+
// Note: OPENSPEC_NO_AUTO_CONFIG check is now handled in the install() method,
|
|
142
|
+
// not in configureProfile() itself
|
|
143
|
+
|
|
144
|
+
it('should create profile with markers when file does not exist', async () => {
|
|
145
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
146
|
+
const profilePath = installer.getProfilePath();
|
|
147
|
+
|
|
148
|
+
const result = await installer.configureProfile(mockScriptPath);
|
|
149
|
+
|
|
150
|
+
expect(result).toBe(true);
|
|
151
|
+
const content = await fs.readFile(profilePath, 'utf-8');
|
|
152
|
+
expect(content).toContain('# OPENSPEC:START');
|
|
153
|
+
expect(content).toContain('# OPENSPEC:END');
|
|
154
|
+
expect(content).toContain(`. "${mockScriptPath}"`);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('should prepend markers and config when file exists without markers', async () => {
|
|
158
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
159
|
+
const profilePath = installer.getProfilePath();
|
|
160
|
+
await fs.mkdir(path.dirname(profilePath), { recursive: true });
|
|
161
|
+
await fs.writeFile(profilePath, '# My custom PowerShell config\nWrite-Host "Hello"');
|
|
162
|
+
|
|
163
|
+
const result = await installer.configureProfile(mockScriptPath);
|
|
164
|
+
|
|
165
|
+
expect(result).toBe(true);
|
|
166
|
+
const content = await fs.readFile(profilePath, 'utf-8');
|
|
167
|
+
expect(content).toContain('# OPENSPEC:START');
|
|
168
|
+
expect(content).toContain('# OPENSPEC:END');
|
|
169
|
+
expect(content).toContain(mockScriptPath);
|
|
170
|
+
expect(content).toContain('# My custom PowerShell config');
|
|
171
|
+
expect(content).toContain('Write-Host "Hello"');
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// Skip on Windows: Windows has dual profile paths (PowerShell Core + Windows PowerShell 5.1),
|
|
175
|
+
// so even if one profile is already configured, the second one will be configured and return true
|
|
176
|
+
it.skipIf(process.platform === 'win32')('should skip configuration when script line already exists', async () => {
|
|
177
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
178
|
+
const profilePath = installer.getProfilePath();
|
|
179
|
+
await fs.mkdir(path.dirname(profilePath), { recursive: true });
|
|
180
|
+
|
|
181
|
+
const initialContent = [
|
|
182
|
+
'# OPENSPEC:START - OpenSpec completion (managed block, do not edit manually)',
|
|
183
|
+
`. "${mockScriptPath}"`,
|
|
184
|
+
'# OPENSPEC:END',
|
|
185
|
+
'',
|
|
186
|
+
'# My custom config',
|
|
187
|
+
'Write-Host "Custom"',
|
|
188
|
+
].join('\n');
|
|
189
|
+
|
|
190
|
+
await fs.writeFile(profilePath, initialContent);
|
|
191
|
+
|
|
192
|
+
const result = await installer.configureProfile(mockScriptPath);
|
|
193
|
+
|
|
194
|
+
// Should return false because already configured (anyConfigured = false)
|
|
195
|
+
expect(result).toBe(false);
|
|
196
|
+
const content = await fs.readFile(profilePath, 'utf-8');
|
|
197
|
+
// Content should be unchanged
|
|
198
|
+
expect(content).toBe(initialContent);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('should preserve user content outside markers', async () => {
|
|
202
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
203
|
+
const profilePath = installer.getProfilePath();
|
|
204
|
+
await fs.mkdir(path.dirname(profilePath), { recursive: true });
|
|
205
|
+
|
|
206
|
+
const initialContent = [
|
|
207
|
+
'# User config before',
|
|
208
|
+
'Set-Variable -Name "test" -Value "before"',
|
|
209
|
+
'',
|
|
210
|
+
'# OPENSPEC:START',
|
|
211
|
+
'# Old config',
|
|
212
|
+
'# OPENSPEC:END',
|
|
213
|
+
'',
|
|
214
|
+
'# User config after',
|
|
215
|
+
'Set-Variable -Name "test" -Value "after"',
|
|
216
|
+
].join('\n');
|
|
217
|
+
|
|
218
|
+
await fs.writeFile(profilePath, initialContent);
|
|
219
|
+
|
|
220
|
+
const result = await installer.configureProfile(mockScriptPath);
|
|
221
|
+
|
|
222
|
+
expect(result).toBe(true);
|
|
223
|
+
const content = await fs.readFile(profilePath, 'utf-8');
|
|
224
|
+
expect(content).toContain('# User config before');
|
|
225
|
+
expect(content).toContain('Set-Variable -Name "test" -Value "before"');
|
|
226
|
+
expect(content).toContain('# User config after');
|
|
227
|
+
expect(content).toContain('Set-Variable -Name "test" -Value "after"');
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it('should generate correct PowerShell syntax in config', async () => {
|
|
231
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
232
|
+
const profilePath = installer.getProfilePath();
|
|
233
|
+
|
|
234
|
+
await installer.configureProfile(mockScriptPath);
|
|
235
|
+
|
|
236
|
+
const content = await fs.readFile(profilePath, 'utf-8');
|
|
237
|
+
expect(content).toContain('# OPENSPEC:START');
|
|
238
|
+
expect(content).toContain(`. "${mockScriptPath}"`);
|
|
239
|
+
expect(content).toContain('# OPENSPEC:END');
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// Skip on Windows: fs.chmod() doesn't reliably restrict write access on Windows
|
|
243
|
+
// (admin users can bypass read-only attribute, and CI runners often have elevated privileges)
|
|
244
|
+
it.skipIf(process.platform === 'win32')('should return false on write permission error', async () => {
|
|
245
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
246
|
+
const profilePath = installer.getProfilePath();
|
|
247
|
+
await fs.mkdir(path.dirname(profilePath), { recursive: true });
|
|
248
|
+
await fs.writeFile(profilePath, '# Test');
|
|
249
|
+
|
|
250
|
+
// Make file read-only
|
|
251
|
+
await fs.chmod(profilePath, 0o444);
|
|
252
|
+
|
|
253
|
+
const result = await installer.configureProfile(mockScriptPath);
|
|
254
|
+
|
|
255
|
+
// Restore permissions for cleanup
|
|
256
|
+
await fs.chmod(profilePath, 0o644);
|
|
257
|
+
|
|
258
|
+
expect(result).toBe(false);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
describe('removeProfileConfig', () => {
|
|
263
|
+
it('should return false when profile does not exist', async () => {
|
|
264
|
+
const result = await installer.removeProfileConfig();
|
|
265
|
+
expect(result).toBe(false);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it('should return false when profile exists but has no markers', async () => {
|
|
269
|
+
const profilePath = installer.getProfilePath();
|
|
270
|
+
await fs.mkdir(path.dirname(profilePath), { recursive: true });
|
|
271
|
+
await fs.writeFile(profilePath, '# My custom config\nWrite-Host "Hello"');
|
|
272
|
+
|
|
273
|
+
const result = await installer.removeProfileConfig();
|
|
274
|
+
|
|
275
|
+
expect(result).toBe(false);
|
|
276
|
+
const content = await fs.readFile(profilePath, 'utf-8');
|
|
277
|
+
expect(content).toBe('# My custom config\nWrite-Host "Hello"');
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it('should remove content between markers', async () => {
|
|
281
|
+
const profilePath = installer.getProfilePath();
|
|
282
|
+
await fs.mkdir(path.dirname(profilePath), { recursive: true });
|
|
283
|
+
|
|
284
|
+
const initialContent = [
|
|
285
|
+
'# OPENSPEC:START',
|
|
286
|
+
'# OpenSpec completions',
|
|
287
|
+
'if (Test-Path "/path") {',
|
|
288
|
+
' . "/path"',
|
|
289
|
+
'}',
|
|
290
|
+
'# OPENSPEC:END',
|
|
291
|
+
'',
|
|
292
|
+
'# My config',
|
|
293
|
+
].join('\n');
|
|
294
|
+
|
|
295
|
+
await fs.writeFile(profilePath, initialContent);
|
|
296
|
+
|
|
297
|
+
const result = await installer.removeProfileConfig();
|
|
298
|
+
|
|
299
|
+
expect(result).toBe(true);
|
|
300
|
+
const content = await fs.readFile(profilePath, 'utf-8');
|
|
301
|
+
expect(content).not.toContain('# OPENSPEC:START');
|
|
302
|
+
expect(content).not.toContain('# OPENSPEC:END');
|
|
303
|
+
expect(content).not.toContain('# OpenSpec completions');
|
|
304
|
+
expect(content).toContain('# My config');
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('should remove trailing empty lines after removal', async () => {
|
|
308
|
+
const profilePath = installer.getProfilePath();
|
|
309
|
+
await fs.mkdir(path.dirname(profilePath), { recursive: true });
|
|
310
|
+
|
|
311
|
+
const initialContent = [
|
|
312
|
+
'# User config',
|
|
313
|
+
'# OPENSPEC:START',
|
|
314
|
+
'# Config',
|
|
315
|
+
'# OPENSPEC:END',
|
|
316
|
+
'',
|
|
317
|
+
'',
|
|
318
|
+
].join('\n');
|
|
319
|
+
|
|
320
|
+
await fs.writeFile(profilePath, initialContent);
|
|
321
|
+
|
|
322
|
+
const result = await installer.removeProfileConfig();
|
|
323
|
+
|
|
324
|
+
expect(result).toBe(true);
|
|
325
|
+
const content = await fs.readFile(profilePath, 'utf-8');
|
|
326
|
+
expect(content).toBe('# User config\n');
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
it('should preserve user content outside markers', async () => {
|
|
330
|
+
const profilePath = installer.getProfilePath();
|
|
331
|
+
await fs.mkdir(path.dirname(profilePath), { recursive: true });
|
|
332
|
+
|
|
333
|
+
const initialContent = [
|
|
334
|
+
'# Before',
|
|
335
|
+
'# OPENSPEC:START',
|
|
336
|
+
'# OpenSpec',
|
|
337
|
+
'# OPENSPEC:END',
|
|
338
|
+
'# After',
|
|
339
|
+
].join('\n');
|
|
340
|
+
|
|
341
|
+
await fs.writeFile(profilePath, initialContent);
|
|
342
|
+
|
|
343
|
+
const result = await installer.removeProfileConfig();
|
|
344
|
+
|
|
345
|
+
expect(result).toBe(true);
|
|
346
|
+
const content = await fs.readFile(profilePath, 'utf-8');
|
|
347
|
+
expect(content).toContain('# Before');
|
|
348
|
+
expect(content).toContain('# After');
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
it('should return false on invalid marker placement', async () => {
|
|
352
|
+
const profilePath = installer.getProfilePath();
|
|
353
|
+
await fs.mkdir(path.dirname(profilePath), { recursive: true });
|
|
354
|
+
|
|
355
|
+
const initialContent = [
|
|
356
|
+
'# OPENSPEC:END',
|
|
357
|
+
'# Config',
|
|
358
|
+
'# OPENSPEC:START',
|
|
359
|
+
].join('\n');
|
|
360
|
+
|
|
361
|
+
await fs.writeFile(profilePath, initialContent);
|
|
362
|
+
|
|
363
|
+
const result = await installer.removeProfileConfig();
|
|
364
|
+
|
|
365
|
+
expect(result).toBe(false);
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
describe('install', () => {
|
|
370
|
+
const mockCompletionScript = `# PowerShell completion script for OpenSpec
|
|
371
|
+
$openspecCompleter = {
|
|
372
|
+
param($wordToComplete, $commandAst, $cursorPosition)
|
|
373
|
+
# Completion logic here
|
|
374
|
+
}
|
|
375
|
+
Register-ArgumentCompleter -CommandName openspec -ScriptBlock $openspecCompleter
|
|
376
|
+
`;
|
|
377
|
+
|
|
378
|
+
it('should install completion script for the first time', async () => {
|
|
379
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
380
|
+
const result = await installer.install(mockCompletionScript);
|
|
381
|
+
|
|
382
|
+
expect(result.success).toBe(true);
|
|
383
|
+
expect(result.message).toContain('installed');
|
|
384
|
+
expect(result.installedPath).toContain('OpenSpecCompletion.ps1');
|
|
385
|
+
expect(result.backupPath).toBeUndefined();
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
it('should create parent directories if they do not exist', async () => {
|
|
389
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
390
|
+
const result = await installer.install(mockCompletionScript);
|
|
391
|
+
|
|
392
|
+
expect(result.success).toBe(true);
|
|
393
|
+
const targetPath = installer.getInstallationPath();
|
|
394
|
+
const fileExists = await fs.access(targetPath).then(() => true).catch(() => false);
|
|
395
|
+
expect(fileExists).toBe(true);
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
it('should write completion script content correctly', async () => {
|
|
399
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
400
|
+
await installer.install(mockCompletionScript);
|
|
401
|
+
|
|
402
|
+
const targetPath = installer.getInstallationPath();
|
|
403
|
+
const content = await fs.readFile(targetPath, 'utf-8');
|
|
404
|
+
expect(content).toBe(mockCompletionScript);
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
it('should detect when already installed with same content', async () => {
|
|
408
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
409
|
+
await installer.install(mockCompletionScript);
|
|
410
|
+
|
|
411
|
+
const result = await installer.install(mockCompletionScript);
|
|
412
|
+
|
|
413
|
+
expect(result.success).toBe(true);
|
|
414
|
+
expect(result.message).toBe('Completion script is already installed (up to date)');
|
|
415
|
+
expect(result.backupPath).toBeUndefined();
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
it('should update when content is different', async () => {
|
|
419
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
420
|
+
await installer.install(mockCompletionScript);
|
|
421
|
+
|
|
422
|
+
const updatedScript = mockCompletionScript + '\n# Updated version';
|
|
423
|
+
const result = await installer.install(updatedScript);
|
|
424
|
+
|
|
425
|
+
expect(result.success).toBe(true);
|
|
426
|
+
expect(result.message).toContain('updated successfully');
|
|
427
|
+
expect(result.backupPath).toBeDefined();
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
it('should create backup when updating existing installation', async () => {
|
|
431
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
432
|
+
await installer.install(mockCompletionScript);
|
|
433
|
+
|
|
434
|
+
const updatedScript = mockCompletionScript + '\n# Updated';
|
|
435
|
+
const result = await installer.install(updatedScript);
|
|
436
|
+
|
|
437
|
+
expect(result.success).toBe(true);
|
|
438
|
+
expect(result.backupPath).toBeDefined();
|
|
439
|
+
|
|
440
|
+
// Verify backup contains original content
|
|
441
|
+
const backupContent = await fs.readFile(result.backupPath!, 'utf-8');
|
|
442
|
+
expect(backupContent).toBe(mockCompletionScript);
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
it('should configure PowerShell profile when not disabled', async () => {
|
|
446
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
447
|
+
const result = await installer.install(mockCompletionScript);
|
|
448
|
+
|
|
449
|
+
expect(result.success).toBe(true);
|
|
450
|
+
expect(result.profileConfigured).toBe(true);
|
|
451
|
+
expect(result.message).toContain('profile configured');
|
|
452
|
+
expect(result.instructions).toBeUndefined();
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
// Note: OPENSPEC_NO_AUTO_CONFIG support was removed from PowerShell installer
|
|
456
|
+
// Profile is now always auto-configured if possible
|
|
457
|
+
|
|
458
|
+
// Skip on Windows: fs.chmod() doesn't reliably restrict write access on Windows
|
|
459
|
+
// (admin users can bypass read-only attribute, and CI runners often have elevated privileges)
|
|
460
|
+
it.skipIf(process.platform === 'win32')('should provide instructions when profile cannot be configured', async () => {
|
|
461
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
462
|
+
// Make profile directory read-only to prevent configuration
|
|
463
|
+
const profilePath = installer.getProfilePath();
|
|
464
|
+
await fs.mkdir(path.dirname(profilePath), { recursive: true });
|
|
465
|
+
await fs.writeFile(profilePath, '# Test');
|
|
466
|
+
await fs.chmod(profilePath, 0o444);
|
|
467
|
+
|
|
468
|
+
const result = await installer.install(mockCompletionScript);
|
|
469
|
+
|
|
470
|
+
// Restore permissions
|
|
471
|
+
await fs.chmod(profilePath, 0o644);
|
|
472
|
+
|
|
473
|
+
expect(result.success).toBe(true);
|
|
474
|
+
expect(result.profileConfigured).toBe(false);
|
|
475
|
+
expect(result.instructions).toBeDefined();
|
|
476
|
+
expect(result.instructions!.some(i => i.includes('Test-Path'))).toBe(true);
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
it('should include backup path in message when updating', async () => {
|
|
480
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
481
|
+
await installer.install(mockCompletionScript);
|
|
482
|
+
|
|
483
|
+
const updatedScript = mockCompletionScript + '\n# Updated';
|
|
484
|
+
const result = await installer.install(updatedScript);
|
|
485
|
+
|
|
486
|
+
expect(result.success).toBe(true);
|
|
487
|
+
expect(result.message).toContain('backed up');
|
|
488
|
+
expect(result.backupPath).toBeDefined();
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
it('should handle installation with paths containing spaces', async () => {
|
|
492
|
+
const spacedHomeDir = path.join(os.tmpdir(), `openspec powershell test ${randomUUID()}`);
|
|
493
|
+
await fs.mkdir(spacedHomeDir, { recursive: true });
|
|
494
|
+
|
|
495
|
+
const spacedInstaller = new PowerShellInstaller(spacedHomeDir);
|
|
496
|
+
const result = await spacedInstaller.install(mockCompletionScript);
|
|
497
|
+
|
|
498
|
+
expect(result.success).toBe(true);
|
|
499
|
+
expect(result.installedPath).toContain('openspec powershell test');
|
|
500
|
+
|
|
501
|
+
// Cleanup
|
|
502
|
+
await fs.rm(spacedHomeDir, { recursive: true, force: true });
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
// Skip on Windows: fs.chmod() on directories doesn't restrict write access on Windows
|
|
506
|
+
// Windows uses ACLs which Node.js chmod doesn't control
|
|
507
|
+
it.skipIf(process.platform === 'win32')('should return failure on permission error', async () => {
|
|
508
|
+
const targetPath = installer.getInstallationPath();
|
|
509
|
+
const targetDir = path.dirname(targetPath);
|
|
510
|
+
await fs.mkdir(targetDir, { recursive: true });
|
|
511
|
+
|
|
512
|
+
// Make target directory read-only to simulate permission error
|
|
513
|
+
await fs.chmod(targetDir, 0o444);
|
|
514
|
+
|
|
515
|
+
const result = await installer.install(mockCompletionScript);
|
|
516
|
+
|
|
517
|
+
// Restore permissions for cleanup
|
|
518
|
+
await fs.chmod(targetDir, 0o755);
|
|
519
|
+
|
|
520
|
+
expect(result.success).toBe(false);
|
|
521
|
+
expect(result.message).toContain('Failed to install completion script');
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
it('should handle empty completion script', async () => {
|
|
525
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
526
|
+
const result = await installer.install('');
|
|
527
|
+
|
|
528
|
+
expect(result.success).toBe(true);
|
|
529
|
+
const targetPath = installer.getInstallationPath();
|
|
530
|
+
const content = await fs.readFile(targetPath, 'utf-8');
|
|
531
|
+
expect(content).toBe('');
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
it('should handle completion script with special characters', async () => {
|
|
535
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
536
|
+
const specialScript = `# PowerShell with special chars: ' " \` $ @\n$test = "value"`;
|
|
537
|
+
|
|
538
|
+
const result = await installer.install(specialScript);
|
|
539
|
+
|
|
540
|
+
expect(result.success).toBe(true);
|
|
541
|
+
const targetPath = installer.getInstallationPath();
|
|
542
|
+
const content = await fs.readFile(targetPath, 'utf-8');
|
|
543
|
+
expect(content).toBe(specialScript);
|
|
544
|
+
});
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
describe('encoding preservation', () => {
|
|
548
|
+
const mockScriptPath = '/path/to/OpenSpecCompletion.ps1';
|
|
549
|
+
const utf16leBom = Buffer.from([0xff, 0xfe]);
|
|
550
|
+
const utf8Bom = Buffer.from([0xef, 0xbb, 0xbf]);
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Helper: write a file in UTF-16 LE with BOM, the way Windows PowerShell does.
|
|
554
|
+
*/
|
|
555
|
+
function writeUtf16LeFile(filePath: string, text: string): Promise<void> {
|
|
556
|
+
const body = Buffer.from(text, 'utf16le');
|
|
557
|
+
return fs.writeFile(filePath, Buffer.concat([utf16leBom, body]));
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Helper: write a file in UTF-8 with BOM.
|
|
562
|
+
*/
|
|
563
|
+
function writeUtf8BomFile(filePath: string, text: string): Promise<void> {
|
|
564
|
+
const body = Buffer.from(text, 'utf-8');
|
|
565
|
+
return fs.writeFile(filePath, Buffer.concat([utf8Bom, body]));
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
it('should preserve UTF-16 LE BOM when configuring profile', async () => {
|
|
569
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
570
|
+
const profilePath = installer.getProfilePath();
|
|
571
|
+
await fs.mkdir(path.dirname(profilePath), { recursive: true });
|
|
572
|
+
|
|
573
|
+
const originalText = '. "C:\\Code\\SystemConfig\\Powershell\\profile.ps1"\r\n';
|
|
574
|
+
await writeUtf16LeFile(profilePath, originalText);
|
|
575
|
+
|
|
576
|
+
const result = await installer.configureProfile(mockScriptPath);
|
|
577
|
+
expect(result).toBe(true);
|
|
578
|
+
|
|
579
|
+
// Read back raw bytes and verify BOM is preserved
|
|
580
|
+
const raw = await fs.readFile(profilePath);
|
|
581
|
+
expect(raw[0]).toBe(0xff);
|
|
582
|
+
expect(raw[1]).toBe(0xfe);
|
|
583
|
+
|
|
584
|
+
// Decode and verify content is intact
|
|
585
|
+
const content = raw.subarray(2).toString('utf16le');
|
|
586
|
+
expect(content).toContain('. "C:\\Code\\SystemConfig\\Powershell\\profile.ps1"');
|
|
587
|
+
expect(content).toContain('# OPENSPEC:START');
|
|
588
|
+
expect(content).toContain(`. "${mockScriptPath}"`);
|
|
589
|
+
expect(content).toContain('# OPENSPEC:END');
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
it('should preserve UTF-16 LE BOM when removing profile config', async () => {
|
|
593
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
594
|
+
const profilePath = installer.getProfilePath();
|
|
595
|
+
await fs.mkdir(path.dirname(profilePath), { recursive: true });
|
|
596
|
+
|
|
597
|
+
const textWithBlock = [
|
|
598
|
+
'. "C:\\Code\\profile.ps1"',
|
|
599
|
+
'# OPENSPEC:START',
|
|
600
|
+
'. "/path/to/OpenSpecCompletion.ps1"',
|
|
601
|
+
'# OPENSPEC:END',
|
|
602
|
+
'',
|
|
603
|
+
].join('\n');
|
|
604
|
+
await writeUtf16LeFile(profilePath, textWithBlock);
|
|
605
|
+
|
|
606
|
+
const result = await installer.removeProfileConfig();
|
|
607
|
+
expect(result).toBe(true);
|
|
608
|
+
|
|
609
|
+
// Verify BOM is preserved
|
|
610
|
+
const raw = await fs.readFile(profilePath);
|
|
611
|
+
expect(raw[0]).toBe(0xff);
|
|
612
|
+
expect(raw[1]).toBe(0xfe);
|
|
613
|
+
|
|
614
|
+
// Verify content: original line kept, OpenSpec block removed
|
|
615
|
+
const content = raw.subarray(2).toString('utf16le');
|
|
616
|
+
expect(content).toContain('. "C:\\Code\\profile.ps1"');
|
|
617
|
+
expect(content).not.toContain('# OPENSPEC:START');
|
|
618
|
+
expect(content).not.toContain('# OPENSPEC:END');
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
it('should preserve UTF-8 BOM when configuring profile', async () => {
|
|
622
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
623
|
+
const profilePath = installer.getProfilePath();
|
|
624
|
+
await fs.mkdir(path.dirname(profilePath), { recursive: true });
|
|
625
|
+
|
|
626
|
+
await writeUtf8BomFile(profilePath, '# My profile\n');
|
|
627
|
+
|
|
628
|
+
const result = await installer.configureProfile(mockScriptPath);
|
|
629
|
+
expect(result).toBe(true);
|
|
630
|
+
|
|
631
|
+
const raw = await fs.readFile(profilePath);
|
|
632
|
+
expect(raw[0]).toBe(0xef);
|
|
633
|
+
expect(raw[1]).toBe(0xbb);
|
|
634
|
+
expect(raw[2]).toBe(0xbf);
|
|
635
|
+
|
|
636
|
+
const content = raw.subarray(3).toString('utf-8');
|
|
637
|
+
expect(content).toContain('# My profile');
|
|
638
|
+
expect(content).toContain('# OPENSPEC:START');
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
it('should skip UTF-16 BE profile and leave it unchanged', async () => {
|
|
642
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
643
|
+
process.env.PROFILE = path.join(testHomeDir, 'custom-profile.ps1');
|
|
644
|
+
const profilePath = installer.getProfilePath();
|
|
645
|
+
await fs.mkdir(path.dirname(profilePath), { recursive: true });
|
|
646
|
+
|
|
647
|
+
// Write a fake UTF-16 BE file (FE FF BOM + some bytes)
|
|
648
|
+
const utf16beBom = Buffer.from([0xfe, 0xff]);
|
|
649
|
+
const body = Buffer.from([0x00, 0x23]); // '#' in UTF-16 BE
|
|
650
|
+
const originalBytes = Buffer.concat([utf16beBom, body]);
|
|
651
|
+
await fs.writeFile(profilePath, originalBytes);
|
|
652
|
+
|
|
653
|
+
const result = await installer.configureProfile(mockScriptPath);
|
|
654
|
+
expect(result).toBe(false);
|
|
655
|
+
|
|
656
|
+
// File should be untouched
|
|
657
|
+
const raw = await fs.readFile(profilePath);
|
|
658
|
+
expect(Buffer.compare(raw, originalBytes)).toBe(0);
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
it('should handle plain UTF-8 files without BOM (no regression)', async () => {
|
|
662
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
663
|
+
const profilePath = installer.getProfilePath();
|
|
664
|
+
await fs.mkdir(path.dirname(profilePath), { recursive: true });
|
|
665
|
+
|
|
666
|
+
await fs.writeFile(profilePath, '# Plain UTF-8\n', 'utf-8');
|
|
667
|
+
|
|
668
|
+
const result = await installer.configureProfile(mockScriptPath);
|
|
669
|
+
expect(result).toBe(true);
|
|
670
|
+
|
|
671
|
+
const raw = await fs.readFile(profilePath);
|
|
672
|
+
// Should NOT have any BOM
|
|
673
|
+
expect(raw[0]).not.toBe(0xff);
|
|
674
|
+
expect(raw[0]).not.toBe(0xfe);
|
|
675
|
+
expect(raw[0]).not.toBe(0xef);
|
|
676
|
+
|
|
677
|
+
const content = raw.toString('utf-8');
|
|
678
|
+
expect(content).toContain('# Plain UTF-8');
|
|
679
|
+
expect(content).toContain('# OPENSPEC:START');
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
it('should round-trip UTF-16 LE through install → uninstall without corruption', async () => {
|
|
683
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
684
|
+
const profilePath = installer.getProfilePath();
|
|
685
|
+
await fs.mkdir(path.dirname(profilePath), { recursive: true });
|
|
686
|
+
|
|
687
|
+
const originalText = '. "C:\\Code\\SystemConfig\\Powershell\\profile.ps1"\r\n';
|
|
688
|
+
await writeUtf16LeFile(profilePath, originalText);
|
|
689
|
+
|
|
690
|
+
// Install adds the OpenSpec block
|
|
691
|
+
const mockScript = '# completion script';
|
|
692
|
+
await installer.install(mockScript);
|
|
693
|
+
|
|
694
|
+
// Verify the profile was modified but encoding preserved
|
|
695
|
+
let raw = await fs.readFile(profilePath);
|
|
696
|
+
expect(raw[0]).toBe(0xff);
|
|
697
|
+
expect(raw[1]).toBe(0xfe);
|
|
698
|
+
let content = raw.subarray(2).toString('utf16le');
|
|
699
|
+
expect(content).toContain('# OPENSPEC:START');
|
|
700
|
+
expect(content).toContain(originalText.trimEnd());
|
|
701
|
+
|
|
702
|
+
// Uninstall removes the OpenSpec block
|
|
703
|
+
await installer.uninstall();
|
|
704
|
+
|
|
705
|
+
raw = await fs.readFile(profilePath);
|
|
706
|
+
expect(raw[0]).toBe(0xff);
|
|
707
|
+
expect(raw[1]).toBe(0xfe);
|
|
708
|
+
content = raw.subarray(2).toString('utf16le');
|
|
709
|
+
expect(content).not.toContain('# OPENSPEC:START');
|
|
710
|
+
expect(content).toContain('. "C:\\Code\\SystemConfig\\Powershell\\profile.ps1"');
|
|
711
|
+
});
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
describe('uninstall', () => {
|
|
715
|
+
const mockCompletionScript = `# PowerShell completion script
|
|
716
|
+
$openspecCompleter = {}
|
|
717
|
+
Register-ArgumentCompleter -CommandName openspec -ScriptBlock $openspecCompleter
|
|
718
|
+
`;
|
|
719
|
+
|
|
720
|
+
it('should successfully uninstall when completion script exists', async () => {
|
|
721
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
722
|
+
await installer.install(mockCompletionScript);
|
|
723
|
+
|
|
724
|
+
const result = await installer.uninstall();
|
|
725
|
+
|
|
726
|
+
expect(result.success).toBe(true);
|
|
727
|
+
expect(result.message).toBe('Completion script uninstalled successfully');
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
it('should remove the completion file', async () => {
|
|
731
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
732
|
+
await installer.install(mockCompletionScript);
|
|
733
|
+
const targetPath = installer.getInstallationPath();
|
|
734
|
+
|
|
735
|
+
await installer.uninstall();
|
|
736
|
+
|
|
737
|
+
const fileExists = await fs.access(targetPath).then(() => true).catch(() => false);
|
|
738
|
+
expect(fileExists).toBe(false);
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
it('should remove profile configuration', async () => {
|
|
742
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
743
|
+
await installer.install(mockCompletionScript);
|
|
744
|
+
const profilePath = installer.getProfilePath();
|
|
745
|
+
|
|
746
|
+
await installer.uninstall();
|
|
747
|
+
|
|
748
|
+
const content = await fs.readFile(profilePath, 'utf-8');
|
|
749
|
+
expect(content).not.toContain('# OPENSPEC:START');
|
|
750
|
+
expect(content).not.toContain('# OPENSPEC:END');
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
it('should return failure when completion script is not installed', async () => {
|
|
754
|
+
const result = await installer.uninstall();
|
|
755
|
+
|
|
756
|
+
expect(result.success).toBe(false);
|
|
757
|
+
expect(result.message).toBe('Completion script is not installed');
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
it('should accept yes option parameter', async () => {
|
|
761
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
762
|
+
await installer.install(mockCompletionScript);
|
|
763
|
+
|
|
764
|
+
const result = await installer.uninstall({ yes: true });
|
|
765
|
+
|
|
766
|
+
expect(result.success).toBe(true);
|
|
767
|
+
expect(result.message).toBe('Completion script uninstalled successfully');
|
|
768
|
+
});
|
|
769
|
+
|
|
770
|
+
it('should handle both script and config removal', async () => {
|
|
771
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
772
|
+
await installer.install(mockCompletionScript);
|
|
773
|
+
|
|
774
|
+
const targetPath = installer.getInstallationPath();
|
|
775
|
+
const profilePath = installer.getProfilePath();
|
|
776
|
+
|
|
777
|
+
// Verify both exist
|
|
778
|
+
const scriptExists = await fs.access(targetPath).then(() => true).catch(() => false);
|
|
779
|
+
const profileContent = await fs.readFile(profilePath, 'utf-8');
|
|
780
|
+
expect(scriptExists).toBe(true);
|
|
781
|
+
expect(profileContent).toContain('# OPENSPEC:START');
|
|
782
|
+
|
|
783
|
+
await installer.uninstall();
|
|
784
|
+
|
|
785
|
+
// Verify both are removed/cleaned
|
|
786
|
+
const scriptExistsAfter = await fs.access(targetPath).then(() => true).catch(() => false);
|
|
787
|
+
const profileContentAfter = await fs.readFile(profilePath, 'utf-8');
|
|
788
|
+
expect(scriptExistsAfter).toBe(false);
|
|
789
|
+
expect(profileContentAfter).not.toContain('# OPENSPEC:START');
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
// Skip on Windows: fs.chmod() on directories doesn't restrict write access on Windows
|
|
793
|
+
// Windows uses ACLs which Node.js chmod doesn't control
|
|
794
|
+
it.skipIf(process.platform === 'win32')('should return failure on permission error', async () => {
|
|
795
|
+
delete process.env.OPENSPEC_NO_AUTO_CONFIG;
|
|
796
|
+
await installer.install(mockCompletionScript);
|
|
797
|
+
const targetPath = installer.getInstallationPath();
|
|
798
|
+
const parentDir = path.dirname(targetPath);
|
|
799
|
+
|
|
800
|
+
// Make parent directory read-only
|
|
801
|
+
await fs.chmod(parentDir, 0o444);
|
|
802
|
+
const result = await installer.uninstall();
|
|
803
|
+
|
|
804
|
+
// Restore permissions
|
|
805
|
+
await fs.chmod(parentDir, 0o755);
|
|
806
|
+
|
|
807
|
+
// On some systems, the access check fails which returns "not installed"
|
|
808
|
+
// On others, the unlink fails which returns "Failed to uninstall"
|
|
809
|
+
expect(result.success).toBe(false);
|
|
810
|
+
expect(
|
|
811
|
+
result.message === 'Completion script is not installed' ||
|
|
812
|
+
result.message.includes('Failed to uninstall completion script')
|
|
813
|
+
).toBe(true);
|
|
814
|
+
});
|
|
815
|
+
|
|
816
|
+
it('should handle uninstall when parent directory does not exist', async () => {
|
|
817
|
+
const result = await installer.uninstall();
|
|
818
|
+
|
|
819
|
+
expect(result.success).toBe(false);
|
|
820
|
+
expect(result.message).toBe('Completion script is not installed');
|
|
821
|
+
});
|
|
822
|
+
});
|
|
823
|
+
|
|
824
|
+
});
|