@caddis/cli 0.3.0 → 0.4.1
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/bundles/antigravity-plugin/agents/knowledge-transfer.md +17 -32
- package/bundles/antigravity-plugin/caddis_statusline.py +25 -3
- package/bundles/antigravity-plugin/guard_agy.py +41 -9
- package/bundles/antigravity-plugin/plugin.json +1 -1
- package/bundles/antigravity-plugin/scripts/caddis_inventory.py +73 -3
- package/bundles/antigravity-plugin/scripts/caddis_statusline.py +25 -3
- package/bundles/antigravity-plugin/scripts/check_doc_coverage.py +1 -1
- package/bundles/antigravity-plugin/scripts/claudster_config.py +0 -5
- package/bundles/antigravity-plugin/scripts/hook_log.py +1 -1
- package/bundles/antigravity-plugin/scripts/new-machine.ps1 +170 -0
- package/bundles/antigravity-plugin/scripts/oss_ask.py +1 -1
- package/bundles/antigravity-plugin/scripts/oss_model.py +10 -2
- package/bundles/antigravity-plugin/scripts/oss_review.py +1 -1
- package/bundles/antigravity-plugin/scripts/setup_project_ai.py +42 -10
- package/bundles/antigravity-plugin/session_end_agy.py +31 -6
- package/bundles/antigravity-plugin/skills/_registry.md +1 -0
- package/bundles/antigravity-plugin/skills/advisory-hub/SKILL.md +44 -0
- package/bundles/antigravity-plugin/skills/code-review/SKILL.md +11 -0
- package/bundles/antigravity-plugin/skills/feature-plan/SKILL.md +21 -0
- package/bundles/antigravity-plugin/skills/gate-review/SKILL.md +11 -0
- package/bundles/antigravity-plugin/skills/implement/SKILL.md +36 -0
- package/bundles/antigravity-plugin/skills/safe-cleanup/SKILL.md +186 -0
- package/bundles/antigravity-plugin/skills/security-review/SKILL.md +9 -0
- package/bundles/antigravity-plugin/skills/validate-phase/SKILL.md +31 -0
- package/bundles/antigravity-plugin/warm_start_agy.py +96 -9
- package/bundles/antigravity-plugin-extras/plugin.json +1 -1
- package/bundles/antigravity-plugin-extras/skills/_registry.md +1 -0
- package/bundles/antigravity-plugin-extras/skills/safe-cleanup/SKILL.md +186 -0
- package/bundles/codex/.codex/config.toml.example +36 -0
- package/bundles/codex/.codex/skills/coding/api-design/SKILL.md +249 -0
- package/bundles/codex/.codex/skills/coding/backend-development/SKILL.md +305 -0
- package/bundles/codex/.codex/skills/coding/code-review/SKILL.md +140 -0
- package/bundles/codex/.codex/skills/coding/codebase-audit/SKILL.md +204 -0
- package/bundles/codex/.codex/skills/coding/dashboard-perf-sweep/SKILL.md +132 -0
- package/bundles/codex/.codex/skills/coding/dashboard-perf-sweep/scripts/perf_sweep.py +249 -0
- package/bundles/codex/.codex/skills/coding/error-handling/SKILL.md +260 -0
- package/bundles/codex/.codex/skills/coding/fastapi-dev/SKILL.md +300 -0
- package/bundles/codex/.codex/skills/coding/javascript-typescript/SKILL.md +142 -0
- package/bundles/codex/.codex/skills/coding/python/SKILL.md +388 -0
- package/bundles/codex/.codex/skills/coding/refactoring/SKILL.md +486 -0
- package/bundles/codex/.codex/skills/coding/security-review/SKILL.md +205 -0
- package/bundles/codex/.codex/skills/coding/sql/SKILL.md +321 -0
- package/bundles/codex/.codex/skills/data/database-design/SKILL.md +177 -0
- package/bundles/codex/.codex/skills/data/db-diagram/SKILL.md +148 -0
- package/bundles/codex/.codex/skills/data/db-diagram/scripts/sql_to_graph.py +1212 -0
- package/bundles/codex/.codex/skills/devops/ci-cd-pipeline/SKILL.md +315 -0
- package/bundles/codex/.codex/skills/devops/gh-cli/SKILL.md +195 -0
- package/bundles/codex/.codex/skills/devops/git-commit/SKILL.md +285 -0
- package/bundles/codex/.codex/skills/devops/safe-cleanup/SKILL.md +186 -0
- package/bundles/codex/.codex/skills/devops/using-git-worktrees/SKILL.md +217 -0
- package/bundles/codex/.codex/skills/devops/windows-deployment/SKILL.md +880 -0
- package/bundles/codex/.codex/skills/docs/code-documentation/SKILL.md +271 -0
- package/bundles/codex/.codex/skills/docs/explainer-doc/SKILL.md +97 -0
- package/bundles/codex/.codex/skills/docs/technical-writing/SKILL.md +286 -0
- package/bundles/codex/.codex/skills/docs/writing-plans/SKILL.md +387 -0
- package/bundles/codex/.codex/skills/frontend/css-architecture/SKILL.md +305 -0
- package/bundles/codex/.codex/skills/frontend/css-architecture/references/RESPONSIVE-DESIGN.md +604 -0
- package/bundles/codex/.codex/skills/frontend/frontend-design/SKILL.md +193 -0
- package/bundles/codex/.codex/skills/frontend/frontend-design/references/my-tech-stack.md +127 -0
- package/bundles/codex/.codex/skills/frontend/mockup/SKILL.md +242 -0
- package/bundles/codex/.codex/skills/frontend/react-best-practices/SKILL.md +269 -0
- package/bundles/codex/.codex/skills/frontend/react-dev/README.md +404 -0
- package/bundles/codex/.codex/skills/frontend/react-dev/SKILL.md +459 -0
- package/bundles/codex/.codex/skills/frontend/react-dev/examples/generic-components.md +579 -0
- package/bundles/codex/.codex/skills/frontend/react-dev/examples/server-components.md +579 -0
- package/bundles/codex/.codex/skills/frontend/react-dev/references/event-handlers.md +574 -0
- package/bundles/codex/.codex/skills/frontend/react-dev/references/hooks.md +456 -0
- package/bundles/codex/.codex/skills/frontend/react-dev/references/react-19-patterns.md +638 -0
- package/bundles/codex/.codex/skills/frontend/react-dev/references/react-router.md +1002 -0
- package/bundles/codex/.codex/skills/frontend/react-dev/references/tanstack-router.md +587 -0
- package/bundles/codex/.codex/skills/frontend/ui-review/SKILL.md +176 -0
- package/bundles/codex/.codex/skills/frontend/ui-review/references/framework-fixes.md +471 -0
- package/bundles/codex/.codex/skills/frontend/ui-review/references/visual-checklist.md +236 -0
- package/bundles/codex/.codex/skills/frontend/warm-editorial-ui/DESIGN_TOKENS.md +487 -0
- package/bundles/codex/.codex/skills/frontend/warm-editorial-ui/IMPLEMENTATION_GUIDE.md +177 -0
- package/bundles/codex/.codex/skills/frontend/warm-editorial-ui/SKILL.md +732 -0
- package/bundles/codex/.codex/skills/media/draw-io/SKILL.md +162 -0
- package/bundles/codex/.codex/skills/media/draw-io/references/aws-icons.md +677 -0
- package/bundles/codex/.codex/skills/media/draw-io/references/layout-guidelines.md +142 -0
- package/bundles/codex/.codex/skills/media/draw-io/references/troubleshooting.md +118 -0
- package/bundles/codex/.codex/skills/media/draw-io/references/workflows.md +103 -0
- package/bundles/codex/.codex/skills/media/draw-io/scripts/convert-drawio-to-png.sh +25 -0
- package/bundles/codex/.codex/skills/media/draw-io/scripts/find_aws_icon.py +79 -0
- package/bundles/codex/.codex/skills/media/mermaid-diagrams/SKILL.md +292 -0
- package/bundles/codex/.codex/skills/media/mermaid-diagrams/references/ENHANCEMENTS.md +264 -0
- package/bundles/codex/.codex/skills/media/mermaid-diagrams/references/MERMAID-SUMMARY.md +137 -0
- package/bundles/codex/.codex/skills/media/mermaid-diagrams/references/advanced-features.md +556 -0
- package/bundles/codex/.codex/skills/media/mermaid-diagrams/references/architecture-diagrams.md +192 -0
- package/bundles/codex/.codex/skills/media/mermaid-diagrams/references/c4-diagrams.md +410 -0
- package/bundles/codex/.codex/skills/media/mermaid-diagrams/references/class-diagrams.md +361 -0
- package/bundles/codex/.codex/skills/media/mermaid-diagrams/references/erd-diagrams.md +510 -0
- package/bundles/codex/.codex/skills/media/mermaid-diagrams/references/flowcharts.md +450 -0
- package/bundles/codex/.codex/skills/media/mermaid-diagrams/references/sequence-diagrams.md +394 -0
- package/bundles/codex/.codex/skills/media/mermaid-diagrams/references/troubleshooting.md +335 -0
- package/bundles/codex/.codex/skills/media/mermaid-diagrams/references/workflows.md +418 -0
- package/bundles/codex/.codex/skills/media/particle-art/SKILL.md +243 -0
- package/bundles/codex/.codex/skills/media/particle-art/references/canvas-utils.ts +171 -0
- package/bundles/codex/.codex/skills/media/particle-art/references/dot-field.template.tsx +203 -0
- package/bundles/codex/.codex/skills/media/particle-art/references/flow-field.template.tsx +263 -0
- package/bundles/codex/.codex/skills/media/particle-art/references/node-shape.template.tsx +261 -0
- package/bundles/codex/.codex/skills/media/particle-art/references/shape-sampler.ts +281 -0
- package/bundles/codex/.codex/skills/media/particle-art/references/stipple-morph.template.tsx +167 -0
- package/bundles/codex/.codex/skills/media/particle-art/references/stipple.template.tsx +175 -0
- package/bundles/codex/.codex/skills/media/particle-art/references/trail-ghost.template.tsx +266 -0
- package/bundles/codex/.codex/skills/media/particle-art/references/usage-examples.md +320 -0
- package/bundles/codex/.codex/skills/testing/playwright/API_REFERENCE.md +653 -0
- package/bundles/codex/.codex/skills/testing/playwright/SKILL.md +454 -0
- package/bundles/codex/.codex/skills/testing/playwright/lib/helpers.js +441 -0
- package/bundles/codex/.codex/skills/testing/playwright/package.json +26 -0
- package/bundles/codex/.codex/skills/testing/playwright/run.js +228 -0
- package/bundles/codex/.codex/skills/testing/tdd-workflow/SKILL.md +188 -0
- package/bundles/codex/.codex/skills/testing/test-strategy/SKILL.md +155 -0
- package/bundles/codex/.codex/skills/testing/webapp-testing/LICENSE.txt +202 -0
- package/bundles/codex/.codex/skills/testing/webapp-testing/SKILL.md +97 -0
- package/bundles/codex/.codex/skills/testing/webapp-testing/examples/console_logging.py +35 -0
- package/bundles/codex/.codex/skills/testing/webapp-testing/examples/element_discovery.py +40 -0
- package/bundles/codex/.codex/skills/testing/webapp-testing/examples/static_html_automation.py +33 -0
- package/bundles/codex/.codex/skills/testing/webapp-testing/scripts/with_server.py +106 -0
- package/bundles/codex/.codex/skills/workflow/advisory-hub/SKILL.md +227 -0
- package/bundles/codex/.codex/skills/workflow/advisory-hub/reference/context-template.md +214 -0
- package/bundles/codex/.codex/skills/workflow/advisory-hub/reference/hub-handbook.md +233 -0
- package/bundles/codex/.codex/skills/workflow/advisory-hub/reference/report-contract.md +94 -0
- package/bundles/codex/.codex/skills/workflow/advisory-hub/reference/succession.md +118 -0
- package/bundles/codex/.codex/skills/workflow/best-practices/SKILL.md +500 -0
- package/bundles/codex/.codex/skills/workflow/best-practices/agents/best-practices-referencer.md +263 -0
- package/bundles/codex/.codex/skills/workflow/best-practices/agents/codebase-context-builder.md +326 -0
- package/bundles/codex/.codex/skills/workflow/best-practices/agents/task-intent-analyzer.md +245 -0
- package/bundles/codex/.codex/skills/workflow/best-practices/references/anti-patterns.md +571 -0
- package/bundles/codex/.codex/skills/workflow/best-practices/references/before-after-examples.md +1114 -0
- package/bundles/codex/.codex/skills/workflow/best-practices/references/best-practices-guide.md +513 -0
- package/bundles/codex/.codex/skills/workflow/best-practices/references/common-workflows.md +692 -0
- package/bundles/codex/.codex/skills/workflow/best-practices/references/prompt-patterns.md +547 -0
- package/bundles/codex/.codex/skills/workflow/brainstorming/SKILL.md +57 -0
- package/bundles/codex/.codex/skills/workflow/context-curator/SKILL.md +157 -0
- package/bundles/codex/.codex/skills/workflow/golden-plan/SKILL.md +586 -0
- package/bundles/codex/.codex/skills/workflow/preflight/SKILL.md +440 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/LICENSE.txt +202 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/SKILL.md +491 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/agents/analyzer.md +274 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/agents/comparator.md +202 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/agents/grader.md +223 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/assets/eval_review.html +146 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/eval-viewer/generate_review.py +471 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/eval-viewer/viewer.html +1325 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/references/schemas.md +430 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/scripts/__init__.py +0 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/scripts/generate_report.py +326 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/scripts/improve_description.py +247 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/scripts/package_skill.py +136 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/scripts/quick_validate.py +103 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/scripts/run_eval.py +310 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/scripts/run_loop.py +328 -0
- package/bundles/codex/.codex/skills/workflow/skill-creator/scripts/utils.py +47 -0
- package/bundles/codex/AGENTS.md +146 -0
- package/bundles/manifest.json +4 -3
- package/dist/claude-deepseek.js +2 -2
- package/dist/claude-glm.js +2 -2
- package/dist/claude-oss.js +2 -2
- package/dist/cli.js +187 -56
- package/package.json +1 -1
- package/bundles/antigravity-plugin/scripts/dream_capture.py +0 -249
- package/bundles/antigravity-plugin/scripts/dream_memory.py +0 -438
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +0 -94
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Italiana-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Jura-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Lora-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +0 -93
- package/bundles/antigravity-plugin-extras/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
|
@@ -896,6 +896,7 @@ agent-log.jsonl
|
|
|
896
896
|
.last-usage-review
|
|
897
897
|
relay.md
|
|
898
898
|
relay/
|
|
899
|
+
session-state.md
|
|
899
900
|
PROJECT-FACTS.md
|
|
900
901
|
memory.jsonl
|
|
901
902
|
"""
|
|
@@ -941,11 +942,14 @@ allow = [
|
|
|
941
942
|
# # accepted back-compat alias for this key.
|
|
942
943
|
# ignore_routes = ["/health", "/__internal"] # routes intentionally left out of the page guide
|
|
943
944
|
|
|
944
|
-
# ── [
|
|
945
|
-
# [
|
|
946
|
-
#
|
|
947
|
-
#
|
|
948
|
-
#
|
|
945
|
+
# ── [handover] — what /caddis:handoff measures (scripts/caddis_inventory.py) ── LIVE ──
|
|
946
|
+
# [handover]
|
|
947
|
+
# test_cmd = "pytest tests/ -q" # THIS REPO'S test command. Without it the inventory
|
|
948
|
+
# # guesses `pytest` at the root, which is right in a
|
|
949
|
+
# # single-package repo and wrong in any repo carrying a
|
|
950
|
+
# # vendored or generated tree. Generated trees
|
|
951
|
+
# # (vscode-extensions/, dist/, node_modules/, .venv/) are
|
|
952
|
+
# # excluded automatically; set this when that is not enough.
|
|
949
953
|
"""
|
|
950
954
|
|
|
951
955
|
|
|
@@ -1128,12 +1132,13 @@ def scaffold_artifact_dir(target: Path, dry: bool) -> list[str]:
|
|
|
1128
1132
|
"""Create the harness-owned .caddis/ artifact tree + a default .gitignore + a config example.
|
|
1129
1133
|
|
|
1130
1134
|
Committed subdirs: plans, handoffs, agent-docs, prd, kb, prompts, comms. Transient state
|
|
1131
|
-
(reviews/*.html, usage-log.jsonl, .last-usage-review, relay*,
|
|
1132
|
-
is gitignored. .caddis/ is the default home for every working-artifact kind (Track A
|
|
1135
|
+
(reviews/*.html, usage-log.jsonl, .last-usage-review, relay*, session-state.md,
|
|
1136
|
+
PROJECT-FACTS.md, memory.jsonl) is gitignored. .caddis/ is the default home for every working-artifact kind (Track A
|
|
1133
1137
|
Phase A3) — kb/ and prompts/ round out plans/prd/agent-docs/reviews so nothing has to
|
|
1134
1138
|
scatter to the repo root or .github/. Also drops a documented `config.toml.example`
|
|
1135
|
-
(guard/doc_coverage
|
|
1136
|
-
|
|
1139
|
+
(guard/doc_coverage). Idempotent. An existing .caddis/.gitignore is never clobbered or
|
|
1140
|
+
reordered, but MISSING entries are appended — otherwise a repo set up before an entry
|
|
1141
|
+
existed would never receive it. The config example is left alone entirely.
|
|
1137
1142
|
|
|
1138
1143
|
Writes into the repo's `.caddis/`.
|
|
1139
1144
|
"""
|
|
@@ -1195,7 +1200,34 @@ def scaffold_artifact_dir(target: Path, dry: bool) -> list[str]:
|
|
|
1195
1200
|
notes.append(f"scaffold: wrote {label}/kb/environment-map.md")
|
|
1196
1201
|
gi = root / ".gitignore"
|
|
1197
1202
|
if gi.exists():
|
|
1198
|
-
|
|
1203
|
+
# APPEND what is missing rather than keeping the file frozen. The old behaviour was
|
|
1204
|
+
# "present -> kept", so a repo scaffolded before an entry was added NEVER received it.
|
|
1205
|
+
# That is not hypothetical: `session-state.md` is rewritten by the Stop hook on every
|
|
1206
|
+
# turn and contains the operator's verbatim words, and an already-scaffolded repo was
|
|
1207
|
+
# sitting one hook-fire away from committing it.
|
|
1208
|
+
#
|
|
1209
|
+
# Only ever adds; a line the user wrote themselves is never touched or reordered.
|
|
1210
|
+
try:
|
|
1211
|
+
existing = gi.read_text(encoding="utf-8")
|
|
1212
|
+
except OSError:
|
|
1213
|
+
existing = ""
|
|
1214
|
+
have = {ln.strip() for ln in existing.splitlines()}
|
|
1215
|
+
missing = [
|
|
1216
|
+
ln for ln in ARTIFACT_GITIGNORE.splitlines()
|
|
1217
|
+
if ln.strip() and not ln.startswith("#") and ln.strip() not in have
|
|
1218
|
+
]
|
|
1219
|
+
if not missing:
|
|
1220
|
+
notes.append(f"scaffold: {label}/.gitignore present — up to date")
|
|
1221
|
+
else:
|
|
1222
|
+
if not dry:
|
|
1223
|
+
block = "" if existing.endswith("\n") or not existing else "\n"
|
|
1224
|
+
block += "\n# added by caddis — newer transient artifacts\n"
|
|
1225
|
+
block += "\n".join(missing) + "\n"
|
|
1226
|
+
gi.write_text(existing + block, encoding="utf-8")
|
|
1227
|
+
notes.append(
|
|
1228
|
+
f"scaffold: {label}/.gitignore — added {len(missing)} missing entry(ies): "
|
|
1229
|
+
+ ", ".join(missing)
|
|
1230
|
+
)
|
|
1199
1231
|
else:
|
|
1200
1232
|
if not dry:
|
|
1201
1233
|
root.mkdir(parents=True, exist_ok=True)
|
|
@@ -41,16 +41,39 @@ def _hook_note(feature, exc, root=None):
|
|
|
41
41
|
except Exception:
|
|
42
42
|
pass
|
|
43
43
|
|
|
44
|
+
|
|
45
|
+
def _workspace_roots(data):
|
|
46
|
+
"""Every workspace root in the payload, as a list. Empty when the payload has none.
|
|
47
|
+
|
|
48
|
+
agy sends `workspacePaths` as a LIST. All three caddis agy hooks used to read
|
|
49
|
+
`workspacePaths[0]` and treat it as "the workspace" — silently, with no signal that a
|
|
50
|
+
choice had been made. In a single-root workspace that is correct and the behaviour here
|
|
51
|
+
is unchanged. In a MULTI-root workspace it is a coin toss: the hook acts on the first
|
|
52
|
+
root regardless of which one the session is actually working in.
|
|
53
|
+
|
|
54
|
+
Nothing on this machine is multi-root today, so this has never fired. It is a live trap
|
|
55
|
+
for exactly the multi-repo workspaces the leakage investigation was about, which is why
|
|
56
|
+
each caller below now handles the list rather than assuming its first element.
|
|
57
|
+
"""
|
|
58
|
+
roots = data.get("workspacePaths") if isinstance(data, dict) else None
|
|
59
|
+
if not isinstance(roots, list):
|
|
60
|
+
return []
|
|
61
|
+
return [str(r) for r in roots if isinstance(r, (str, bytes)) and str(r).strip()]
|
|
62
|
+
|
|
44
63
|
def main() -> None:
|
|
45
64
|
try:
|
|
46
65
|
data = json.load(sys.stdin)
|
|
47
66
|
except Exception:
|
|
48
67
|
data = {}
|
|
49
68
|
try:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
69
|
+
roots = _workspace_roots(data) or [os.getcwd()]
|
|
70
|
+
# Write the record to every root that ALREADY has a .caddis dir, rather than to
|
|
71
|
+
# whichever root happened to be first. A multi-root session's usage belongs to each
|
|
72
|
+
# repo that participates in it, and creating .caddis in a repo that never opted in
|
|
73
|
+
# would be caddis littering someone else's tree.
|
|
74
|
+
targets = [_artifact_root(r) for r in roots if os.path.isdir(_artifact_root(r))]
|
|
75
|
+
if not targets:
|
|
76
|
+
targets = [_artifact_root(roots[0])] # single-root default: unchanged behaviour
|
|
54
77
|
record = {
|
|
55
78
|
"ts": datetime.now(timezone.utc).isoformat(),
|
|
56
79
|
"event": "session_end",
|
|
@@ -60,8 +83,10 @@ def main() -> None:
|
|
|
60
83
|
"terminationReason": data.get("terminationReason"),
|
|
61
84
|
"model": data.get("modelName"),
|
|
62
85
|
}
|
|
63
|
-
|
|
64
|
-
|
|
86
|
+
for art in targets:
|
|
87
|
+
os.makedirs(art, exist_ok=True)
|
|
88
|
+
with open(os.path.join(art, "usage-log.jsonl"), "a", encoding="utf-8") as fh:
|
|
89
|
+
fh.write(json.dumps(record) + "\n")
|
|
65
90
|
except Exception as _exc:
|
|
66
91
|
_hook_note("agy usage-log write", _exc) # never fail the turn
|
|
67
92
|
# No stdout: agy interprets a Stop hook's stdout as a decision object.
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
| Ci Cd Pipeline | `ci-cd-pipeline/` | CI/CD pipeline design and implementation for GitHub Actions, Azure DevOps, and general pipeline architecture. Use when creating build pipelines, deployment workflows, quality gates, environment promotion strategies, or automating release processes. |
|
|
40
40
|
| Gh Cli | `gh-cli/` | GitHub CLI operations — issues, PRs, releases, and repo management |
|
|
41
41
|
| Git Commit | `git-commit/` | Create well-structured conventional commit messages following Conventional Commits standard. Use when committing changes, preparing PRs, or generating changelogs. |
|
|
42
|
+
| Safe Cleanup | `safe-cleanup/` | Use BEFORE deleting any directory tree, clearing a scratchpad, removing git worktrees, or "tidying up" generated folders - especially on Windows, where a recursive delete that meets a junction or symlink destroys the link's TARGET. Also use when verifying that a Python venv or node_modules survived a cleanup, because pip check and file counts both report healthy on a half-deleted environment. |
|
|
42
43
|
| Using Git Worktrees | `using-git-worktrees/` | Use when starting feature work that needs isolation from current workspace or before executing implementation plans - creates isolated git worktrees with smart directory selection and safety verification |
|
|
43
44
|
| Windows Deployment | `windows-deployment/` | Deploy FastAPI + React/Vite apps to Windows Server with NSSM services, reverse proxy (IIS or nginx), and git-pull workflow. Use when deploying any web app to a Windows prod server, setting up NSSM services, configuring IIS or nginx reverse proxy, making code environment-aware for dev/prod, or troubleshooting prod deployment issues. |
|
|
44
45
|
|
|
@@ -93,6 +93,50 @@ A three-phase feature hits none of this. `/caddis:feature-plan` Step 3b runs thi
|
|
|
93
93
|
it never creates the file silently. This is the test's only home — do not restate the thresholds
|
|
94
94
|
elsewhere, or the copies drift.
|
|
95
95
|
|
|
96
|
+
### Failing this test correctly does not mean "no discipline"
|
|
97
|
+
|
|
98
|
+
A plan can fail the test above — properly, no Hub needed — and still be multi-phase, multi-session,
|
|
99
|
+
and worth structuring. The trap is what happens next.
|
|
100
|
+
|
|
101
|
+
The Hub's file conventions are *attractive*. Once one plan in a repo runs in Hub mode, its
|
|
102
|
+
`phase-NN.prompt.md` / `phase-NN.report.md` / CONTINUE GATE artefacts are sitting right there as the
|
|
103
|
+
most recent example of "how we structure a multi-session plan here." A second, smaller plan copies
|
|
104
|
+
them by analogy. It gets the readability. It gets **none** of the safety, because the safety was
|
|
105
|
+
never in the file names — it was in the role split and the verdict gate.
|
|
106
|
+
|
|
107
|
+
That has happened. A six-phase UI plan borrowed the naming, and an implementing session filed its own
|
|
108
|
+
batch report **and then wrote the next batch's prompt in the same session**, with nobody having
|
|
109
|
+
looked at the work in between. Nothing was wrong that time. Nothing *checked*, either — and the good
|
|
110
|
+
outcome is not evidence the mechanism worked, it is evidence nothing tested it.
|
|
111
|
+
|
|
112
|
+
This skill already says why role separation is not decoration:
|
|
113
|
+
|
|
114
|
+
> *An implementer that writes its own verdict has produced a self-assessment wearing a verdict's
|
|
115
|
+
> name — worse than no verdict, because it looks like a check happened.*
|
|
116
|
+
|
|
117
|
+
The same sentence holds with two words changed: **an implementer that writes the next phase's
|
|
118
|
+
instructions** has produced a plan wearing an independently-authored prompt's name.
|
|
119
|
+
|
|
120
|
+
### The one lightweight rule — cheap enough to always afford
|
|
121
|
+
|
|
122
|
+
> **The session that files a phase's report must not also write the next phase's prompt without an
|
|
123
|
+
> independent re-check in between.**
|
|
124
|
+
|
|
125
|
+
That is the whole rule. It costs minutes, not a session:
|
|
126
|
+
|
|
127
|
+
- re-run the test suite rather than trusting the report's claim that it passed
|
|
128
|
+
- grep the source for the report's two or three load-bearing claims
|
|
129
|
+
- open one or two of the screenshots it describes, rather than reading its description of them
|
|
130
|
+
|
|
131
|
+
No switch file. No dedicated Hub session. No advisory-context doc. If the re-check finds nothing, you
|
|
132
|
+
have lost ten minutes; if it finds something, it found it *before* the wrong instruction went into a
|
|
133
|
+
fresh session that cannot know any better.
|
|
134
|
+
|
|
135
|
+
**State which one you are doing, in the plan.** A plan that borrows Hub file conventions should say
|
|
136
|
+
either "full Advisory Hub mode" or "Hub file conventions, lightweight re-check rule, no Hub" —
|
|
137
|
+
because a reader six phases later cannot tell the two apart from the artefacts alone. That is the
|
|
138
|
+
entire problem this section exists to prevent.
|
|
139
|
+
|
|
96
140
|
## Succession is not the same as a standing validator
|
|
97
141
|
|
|
98
142
|
Two things look alike from outside and are not:
|
|
@@ -8,6 +8,17 @@ license: Apache-2.0
|
|
|
8
8
|
|
|
9
9
|
# Code Review
|
|
10
10
|
|
|
11
|
+
> **On Claude Code, prefer the native `/code-review`.** It is a command, not a skill, so it always
|
|
12
|
+
> fires — including headless — and it has grown capabilities this one does not have: effort levels
|
|
13
|
+
> (`low`…`max`), an `ultra` mode that runs a multi-agent review in the cloud, `--comment` to post
|
|
14
|
+
> findings as inline PR comments, and `--fix` to apply them to the working tree. Reach for it first.
|
|
15
|
+
>
|
|
16
|
+
> This surface remains because caddis ships to harnesses that have **no** native equivalent — agy,
|
|
17
|
+
> Codex and Copilot. There it is the only review you get. Do not delete it to tidy up Claude Code.
|
|
18
|
+
>
|
|
19
|
+
> `/caddis:cross-review` is NOT replaced by either. It sends the diff to a **different vendor's**
|
|
20
|
+
> model, which neither this nor the native reviewer can do.
|
|
21
|
+
|
|
11
22
|
## Review Categories
|
|
12
23
|
|
|
13
24
|
### 1. Security Review
|
|
@@ -349,6 +349,27 @@ this. But **always record the determination in the plan, pass or fail**: one lin
|
|
|
349
349
|
> `Advisory Hub: not applicable — no REQUIRED trigger (not a migration / security change /
|
|
350
350
|
> production data correctness / numbers published to stakeholders).`
|
|
351
351
|
|
|
352
|
+
### If the test FAILS but this repo already runs a Hub for another plan
|
|
353
|
+
|
|
354
|
+
Check for an existing `*-advisory-context.md` in `.caddis/plans/` belonging to a **different** plan.
|
|
355
|
+
If one exists, add a second line under `## Constraints & decisions`:
|
|
356
|
+
|
|
357
|
+
> `Hub conventions: this repo runs Advisory Hub for <other-plan>. This plan does NOT — if it borrows
|
|
358
|
+
> the phase-NN.prompt.md / .report.md / CONTINUE GATE conventions, the lightweight rule applies: the
|
|
359
|
+
> session that files a report must not write the next prompt without an independent re-check.`
|
|
360
|
+
|
|
361
|
+
**Why this line exists.** A repo with one Hub plan has its artefacts sitting there as the most recent
|
|
362
|
+
example of "how we structure a multi-session plan here", and the next plan copies them by analogy.
|
|
363
|
+
It inherits the file names and none of the safety, because the safety was never in the names.
|
|
364
|
+
Measured once already: an implementing session filed its own batch report and then wrote the next
|
|
365
|
+
batch's prompt in the same session, with nobody having looked in between. Nothing was wrong that
|
|
366
|
+
time — and nothing checked either.
|
|
367
|
+
|
|
368
|
+
This is the cheapest possible place to catch it: when the second plan is created, before any
|
|
369
|
+
artefact-mimicry has happened. See *"Failing this test correctly does not mean no discipline"* in the
|
|
370
|
+
`advisory-hub` skill for the rule itself. Do not restate the rule here — one home, or the copies
|
|
371
|
+
drift.
|
|
372
|
+
|
|
352
373
|
Silent to the human, auditable in the artifact. "Say nothing" once meant *leave no trace anywhere*,
|
|
353
374
|
and a wrong negative was then invisible — no line in the plan, no line in the chat, nothing for
|
|
354
375
|
anyone to challenge. A rule whose failures leave no artifact cannot be reviewed.
|
|
@@ -5,6 +5,17 @@ description: Deterministic headless code review — adversarial diff review, sel
|
|
|
5
5
|
|
|
6
6
|
# /caddis:gate-review — headless adversarial code review (self-contained)
|
|
7
7
|
|
|
8
|
+
> **On Claude Code, prefer the native `/code-review`.** It is a command, not a skill, so it always
|
|
9
|
+
> fires — including headless — and it has grown capabilities this one does not have: effort levels
|
|
10
|
+
> (`low`…`max`), an `ultra` mode that runs a multi-agent review in the cloud, `--comment` to post
|
|
11
|
+
> findings as inline PR comments, and `--fix` to apply them to the working tree. Reach for it first.
|
|
12
|
+
>
|
|
13
|
+
> This surface remains because caddis ships to harnesses that have **no** native equivalent — agy,
|
|
14
|
+
> Codex and Copilot. There it is the only review you get. Do not delete it to tidy up Claude Code.
|
|
15
|
+
>
|
|
16
|
+
> `/caddis:cross-review` is NOT replaced by either. It sends the diff to a **different vendor's**
|
|
17
|
+
> model, which neither this nor the native reviewer can do.
|
|
18
|
+
|
|
8
19
|
Perform an adversarial code review of **$ARGUMENTS** (a git range, e.g. `abc123..HEAD` — defaults
|
|
9
20
|
to the current working diff when empty).
|
|
10
21
|
|
|
@@ -137,6 +137,42 @@ This is the Hub's central power and until now it ran on human discipline alone:
|
|
|
137
137
|
whether the next phase could start, and *nothing read it*. Five lines of check make the claim true by
|
|
138
138
|
machine.
|
|
139
139
|
|
|
140
|
+
### Ringing the Hub, and waiting for it (Claude Code only, optional)
|
|
141
|
+
|
|
142
|
+
Two moments in Advisory-Hub mode currently cost the user a copy-paste. Both are optional, both
|
|
143
|
+
degrade to today's behaviour, and neither replaces a file.
|
|
144
|
+
|
|
145
|
+
**After you file `phase-NN.report.md`** — if `ListAgents` is available, look for a peer session whose
|
|
146
|
+
name starts with **this repo's directory name**. Sessions are auto-named `<repo-dir>-<hash>`, so a
|
|
147
|
+
same-repo peer is the Hub:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
SendMessage({to: "<peer-name>", summary: "phase-05 report filed",
|
|
151
|
+
message: "phase-05.report.md is filed and awaiting a verdict."})
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**When you are BLOCKED on a verdict** — instead of stopping dead, subscribe once:
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
SendMessage({to: "<peer-name>", notify_when_idle: true,
|
|
158
|
+
message: "blocked on phase-05 verdict; ping me when you have written it"})
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
`notify_when_idle` is one-shot and costs the Hub nothing extra. **Never poll `ListAgents` in a loop,
|
|
162
|
+
and never send "are you done yet?"** — that burns both sessions' context to no purpose.
|
|
163
|
+
|
|
164
|
+
**The rules that keep this from becoming a mess:**
|
|
165
|
+
|
|
166
|
+
- **The file is the decision; the message is a doorbell.** Never treat a chat message as a verdict.
|
|
167
|
+
If a peer says "accepted", still read `phase-NN.verdict.md` — the gate above checks the FILE, and
|
|
168
|
+
a message cannot be re-read next week or by a third session.
|
|
169
|
+
- **No `ListAgents`, no peer, or more than one same-repo peer → do nothing and carry on.** caddis
|
|
170
|
+
also runs on agy and Codex, which have no cross-session messaging at all. Everything above is an
|
|
171
|
+
accelerant on one harness; the file protocol is the portable layer and is what actually works.
|
|
172
|
+
- **Headless runs never message.** There is no copy-paste to save.
|
|
173
|
+
- **Never ask a peer to perform work your own session was denied.** Permission boundaries are
|
|
174
|
+
per-session, and routing blocked work through another session launders the user's decision.
|
|
175
|
+
|
|
140
176
|
**If a `phase-NN.prompt.md` exists for the phase you are about to run, it is the INSTRUCTION OF
|
|
141
177
|
RECORD** — read it, and measure your DEVIATIONS against it, not against the plan alone. The Hub writes
|
|
142
178
|
that file before the phase precisely so a deviation is falsifiable; an executor that never reads it
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: safe-cleanup
|
|
3
|
+
description: Use BEFORE deleting any directory tree, clearing a scratchpad, removing git worktrees, or "tidying up" generated folders - especially on Windows, where a recursive delete that meets a junction or symlink destroys the link's TARGET. Also use when verifying that a Python venv or node_modules survived a cleanup, because pip check and file counts both report healthy on a half-deleted environment.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Safe Cleanup
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Cleanup looks like the safest thing you do all day. It is the most destructive.
|
|
11
|
+
|
|
12
|
+
This skill exists because of a real incident: an agent created 31 directory
|
|
13
|
+
junctions from throwaway worktrees into live repositories, unlinked them, saw
|
|
14
|
+
"31 unlinked, 0 failed", then recursively deleted the parent. A junction it had
|
|
15
|
+
never seen survived the scan, the delete followed it, and **five repositories'
|
|
16
|
+
development environments were destroyed**. Every verification afterwards said
|
|
17
|
+
"intact", because the verification was wrong too.
|
|
18
|
+
|
|
19
|
+
Two hours of repair. None of it would have happened with the rules below.
|
|
20
|
+
|
|
21
|
+
## The one-paragraph version
|
|
22
|
+
|
|
23
|
+
On Windows, `Remove-Item -Recurse` **follows junctions and deletes their
|
|
24
|
+
targets**. Enumerating with `-ErrorAction SilentlyContinue` hides the ones you
|
|
25
|
+
cannot read. And after the damage, `pip check`, `pip list` and file counts all
|
|
26
|
+
report success, because metadata survives while package files do not. So: never
|
|
27
|
+
link into somewhere real, never recurse through a link, prefer rename over
|
|
28
|
+
delete, and verify by *using* the thing rather than counting it.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## RULE 1 - Prefer rename over delete
|
|
33
|
+
|
|
34
|
+
Rename is atomic. Recursive delete is not: it can fail half way and leave a
|
|
35
|
+
directory that looks present and is unusable.
|
|
36
|
+
|
|
37
|
+
```powershell
|
|
38
|
+
Rename-Item -Path $target -NewName ".broken-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
In the incident, a venv holding `_greenlet.cp314-win_amd64.pyd` open **refused to
|
|
42
|
+
delete** but **renamed fine**. Had the delete been retried or forced, it would
|
|
43
|
+
have half-emptied the directory.
|
|
44
|
+
|
|
45
|
+
Rename first, build fresh alongside, delete the old copy later when nothing holds
|
|
46
|
+
it. Disk is cheap. An environment nobody can recover is not.
|
|
47
|
+
|
|
48
|
+
## RULE 2 - Never recurse a delete through a reparse point
|
|
49
|
+
|
|
50
|
+
Junctions and symlinks are transparent to `Remove-Item -Recurse`. Deleting a
|
|
51
|
+
folder that contains a link to `C:\live\thing` deletes **the contents of
|
|
52
|
+
`C:\live\thing`**.
|
|
53
|
+
|
|
54
|
+
Check first, and **fail if the check itself cannot complete**:
|
|
55
|
+
|
|
56
|
+
```powershell
|
|
57
|
+
$links = @(Get-ChildItem $path -Recurse -Force -Directory -ErrorAction Stop |
|
|
58
|
+
Where-Object { $_.Attributes -band [IO.FileAttributes]::ReparsePoint })
|
|
59
|
+
if ($links.Count) {
|
|
60
|
+
$links | ForEach-Object { Write-Host " $($_.FullName) -> $($_.Target)" }
|
|
61
|
+
throw "refusing: $($links.Count) link(s) inside $path"
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`-ErrorAction SilentlyContinue` on that scan is precisely what caused the
|
|
66
|
+
incident. A link inside a directory the scanner could not read was skipped in
|
|
67
|
+
silence and never appeared in the count. **A scan that cannot see everything must
|
|
68
|
+
fail, not shrug.**
|
|
69
|
+
|
|
70
|
+
To remove a link itself, unlink it - never delete through it:
|
|
71
|
+
|
|
72
|
+
```powershell
|
|
73
|
+
[System.IO.Directory]::Delete($linkPath, $false) # link only, never the target
|
|
74
|
+
cmd /c rmdir "$linkPath" # same effect
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## RULE 3 - Do not create links into live directories
|
|
78
|
+
|
|
79
|
+
The safest delete is the one with nothing to follow.
|
|
80
|
+
|
|
81
|
+
If a throwaway workspace needs dependencies, **build them there**, or point the
|
|
82
|
+
tool at an absolute interpreter path. Do not junction `<scratch>\.venv` to
|
|
83
|
+
`<live-repo>\.venv` for convenience - that is a loaded gun aimed at the repo, and
|
|
84
|
+
any cleanup above the link can fire it.
|
|
85
|
+
|
|
86
|
+
If you must link, remove the link the moment you are done, and never leave one
|
|
87
|
+
inside a directory that something else will clean up.
|
|
88
|
+
|
|
89
|
+
## RULE 4 - Verify by using, not by counting
|
|
90
|
+
|
|
91
|
+
After any cleanup near an environment, prove it still works. These all LIE on a
|
|
92
|
+
half-deleted Python venv, because dist-info metadata survives while package files
|
|
93
|
+
are removed:
|
|
94
|
+
|
|
95
|
+
| Check | Why it lies |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `Test-Path .venv\Scripts\python.exe` | Proves the interpreter exists. Says nothing about packages. |
|
|
98
|
+
| file or directory counts | Metadata directories inflate the count. |
|
|
99
|
+
| `pip list` | Reads metadata. |
|
|
100
|
+
| `pip check` | Reads metadata. Reported "No broken requirements found" on a venv that could not import fastapi. |
|
|
101
|
+
| `pip install -e .` | Reads metadata, calls the package satisfied, **skips it, and reports success**. |
|
|
102
|
+
|
|
103
|
+
The honest check is whether the interpreter can import what the project declares:
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
import importlib.util
|
|
107
|
+
importlib.util.find_spec("fastapi") is None # -> True means genuinely missing
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
For node, check that a real entry point resolves, not that `node_modules` exists.
|
|
111
|
+
|
|
112
|
+
**Map distribution names to import names.** `pyjwt` imports as `jwt`,
|
|
113
|
+
`python-ulid` as `ulid`, `python-dotenv` as `dotenv`. A naive audit produces false
|
|
114
|
+
positives and will have you rebuilding healthy environments - which is its own way
|
|
115
|
+
of causing an outage.
|
|
116
|
+
|
|
117
|
+
## RULE 5 - Stop what holds the files, or refuse
|
|
118
|
+
|
|
119
|
+
A running service turns a delete into a **partial** delete - the worst outcome.
|
|
120
|
+
|
|
121
|
+
Stop named services first. Then check for surviving processes and **refuse rather
|
|
122
|
+
than force**:
|
|
123
|
+
|
|
124
|
+
```powershell
|
|
125
|
+
$held = @(Get-CimInstance Win32_Process -Filter "Name='python.exe'" |
|
|
126
|
+
Where-Object { $_.ExecutablePath -like "$venv\*" })
|
|
127
|
+
if ($held.Count) { throw "refusing: still held by PID $($held[0].ProcessId)" }
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
In the incident's repair, this refused on one repo because a **VS Code language
|
|
131
|
+
server** had held that venv since the previous day. Not a service, not safe to
|
|
132
|
+
kill, not the script's business. That repo was fixed a different way. **Refusing
|
|
133
|
+
was correct.**
|
|
134
|
+
|
|
135
|
+
## RULE 6 - One agent at a time on a shared resource
|
|
136
|
+
|
|
137
|
+
Two agents installing into the same environment concurrently can produce exactly
|
|
138
|
+
this partial state. Three sessions were live in one repository during the
|
|
139
|
+
incident. Whoever is repairing says so; everyone else keeps out.
|
|
140
|
+
|
|
141
|
+
## RULE 7 - Verify against the source of truth, not the working copy
|
|
142
|
+
|
|
143
|
+
Checkouts go stale. During the same incident a subagent reported a file as absent
|
|
144
|
+
from a configuration, contradicting a change made hours earlier. The file was
|
|
145
|
+
present on `origin/main`; the working copy was **10 commits behind**.
|
|
146
|
+
|
|
147
|
+
Before asserting something is missing, check `git show origin/main:<path>`, not
|
|
148
|
+
the file on disk.
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Before you delete anything - the checklist
|
|
153
|
+
|
|
154
|
+
1. Can I **rename** instead? Do that.
|
|
155
|
+
2. Does the tree contain **reparse points**? Scan with `-ErrorAction Stop`. Refuse if any, or if the scan fails.
|
|
156
|
+
3. Does anything **hold files open**? Stop services; refuse on surviving processes.
|
|
157
|
+
4. Did I create any **links into live directories** earlier in this session? Unlink them explicitly, by name.
|
|
158
|
+
5. After: **verify by using**, not by counting.
|
|
159
|
+
6. If something looks wrong: check `origin/main`, not the working copy.
|
|
160
|
+
|
|
161
|
+
## What good verification output looks like
|
|
162
|
+
|
|
163
|
+
Not this:
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
.venv intact: True <- only proves python.exe exists
|
|
167
|
+
31 unlinked, 0 failed <- says nothing about what the scan missed
|
|
168
|
+
No broken requirements found <- reads metadata, not reality
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
This:
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
service-a OK declared=24 missing=0 <- every declared dep imported
|
|
175
|
+
service-b OK declared=19 missing=0
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Reference implementation
|
|
179
|
+
|
|
180
|
+
The estate this skill came from keeps working tools at `.caddis/tools/`:
|
|
181
|
+
|
|
182
|
+
- `venv-audit.py` - imports every dependency each `pyproject.toml` declares
|
|
183
|
+
- `rebuild-venv.ps1` - renames aside, rebuilds, restarts services, refuses on links or live processes
|
|
184
|
+
- `README-venv-safety.md` - the incident record
|
|
185
|
+
|
|
186
|
+
Adapt rather than copy: the rules matter more than the scripts.
|
|
@@ -6,6 +6,15 @@ description: "Security review workflow — OWASP, code scanning, cloud infrastru
|
|
|
6
6
|
|
|
7
7
|
# Security Review
|
|
8
8
|
|
|
9
|
+
> **On Claude Code, prefer the native `/security-review`.** It is a command, not a skill, so it always
|
|
10
|
+
> fires — including headless — and it has grown capabilities this one does not have: Reach for it first.
|
|
11
|
+
>
|
|
12
|
+
> This surface remains because caddis ships to harnesses that have **no** native equivalent — agy,
|
|
13
|
+
> Codex and Copilot. There it is the only review you get. Do not delete it to tidy up Claude Code.
|
|
14
|
+
>
|
|
15
|
+
> `/caddis:cross-review` is NOT replaced by either. It sends the diff to a **different vendor's**
|
|
16
|
+
> model, which neither this nor the native reviewer can do.
|
|
17
|
+
|
|
9
18
|
Security review workflow covering OWASP Top 10, code scanning, and cloud infrastructure.
|
|
10
19
|
|
|
11
20
|
## When to Use
|
|
@@ -98,6 +98,37 @@ step, not just described.
|
|
|
98
98
|
Add or update this phase's row in `.caddis/advisory-hub-reports/README.md` (Phase | Report | Verdict |
|
|
99
99
|
Outcome | Date).
|
|
100
100
|
|
|
101
|
+
## Step 8 — tell the implementing session (Claude Code only, optional)
|
|
102
|
+
|
|
103
|
+
The verdict file is the decision. This step only saves the user from carrying it by hand.
|
|
104
|
+
|
|
105
|
+
If `ListAgents` is available, look for a peer session whose name starts with **this repo's directory
|
|
106
|
+
name** — sessions are auto-named `<repo-dir>-<hash>`, so in a repo directory called `acme-api`,
|
|
107
|
+
`acme-api-91` is a session in this repo and `other-project-e8` is not. If exactly one such peer
|
|
108
|
+
exists, it is the implementer:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
SendMessage({to: "<peer-name>", summary: "phase-05 verdict",
|
|
112
|
+
message: "phase-05.verdict.md written — verdict: accept-with-correction. "
|
|
113
|
+
"Corrections are in the file and in advisory-context.md."})
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Send the **headline and the filename**, never the whole verdict. The file is the record; the message
|
|
117
|
+
is a doorbell. A chat message cannot be re-read next week; `phase-05.verdict.md` can.
|
|
118
|
+
|
|
119
|
+
**Do not do any of this if:**
|
|
120
|
+
|
|
121
|
+
- there is no `ListAgents` — caddis also runs on agy and Codex, which have no cross-session
|
|
122
|
+
messaging. The file-based flow is the portable one and works everywhere. This step is an
|
|
123
|
+
accelerant, not a requirement.
|
|
124
|
+
- **more than one** same-repo peer is listed. Guessing which is the implementer is worse than not
|
|
125
|
+
sending — say so to the user and let them name it.
|
|
126
|
+
- you are headless. There is no one to save a copy-paste for.
|
|
127
|
+
|
|
128
|
+
**Never ask the peer to run something your own session was denied.** Permission boundaries are
|
|
129
|
+
per-session; routing blocked work through another session launders the user's decision. Route it back
|
|
130
|
+
to the user instead.
|
|
131
|
+
|
|
101
132
|
## Rules
|
|
102
133
|
|
|
103
134
|
- **Fail closed.** A gate you could not re-run is `NOT RE-RUN`, never `PASS`. A claim you could not
|