@soleur/opencode 0.0.0-stage → 1.0.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/.claude-plugin/agents.manifest.json +476 -0
- package/.claude-plugin/plugin.json +42 -0
- package/README.md +44 -2
- package/agents/community/.gitkeep +0 -0
- package/agents/engineering/cto.md +87 -0
- package/agents/engineering/design/ddd-architect.md +95 -0
- package/agents/engineering/discovery/agent-finder.md +214 -0
- package/agents/engineering/discovery/functional-discovery.md +182 -0
- package/agents/engineering/infra/infra-security.md +151 -0
- package/agents/engineering/infra/platform-strategist.md +109 -0
- package/agents/engineering/infra/terraform-architect.md +171 -0
- package/agents/engineering/prompt-engineer.md +37 -0
- package/agents/engineering/research/best-practices-researcher.md +115 -0
- package/agents/engineering/research/framework-docs-researcher.md +93 -0
- package/agents/engineering/research/git-history-analyzer.md +53 -0
- package/agents/engineering/research/learnings-researcher.md +285 -0
- package/agents/engineering/research/repo-research-analyst.md +118 -0
- package/agents/engineering/review/agent-native-reviewer.md +279 -0
- package/agents/engineering/review/architecture-strategist.md +61 -0
- package/agents/engineering/review/code-quality-analyst.md +92 -0
- package/agents/engineering/review/code-simplicity-reviewer.md +109 -0
- package/agents/engineering/review/data-integrity-guardian.md +82 -0
- package/agents/engineering/review/data-migration-expert.md +98 -0
- package/agents/engineering/review/deployment-verification-agent.md +183 -0
- package/agents/engineering/review/dhh-rails-reviewer.md +46 -0
- package/agents/engineering/review/kieran-rails-reviewer.md +87 -0
- package/agents/engineering/review/legacy-code-expert.md +55 -0
- package/agents/engineering/review/observability-coverage-reviewer.md +147 -0
- package/agents/engineering/review/pattern-recognition-specialist.md +59 -0
- package/agents/engineering/review/performance-oracle.md +130 -0
- package/agents/engineering/review/security-sentinel.md +167 -0
- package/agents/engineering/review/semgrep-sast.md +36 -0
- package/agents/engineering/review/test-design-reviewer.md +150 -0
- package/agents/engineering/review/user-impact-reviewer.md +70 -0
- package/agents/engineering/workflow/pr-comment-resolver.md +69 -0
- package/agents/finance/budget-analyst.md +29 -0
- package/agents/finance/cfo.md +44 -0
- package/agents/finance/financial-reporter.md +30 -0
- package/agents/finance/revenue-analyst.md +30 -0
- package/agents/legal/clo.md +115 -0
- package/agents/legal/legal-compliance-auditor.md +110 -0
- package/agents/legal/legal-document-generator.md +134 -0
- package/agents/marketing/analytics-analyst.md +25 -0
- package/agents/marketing/brand-architect.md +181 -0
- package/agents/marketing/cmo.md +76 -0
- package/agents/marketing/conversion-optimizer.md +19 -0
- package/agents/marketing/copywriter.md +20 -0
- package/agents/marketing/fact-checker.md +70 -0
- package/agents/marketing/growth-strategist.md +145 -0
- package/agents/marketing/paid-media-strategist.md +28 -0
- package/agents/marketing/pricing-strategist.md +17 -0
- package/agents/marketing/programmatic-seo-specialist.md +25 -0
- package/agents/marketing/retention-strategist.md +23 -0
- package/agents/marketing/seo-aeo-analyst.md +164 -0
- package/agents/operations/coo.md +50 -0
- package/agents/operations/ops-advisor.md +78 -0
- package/agents/operations/ops-provisioner.md +101 -0
- package/agents/operations/ops-research.md +52 -0
- package/agents/operations/service-automator.md +278 -0
- package/agents/product/business-validator.md +206 -0
- package/agents/product/competitive-intelligence.md +89 -0
- package/agents/product/cpo.md +63 -0
- package/agents/product/design/ux-design-lead.md +209 -0
- package/agents/product/spec-flow-analyzer.md +122 -0
- package/agents/sales/cro.md +44 -0
- package/agents/sales/deal-architect.md +29 -0
- package/agents/sales/outbound-strategist.md +29 -0
- package/agents/sales/pipeline-analyst.md +29 -0
- package/agents/support/cco.md +48 -0
- package/agents/support/community-manager.md +570 -0
- package/agents/support/ticket-triage.md +70 -0
- package/bin/soleur-opencode.js +29 -0
- package/commands/go.md +659 -0
- package/commands/help.md +273 -0
- package/commands/sync.md +977 -0
- package/commands/version.md +103 -0
- package/hooks/antigravity-hooks.json +84 -0
- package/hooks/antigravity-session-start.sh +15 -0
- package/hooks/bare-root-cwd-guard.sh +131 -0
- package/hooks/browser-snapshot-credential-guard.sh +200 -0
- package/hooks/codex-session-start.sh +9 -0
- package/hooks/compaction-state.sh +525 -0
- package/hooks/destructive-command-guard.sh +1387 -0
- package/hooks/devin-session-start.sh +90 -0
- package/hooks/ext-filter-detect.sh +171 -0
- package/hooks/hooks.json +133 -0
- package/hooks/lib/hook-tool-kind.sh +24 -0
- package/hooks/lib/log-rotation.sh +176 -0
- package/hooks/lib/shell-argv.pl +576 -0
- package/hooks/memory-backstop.sh +1114 -0
- package/hooks/operator-stage-approval.sh +391 -0
- package/hooks/stop-hook.sh +367 -0
- package/hooks/unkept-promise-hook.sh +383 -0
- package/hooks/version-banner.sh +127 -0
- package/hooks/welcome-hook.sh +50 -0
- package/install.js +108 -0
- package/lib/agent-registry.ts +154 -0
- package/lib/c4-canonical-cli.mjs +34 -0
- package/lib/c4-canonical.mjs +46 -0
- package/lib/c4-from-components.ts +554 -0
- package/lib/go-routing.ts +81 -0
- package/lib/grok-inspect-contract.ts +311 -0
- package/lib/harness-model-map.ts +101 -0
- package/lib/harness-parity.ts +726 -0
- package/lib/harness-tool-map.ts +180 -0
- package/lib/harness.ts +716 -0
- package/lib/heartbeat-live-reconcile.ts +1153 -0
- package/lib/heartbeat-manifest.ts +342 -0
- package/lib/kb-coverage.ts +252 -0
- package/lib/pr-merge-poll.ts +103 -0
- package/lib/workflow-fidelity.ts +388 -0
- package/opencode/INSTRUCTIONS.md +152 -0
- package/opencode/agents/engineering/cto.md +10 -0
- package/opencode/agents/engineering/design/ddd-architect.md +10 -0
- package/opencode/agents/engineering/discovery/agent-finder.md +10 -0
- package/opencode/agents/engineering/discovery/functional-discovery.md +10 -0
- package/opencode/agents/engineering/infra/infra-security.md +10 -0
- package/opencode/agents/engineering/infra/platform-strategist.md +10 -0
- package/opencode/agents/engineering/infra/terraform-architect.md +10 -0
- package/opencode/agents/engineering/prompt-engineer.md +10 -0
- package/opencode/agents/engineering/research/best-practices-researcher.md +10 -0
- package/opencode/agents/engineering/research/framework-docs-researcher.md +10 -0
- package/opencode/agents/engineering/research/git-history-analyzer.md +10 -0
- package/opencode/agents/engineering/research/learnings-researcher.md +10 -0
- package/opencode/agents/engineering/research/repo-research-analyst.md +10 -0
- package/opencode/agents/engineering/review/agent-native-reviewer.md +10 -0
- package/opencode/agents/engineering/review/architecture-strategist.md +10 -0
- package/opencode/agents/engineering/review/code-quality-analyst.md +10 -0
- package/opencode/agents/engineering/review/code-simplicity-reviewer.md +10 -0
- package/opencode/agents/engineering/review/data-integrity-guardian.md +10 -0
- package/opencode/agents/engineering/review/data-migration-expert.md +10 -0
- package/opencode/agents/engineering/review/deployment-verification-agent.md +10 -0
- package/opencode/agents/engineering/review/dhh-rails-reviewer.md +10 -0
- package/opencode/agents/engineering/review/kieran-rails-reviewer.md +10 -0
- package/opencode/agents/engineering/review/legacy-code-expert.md +10 -0
- package/opencode/agents/engineering/review/observability-coverage-reviewer.md +10 -0
- package/opencode/agents/engineering/review/pattern-recognition-specialist.md +10 -0
- package/opencode/agents/engineering/review/performance-oracle.md +10 -0
- package/opencode/agents/engineering/review/security-sentinel.md +10 -0
- package/opencode/agents/engineering/review/semgrep-sast.md +10 -0
- package/opencode/agents/engineering/review/test-design-reviewer.md +10 -0
- package/opencode/agents/engineering/review/user-impact-reviewer.md +10 -0
- package/opencode/agents/engineering/workflow/pr-comment-resolver.md +10 -0
- package/opencode/agents/finance/budget-analyst.md +10 -0
- package/opencode/agents/finance/cfo.md +10 -0
- package/opencode/agents/finance/financial-reporter.md +10 -0
- package/opencode/agents/finance/revenue-analyst.md +10 -0
- package/opencode/agents/legal/clo.md +10 -0
- package/opencode/agents/legal/legal-compliance-auditor.md +10 -0
- package/opencode/agents/legal/legal-document-generator.md +10 -0
- package/opencode/agents/marketing/analytics-analyst.md +10 -0
- package/opencode/agents/marketing/brand-architect.md +10 -0
- package/opencode/agents/marketing/cmo.md +10 -0
- package/opencode/agents/marketing/conversion-optimizer.md +10 -0
- package/opencode/agents/marketing/copywriter.md +10 -0
- package/opencode/agents/marketing/fact-checker.md +10 -0
- package/opencode/agents/marketing/growth-strategist.md +10 -0
- package/opencode/agents/marketing/paid-media-strategist.md +10 -0
- package/opencode/agents/marketing/pricing-strategist.md +10 -0
- package/opencode/agents/marketing/programmatic-seo-specialist.md +10 -0
- package/opencode/agents/marketing/retention-strategist.md +10 -0
- package/opencode/agents/marketing/seo-aeo-analyst.md +10 -0
- package/opencode/agents/operations/coo.md +10 -0
- package/opencode/agents/operations/ops-advisor.md +10 -0
- package/opencode/agents/operations/ops-provisioner.md +10 -0
- package/opencode/agents/operations/ops-research.md +10 -0
- package/opencode/agents/operations/service-automator.md +10 -0
- package/opencode/agents/product/business-validator.md +10 -0
- package/opencode/agents/product/competitive-intelligence.md +10 -0
- package/opencode/agents/product/cpo.md +10 -0
- package/opencode/agents/product/design/ux-design-lead.md +10 -0
- package/opencode/agents/product/spec-flow-analyzer.md +10 -0
- package/opencode/agents/sales/cro.md +10 -0
- package/opencode/agents/sales/deal-architect.md +10 -0
- package/opencode/agents/sales/outbound-strategist.md +10 -0
- package/opencode/agents/sales/pipeline-analyst.md +10 -0
- package/opencode/agents/support/cco.md +10 -0
- package/opencode/agents/support/community-manager.md +10 -0
- package/opencode/agents/support/ticket-triage.md +10 -0
- package/opencode/commands/go.md +10 -0
- package/opencode/commands/help.md +10 -0
- package/opencode/commands/sync.md +10 -0
- package/opencode/commands/version.md +11 -0
- package/opencode/opencode.json +8 -0
- package/opencode/plugin.ts +493 -0
- package/package.json +36 -4
- package/scripts/admin-merge-ready.sh +545 -0
- package/scripts/admin-merge-ready.test.sh +753 -0
- package/scripts/affected-tests.sh +908 -0
- package/scripts/affected-tests.test.sh +1797 -0
- package/scripts/alpha-metrics.sh +78 -0
- package/scripts/alpha-metrics.test.sh +115 -0
- package/scripts/ancestor-signal-helpers.baseline.txt +16 -0
- package/scripts/audit-flag-flip.sh +107 -0
- package/scripts/check-red-on-main.sh +316 -0
- package/scripts/ci-head-verdict.sh +363 -0
- package/scripts/cloud-detect.sh +193 -0
- package/scripts/delegation-verify.sh +657 -0
- package/scripts/delegation-verify.test.sh +1424 -0
- package/scripts/deploy-arm.sh +475 -0
- package/scripts/domain-model-drift.sh +419 -0
- package/scripts/emit-decision.sh +144 -0
- package/scripts/emit-decision.test.sh +144 -0
- package/scripts/ext-filter-divergence-corpus.txt +15 -0
- package/scripts/ext-filter-divergence.sh +189 -0
- package/scripts/generate-c4-from-components.ts +442 -0
- package/scripts/grok-fidelity-gate.sh +68 -0
- package/scripts/grok-pre-push-gate.sh +232 -0
- package/scripts/harness-discovery-smoke.ts +906 -0
- package/scripts/harness-parity-census.ts +92 -0
- package/scripts/inngest-luks-alert-armed-probe.ts +29 -0
- package/scripts/install-opencode-adapter.ts +520 -0
- package/scripts/lib/affected-tests/common.sh +365 -0
- package/scripts/lib/affected-tests/go.sh +157 -0
- package/scripts/lib/affected-tests/js.sh +188 -0
- package/scripts/lib/affected-tests/nx-turbo.sh +98 -0
- package/scripts/lib/affected-tests/python.sh +185 -0
- package/scripts/lib/context-sanitize.sh +49 -0
- package/scripts/lib/domain-model-lib.sh +180 -0
- package/scripts/lib/ext-filter-grammar.tsv +34 -0
- package/scripts/lib/operator-script.sh +1236 -0
- package/scripts/lib/proc.sh +580 -0
- package/scripts/lib/session-state.sh +748 -0
- package/scripts/lib/tmp-classify.sh +843 -0
- package/scripts/lib/wrapper-boundary.sh +47 -0
- package/scripts/lint-ratchet.py +1547 -0
- package/scripts/monitor-pr-checks.sh +441 -0
- package/scripts/pipeline-tally.sh +756 -0
- package/scripts/pipeline-tally.test.sh +740 -0
- package/scripts/plugin-version.sh +528 -0
- package/scripts/precommit-guard.sh +113 -0
- package/scripts/precommit-guard.test.sh +254 -0
- package/scripts/reconcile-live-heartbeats.ts +705 -0
- package/scripts/render-c4-model.sh +217 -0
- package/scripts/resolve-git-root.sh +55 -0
- package/scripts/resolve-regenerable-conflicts.sh +363 -0
- package/scripts/resolve-regenerable-conflicts.test.sh +780 -0
- package/scripts/ruff-requirements.txt +22 -0
- package/scripts/run-in-pid-namespace.sh +98 -0
- package/scripts/run-in-pid-namespace.test.sh +290 -0
- package/scripts/scan-ancestor-signal-helpers.py +556 -0
- package/scripts/scan-ancestor-signal-helpers.test.sh +670 -0
- package/scripts/setup-ralph-loop.sh +238 -0
- package/scripts/sync-cursor-name-map.ts +316 -0
- package/scripts/sync-grok-agent-compat.ts +188 -0
- package/scripts/sync-npm-package.ts +178 -0
- package/scripts/sync-opencode-adapter.ts +479 -0
- package/scripts/sync-pr-behind.sh +534 -0
- package/scripts/sync-pr-behind.test.sh +252 -0
- package/scripts/taste-profile-update.sh +180 -0
- package/scripts/taste-profile-update.test.sh +167 -0
- package/scripts/write-budget-marker.sh +23 -0
- package/scripts/write-kb-coverage.ts +113 -0
- package/skills/admin-ip-refresh/SKILL.md +81 -0
- package/skills/admin-ip-refresh/references/admin-ip-refresh-procedure.md +201 -0
- package/skills/agent-browser/SKILL.md +698 -0
- package/skills/agent-browser/scripts/playwright-mcp-profile-slot.sh +304 -0
- package/skills/agent-browser/scripts/playwright-mcp-redact-proxy.py +964 -0
- package/skills/agent-browser/scripts/redact-a11y-snapshot.py +443 -0
- package/skills/agent-browser/test/fixtures/capture-playwright-mcp-fixtures.py +217 -0
- package/skills/agent-browser/test/fixtures/fake-passthrough-proxy.py +24 -0
- package/skills/agent-browser/test/fixtures/fake-playwright-mcp.py +131 -0
- package/skills/agent-browser/test/fixtures/make-proxy-mutant.py +48 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/dialog-link-injection.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/empty-content.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-and-result.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-code-bool.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-code-string.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-message-tree.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-no-data.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-string.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-with-data.json +9 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/evaluate-escaped-object.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/invalid-utf8.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/link-result.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/list-two-results.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/meta-in-result.json +13 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/no-content.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/quoted-key.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/resource-block.json +18 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/result-and-method.json +11 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/result-string.json +3 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped-one-row.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/structured-content.json +13 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/tools-list-no-tools.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/tree-no-credential.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/two-text-blocks.json +14 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/unparsable-line.json +3 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-brace.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-link-substring.json +10 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/close.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/evaluate.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/find.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/framing.json +6 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/initialize.json +14 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate-link.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/roots-list-request.json +5 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/screenshot.json +17 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-filename.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-json.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-raw.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/tools-list.json +827 -0
- package/skills/agent-browser/test/fixtures/proxy-session-driver.py +138 -0
- package/skills/agent-browser/test/fixtures/session-facts.py +102 -0
- package/skills/agent-browser/test/playwright-mcp-lifetime.test.sh +1620 -0
- package/skills/agent-browser/test/playwright-mcp-redact-proxy.test.sh +1599 -0
- package/skills/agent-browser/test/redact-a11y-snapshot.test.sh +527 -0
- package/skills/agent-native-architecture/SKILL.md +479 -0
- package/skills/agent-native-architecture/references/action-parity-discipline.md +430 -0
- package/skills/agent-native-architecture/references/agent-execution-patterns.md +483 -0
- package/skills/agent-native-architecture/references/agent-native-testing.md +605 -0
- package/skills/agent-native-architecture/references/architecture-patterns.md +493 -0
- package/skills/agent-native-architecture/references/dynamic-context-injection.md +358 -0
- package/skills/agent-native-architecture/references/files-universal-interface.md +314 -0
- package/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +381 -0
- package/skills/agent-native-architecture/references/mcp-tool-design.md +524 -0
- package/skills/agent-native-architecture/references/mobile-patterns.md +897 -0
- package/skills/agent-native-architecture/references/product-implications.md +478 -0
- package/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +342 -0
- package/skills/agent-native-architecture/references/self-modification.md +294 -0
- package/skills/agent-native-architecture/references/shared-workspace-architecture.md +700 -0
- package/skills/agent-native-architecture/references/system-prompt-design.md +263 -0
- package/skills/agent-native-audit/SKILL.md +300 -0
- package/skills/agent-native-audit/workflows/agent-native-audit.workflow.js +423 -0
- package/skills/andrew-kane-gem-writer/SKILL.md +189 -0
- package/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
- package/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
- package/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
- package/skills/andrew-kane-gem-writer/references/resources.md +126 -0
- package/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
- package/skills/architecture/SKILL.md +436 -0
- package/skills/architecture/references/adr-template.md +154 -0
- package/skills/architecture/references/likec4-reference.md +136 -0
- package/skills/architecture/references/nfr-reference.md +126 -0
- package/skills/archive-kb/SKILL.md +86 -0
- package/skills/archive-kb/scripts/archive-kb.sh +300 -0
- package/skills/archive-kb/test/archive-kb-partial-run.test.sh +276 -0
- package/skills/atdd-developer/SKILL.md +65 -0
- package/skills/brainstorm/SKILL.md +701 -0
- package/skills/brainstorm/references/brainstorm-brand-workshop.md +153 -0
- package/skills/brainstorm/references/brainstorm-domain-config.md +63 -0
- package/skills/brainstorm/references/brainstorm-validation-workshop.md +65 -0
- package/skills/brainstorm/references/ui-surface-terms.md +42 -0
- package/skills/brainstorm-techniques/SKILL.md +231 -0
- package/skills/brainstorm-techniques/references/decision-principles.md +150 -0
- package/skills/brainstorm-techniques/references/phase-boundaries.md +103 -0
- package/skills/brainstorm-techniques/references/standing-delegation.md +407 -0
- package/skills/brainstorm-techniques/references/technical-ruling-delegation.md +174 -0
- package/skills/campaign-calendar/SKILL.md +145 -0
- package/skills/cf-token-scope/SKILL.md +164 -0
- package/skills/cf-token-scope/references/widen-playbook.md +114 -0
- package/skills/cf-token-scope/scripts/cf-token-scope.sh +253 -0
- package/skills/changelog/SKILL.md +142 -0
- package/skills/code-to-prd/SKILL.md +66 -0
- package/skills/code-to-prd/references/banner-template.md +12 -0
- package/skills/code-to-prd/references/prd-template.md +41 -0
- package/skills/code-to-prd/scripts/code-to-prd.sh +634 -0
- package/skills/code-to-prd/test/code-to-prd.test.sh +447 -0
- package/skills/code-to-prd/test/fixture/.env.example +7 -0
- package/skills/code-to-prd/test/fixture/app/about/page.tsx +11 -0
- package/skills/code-to-prd/test/fixture/app/api/health/route.ts +10 -0
- package/skills/code-to-prd/test/fixture/app/page.tsx +14 -0
- package/skills/code-to-prd/test/fixture/next.config.mjs +3 -0
- package/skills/code-to-prd/test/fixture/package.json +6 -0
- package/skills/cohort-status/SKILL.md +62 -0
- package/skills/community/SKILL.md +210 -0
- package/skills/community/scripts/bsky-community.sh +644 -0
- package/skills/community/scripts/bsky-setup.sh +631 -0
- package/skills/community/scripts/community-router.sh +93 -0
- package/skills/community/scripts/discord-community.sh +487 -0
- package/skills/community/scripts/discord-setup.sh +784 -0
- package/skills/community/scripts/github-community.sh +706 -0
- package/skills/community/scripts/hn-community.sh +233 -0
- package/skills/community/scripts/lib/hmac-sha1-b64.sh +126 -0
- package/skills/community/scripts/linkedin-community.sh +750 -0
- package/skills/community/scripts/linkedin-setup.sh +758 -0
- package/skills/community/scripts/x-community.sh +890 -0
- package/skills/community/scripts/x-setup.sh +713 -0
- package/skills/community/test/community-argv.test.sh +2922 -0
- package/skills/community/test/github-community.test.sh +981 -0
- package/skills/competitive-analysis/SKILL.md +69 -0
- package/skills/competitive-analysis/references/peer-plugin-audit.md +218 -0
- package/skills/compound/SKILL.md +673 -0
- package/skills/compound/scripts/token-efficiency-report.sh +334 -0
- package/skills/compound/test/phase-16.test.sh +379 -0
- package/skills/compound-capture/SKILL.md +791 -0
- package/skills/compound-capture/assets/critical-pattern-template.md +37 -0
- package/skills/compound-capture/assets/resolution-template.md +116 -0
- package/skills/compound-capture/references/yaml-schema.md +67 -0
- package/skills/compound-capture/schema.yaml +181 -0
- package/skills/constraint-scaffold/SKILL.md +175 -0
- package/skills/constraint-scaffold/references/boundary-readme.template +35 -0
- package/skills/constraint-scaffold/references/constraint-gates-workflow.template +69 -0
- package/skills/constraint-scaffold/references/depcruise-config.template +230 -0
- package/skills/constraint-scaffold/references/fix-constraints-stage-a.template +240 -0
- package/skills/constraint-scaffold/references/fix-constraints-stage-b.template +313 -0
- package/skills/constraint-scaffold/references/shared-runner.template +135 -0
- package/skills/constraint-scaffold/scripts/constraint-scaffold.sh +589 -0
- package/skills/constraint-scaffold/test/bite-proof.test.sh +1338 -0
- package/skills/constraint-scaffold/test/boundary.test.sh +734 -0
- package/skills/constraint-scaffold/test/emit-fix-constraints.test.sh +193 -0
- package/skills/constraint-scaffold/test/generator.test.sh +93 -0
- package/skills/constraint-scaffold/test/parity.test.sh +285 -0
- package/skills/content-writer/SKILL.md +242 -0
- package/skills/content-writer/scripts/blog-jargon-scan.sh +42 -0
- package/skills/cron-delete/SKILL.md +56 -0
- package/skills/cron-list/SKILL.md +54 -0
- package/skills/deepen-plan/SKILL.md +937 -0
- package/skills/deepen-plan/workflows/deepen-plan.workflow.js +488 -0
- package/skills/deploy/SKILL.md +115 -0
- package/skills/deploy/references/hetzner-setup.md +65 -0
- package/skills/deploy/scripts/deploy.sh +37 -0
- package/skills/deploy-docs/SKILL.md +95 -0
- package/skills/dhh-rails-style/SKILL.md +203 -0
- package/skills/dhh-rails-style/references/architecture.md +717 -0
- package/skills/dhh-rails-style/references/controllers.md +323 -0
- package/skills/dhh-rails-style/references/frontend.md +556 -0
- package/skills/dhh-rails-style/references/gems.md +316 -0
- package/skills/dhh-rails-style/references/models.md +388 -0
- package/skills/dhh-rails-style/references/testing.md +354 -0
- package/skills/discord-content/SKILL.md +126 -0
- package/skills/docs-site/SKILL.md +214 -0
- package/skills/drain-labeled-backlog/SKILL.md +203 -0
- package/skills/drain-labeled-backlog/scripts/group-by-area.sh +208 -0
- package/skills/drain-labeled-backlog/workflows/drain-labeled-backlog.workflow.js +433 -0
- package/skills/drain-prs/SKILL.md +142 -0
- package/skills/drain-prs/scripts/triage-prs.sh +192 -0
- package/skills/drain-prs/test/argv-ceiling.test.sh +183 -0
- package/skills/dspy-ruby/SKILL.md +634 -0
- package/skills/dspy-ruby/assets/config-template.rb +359 -0
- package/skills/dspy-ruby/assets/module-template.rb +326 -0
- package/skills/dspy-ruby/assets/signature-template.rb +143 -0
- package/skills/dspy-ruby/references/core-concepts.md +268 -0
- package/skills/dspy-ruby/references/optimization.md +623 -0
- package/skills/dspy-ruby/references/providers.md +335 -0
- package/skills/eval-harness/README.md +194 -0
- package/skills/eval-harness/SKILL.md +157 -0
- package/skills/eval-harness/enums/go-routes.json +13 -0
- package/skills/eval-harness/enums/incident-threshold.json +5 -0
- package/skills/eval-harness/enums/lane.json +5 -0
- package/skills/eval-harness/enums/tool-selection.json +20 -0
- package/skills/eval-harness/enums/triage-levels.json +5 -0
- package/skills/eval-harness/gated-skills.json +34 -0
- package/skills/eval-harness/models.generated.json +5 -0
- package/skills/eval-harness/promptfooconfig-go-routing.yaml +35 -0
- package/skills/eval-harness/promptfooconfig-incident-threshold.yaml +32 -0
- package/skills/eval-harness/promptfooconfig-lane-inference.yaml +33 -0
- package/skills/eval-harness/promptfooconfig-ticket-triage.yaml +34 -0
- package/skills/eval-harness/promptfooconfig-tool-selection.yaml +33 -0
- package/skills/eval-harness/prompts/go-baseline.txt +6 -0
- package/skills/eval-harness/prompts/go-skill.txt +21 -0
- package/skills/eval-harness/prompts/incident-threshold-baseline.txt +6 -0
- package/skills/eval-harness/prompts/incident-threshold-skill.txt +12 -0
- package/skills/eval-harness/prompts/lane-inference-baseline.txt +6 -0
- package/skills/eval-harness/prompts/lane-inference-skill.txt +15 -0
- package/skills/eval-harness/prompts/tool-selection-baseline.txt +19 -0
- package/skills/eval-harness/prompts/tool-selection-skill.txt +22 -0
- package/skills/eval-harness/prompts/triage-baseline.txt +7 -0
- package/skills/eval-harness/prompts/triage-skill.txt +10 -0
- package/skills/eval-harness/scripts/eval-gate.cjs +318 -0
- package/skills/eval-harness/scripts/extract-block.cjs +87 -0
- package/skills/eval-harness/scripts/gate-classification.cjs +28 -0
- package/skills/eval-harness/scripts/gen-models.sh +41 -0
- package/skills/eval-harness/scripts/gen-skill-prompt.cjs +177 -0
- package/skills/eval-harness/scripts/measure-classification.cjs +30 -0
- package/skills/eval-harness/scripts/parse-label.cjs +93 -0
- package/skills/eval-harness/scripts/verdict.cjs +132 -0
- package/skills/eval-harness/tasks/go-routing.jsonl +8 -0
- package/skills/eval-harness/tasks/incident-threshold.jsonl +7 -0
- package/skills/eval-harness/tasks/lane-inference.jsonl +7 -0
- package/skills/eval-harness/tasks/ticket-triage.jsonl +6 -0
- package/skills/eval-harness/tasks/tool-selection.jsonl +15 -0
- package/skills/eval-harness/test/eval-gate.test.sh +132 -0
- package/skills/eval-harness/test/extract-block.test.sh +87 -0
- package/skills/eval-harness/test/gate-classification.test.sh +77 -0
- package/skills/eval-harness/test/gen-models.test.sh +75 -0
- package/skills/eval-harness/test/measure-classification.test.sh +74 -0
- package/skills/eval-harness/test/parse-label.test.sh +129 -0
- package/skills/eval-harness/test/registry-completeness.test.sh +109 -0
- package/skills/eval-harness/test/verdict.test.sh +123 -0
- package/skills/every-style-editor/SKILL.md +142 -0
- package/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
- package/skills/feature-tweet/SKILL.md +199 -0
- package/skills/feature-video/SKILL.md +412 -0
- package/skills/feature-video/scripts/check_deps.sh +281 -0
- package/skills/file-todos/SKILL.md +267 -0
- package/skills/file-todos/assets/todo-template.md +166 -0
- package/skills/fix-issue/SKILL.md +278 -0
- package/skills/fix-issue/references/agent-authored-exclusion.md +118 -0
- package/skills/fix-issue/references/exclude-label-jq-snippet.md +96 -0
- package/skills/flag-bootstrap/SETUP.md +142 -0
- package/skills/flag-create/SKILL.md +145 -0
- package/skills/flag-create/scripts/create.sh +273 -0
- package/skills/flag-delete/SKILL.md +167 -0
- package/skills/flag-delete/scripts/delete.sh +288 -0
- package/skills/flag-list/SKILL.md +99 -0
- package/skills/flag-list/scripts/list.sh +275 -0
- package/skills/flag-set-role/SKILL.md +229 -0
- package/skills/flag-set-role/scripts/flip.sh +774 -0
- package/skills/frontend-anti-slop/SKILL.md +106 -0
- package/skills/frontend-anti-slop/references/anti-patterns.md +199 -0
- package/skills/frontend-anti-slop/references/slop-rules.md +65 -0
- package/skills/frontend-anti-slop/scripts/tier1-scan.ts +525 -0
- package/skills/frontend-design/SKILL.md +77 -0
- package/skills/gdpr-gate/NOTICE +136 -0
- package/skills/gdpr-gate/SKILL.md +341 -0
- package/skills/gdpr-gate/references/fields.md +160 -0
- package/skills/gdpr-gate/references/layers/api-layer.md +355 -0
- package/skills/gdpr-gate/references/layers/auth-sessions.md +290 -0
- package/skills/gdpr-gate/references/layers/data-in-transit.md +331 -0
- package/skills/gdpr-gate/references/layers/data-lifecycle.md +341 -0
- package/skills/gdpr-gate/references/layers/frontend.md +249 -0
- package/skills/gdpr-gate/references/layers/testing-seeding.md +256 -0
- package/skills/gdpr-gate/references/leakage-vectors.md +248 -0
- package/skills/gdpr-gate/references/legacy/legal-consent-v1-prose.md +48 -0
- package/skills/gdpr-gate/references/legal-consent.md +140 -0
- package/skills/gdpr-gate/references/non-negotiables.md +60 -0
- package/skills/gdpr-gate/scripts/gdpr-gate.sh +271 -0
- package/skills/gdpr-gate/scripts/notice-frontmatter.sh +337 -0
- package/skills/gdpr-gate/scripts/path-denylist.txt +39 -0
- package/skills/gdpr-gate/scripts/repo-scan.sh +158 -0
- package/skills/gdpr-gate/scripts/vendor-drift-classify.sh +120 -0
- package/skills/gdpr-gate/scripts/vendor-pin-integrity.sh +237 -0
- package/skills/gemini-imagegen/SKILL.md +283 -0
- package/skills/gemini-imagegen/requirements.txt +5 -0
- package/skills/gemini-imagegen/scripts/_error_handling.py +146 -0
- package/skills/gemini-imagegen/scripts/compose_images.py +150 -0
- package/skills/gemini-imagegen/scripts/edit_image.py +137 -0
- package/skills/gemini-imagegen/scripts/gemini_images.py +256 -0
- package/skills/gemini-imagegen/scripts/generate_image.py +147 -0
- package/skills/gemini-imagegen/scripts/multi_turn_chat.py +223 -0
- package/skills/gemini-imagegen/scripts/test_error_handling.py +179 -0
- package/skills/git-worktree/SKILL.md +534 -0
- package/skills/git-worktree/scripts/git-repo-readiness-diag.sh +98 -0
- package/skills/git-worktree/scripts/worktree-manager.sh +4773 -0
- package/skills/git-worktree/test/create-from-origin-main.test.sh +116 -0
- package/skills/git-worktree/test/lease-protects-active.test.sh +1056 -0
- package/skills/git-worktree/test/no-repo-fail-loud.test.sh +88 -0
- package/skills/git-worktree/test/orphan-reaper-honest-count.test.sh +379 -0
- package/skills/git-worktree/test/reap-archive-persistence.test.sh +725 -0
- package/skills/git-worktree/test/stale-lock-sweep.test.sh +176 -0
- package/skills/go/SKILL.md +54 -0
- package/skills/growth/SKILL.md +164 -0
- package/skills/harvest-debt/SKILL.md +78 -0
- package/skills/harvest-debt/scripts/harvest-debt.sh +114 -0
- package/skills/heal-skill/SKILL.md +173 -0
- package/skills/help/SKILL.md +46 -0
- package/skills/incident/NOTICE +39 -0
- package/skills/incident/SKILL.md +395 -0
- package/skills/incident/scripts/dry-run.sh +448 -0
- package/skills/incident/scripts/redact-engine.py +412 -0
- package/skills/incident/scripts/redact-sentinel.sh +44 -0
- package/skills/incident/templates/pir.md +139 -0
- package/skills/incident/test/fixtures/dry-run-incident.json +26 -0
- package/skills/incident/test/fixtures/dry-run-secret-leak.json +26 -0
- package/skills/incident/test/fixtures/legacy-bash-scanner.sh +82 -0
- package/skills/incident/test/fixtures/positive-corpus.md +87 -0
- package/skills/incident/test/redact-sentinel.test.sh +1420 -0
- package/skills/invoice/SKILL.md +206 -0
- package/skills/kb-glossary/SKILL.md +71 -0
- package/skills/kb-glossary/references/glossary-format.md +111 -0
- package/skills/kb-glossary/references/rejected-request-register.md +115 -0
- package/skills/kb-search/SKILL.md +276 -0
- package/skills/kb-search/scripts/kb-search-cache.sh +123 -0
- package/skills/legal-audit/SKILL.md +161 -0
- package/skills/legal-generate/NOTICE +242 -0
- package/skills/legal-generate/SKILL.md +244 -0
- package/skills/legal-generate/references/templates/advisor-agreement/template.md +12 -0
- package/skills/legal-generate/references/templates/business-associate-agreement/template.md +112 -0
- package/skills/legal-generate/references/templates/cookie-notice/template.md +82 -0
- package/skills/legal-generate/references/templates/dpa-global/template.md +439 -0
- package/skills/legal-generate/references/templates/dpa-us/template.md +222 -0
- package/skills/legal-generate/references/templates/employee-offer-letter/template.md +75 -0
- package/skills/legal-generate/references/templates/master-services-agreement/template.md +252 -0
- package/skills/legal-generate/references/templates/mutual-nda/template.md +66 -0
- package/skills/legal-generate/references/templates/one-way-nda/template.md +38 -0
- package/skills/legal-generate/references/templates/privacy-policy-gdpr/template.md +427 -0
- package/skills/legal-generate/references/templates/privacy-policy-us/template.md +313 -0
- package/skills/legal-generate/references/templates/terms-of-use/template.md +75 -0
- package/skills/legal-generate/scripts/strip-vendor-credit.sh +96 -0
- package/skills/linear-fetch/SKILL.md +247 -0
- package/skills/linear-fetch/scripts/assert-no-linear-telemetry.sh +66 -0
- package/skills/linear-fetch/scripts/redact-linear-urls.sh +51 -0
- package/skills/linear-fetch/scripts/render-caller-template.sh +36 -0
- package/skills/linear-fetch/test/assert-no-linear-telemetry.test.sh +113 -0
- package/skills/linear-fetch/test/parity.test.sh +112 -0
- package/skills/linear-fetch/test/persist-safe-integration.test.sh +191 -0
- package/skills/linear-fetch/test/redact-linear-urls.test.sh +226 -0
- package/skills/merge-pr/SKILL.md +668 -0
- package/skills/model-launch-review/SKILL.md +255 -0
- package/skills/model-launch-review/scripts/audit-models.sh +501 -0
- package/skills/one-shot/SKILL.md +316 -0
- package/skills/one-shot/references/token-discipline.md +74 -0
- package/skills/operator-bootstrap/SKILL.md +412 -0
- package/skills/operator-bootstrap/template.sh +439 -0
- package/skills/operator-digest/SKILL.md +287 -0
- package/skills/operator-digest/assets/operator-digest.workflow.yml +175 -0
- package/skills/operator-digest/scripts/digest-scrub.sh +119 -0
- package/skills/operator-digest/scripts/provision-operator-digest-repo.sh +147 -0
- package/skills/operator-rephrase/SKILL.md +98 -0
- package/skills/pencil-setup/SKILL.md +201 -0
- package/skills/pencil-setup/scripts/check_deps.sh +556 -0
- package/skills/pencil-setup/scripts/copy_adapter.sh +80 -0
- package/skills/pencil-setup/scripts/package-lock.json +1172 -0
- package/skills/pencil-setup/scripts/package.json +14 -0
- package/skills/pencil-setup/scripts/pencil-error-enrichment.mjs +21 -0
- package/skills/pencil-setup/scripts/pencil-mcp-adapter.mjs +733 -0
- package/skills/pencil-setup/scripts/pencil-response-classify.mjs +38 -0
- package/skills/pencil-setup/scripts/pencil-save-gate.mjs +26 -0
- package/skills/pencil-setup/scripts/sanitize-filename.mjs +25 -0
- package/skills/plan/SKILL.md +1140 -0
- package/skills/plan/references/differential-migration-testing.md +185 -0
- package/skills/plan/references/plan-community-discovery.md +42 -0
- package/skills/plan/references/plan-founder-check.md +137 -0
- package/skills/plan/references/plan-functional-overlap.md +25 -0
- package/skills/plan/references/plan-host-fanout.md +51 -0
- package/skills/plan/references/plan-issue-templates.md +779 -0
- package/skills/plan/references/plan-network-outage-checklist.md +131 -0
- package/skills/plan/references/plan-scope-check.md +126 -0
- package/skills/plan/references/plan-sharp-edges.md +325 -0
- package/skills/plan/references/plan-signoff-lifecycle.md +12 -0
- package/skills/plan/references/webapp-cwv-observability.md +143 -0
- package/skills/plan-review/SKILL.md +91 -0
- package/skills/plan-review/lib/named-panel.mjs +58 -0
- package/skills/plan-review/workflows/plan-review.workflow.js +477 -0
- package/skills/postmerge/SKILL.md +642 -0
- package/skills/postmerge/references/deploy-status-debugging.md +138 -0
- package/skills/postmerge/references/graceful-degradation.md +20 -0
- package/skills/postmerge/references/sentry-error-count-delta.md +137 -0
- package/skills/preflight/SKILL.md +1553 -0
- package/skills/preflight/references/check-13-founder-check.md +286 -0
- package/skills/preflight/scripts/founder-check.py +1640 -0
- package/skills/preflight/scripts/parse-form-a.awk +107 -0
- package/skills/preflight/scripts/probe-verb-gate.sh +108 -0
- package/skills/product-roadmap/SKILL.md +357 -0
- package/skills/product-roadmap/scripts/roadmap-reconcile.sh +327 -0
- package/skills/provision-cloudflare/SKILL.md +67 -0
- package/skills/provision-cloudflare/scripts/provision-cloudflare.sh +271 -0
- package/skills/provision-doppler/SKILL.md +58 -0
- package/skills/provision-doppler/scripts/provision-doppler.sh +358 -0
- package/skills/provision-github/SKILL.md +59 -0
- package/skills/provision-github/scripts/provision-github.sh +300 -0
- package/skills/provision-hetzner/SKILL.md +76 -0
- package/skills/provision-hetzner/scripts/provision-hetzner.sh +262 -0
- package/skills/provision-hetzner/test/fixture/knowledge-base/legal/tenant-dpa-register.md +26 -0
- package/skills/provision-hetzner/test/fixture/provision-hetzner-dry-run.golden +34 -0
- package/skills/provision-hetzner/test/provision-hetzner-characterization.test.sh +227 -0
- package/skills/qa/SKILL.md +263 -0
- package/skills/qa/references/browser-preflight.md +22 -0
- package/skills/questionnaire-generate/SKILL.md +328 -0
- package/skills/questionnaire-generate/references/questionnaire.template +60 -0
- package/skills/rclone/SKILL.md +162 -0
- package/skills/rclone/scripts/check_setup.sh +63 -0
- package/skills/release-announce/SKILL.md +65 -0
- package/skills/release-docs/SKILL.md +92 -0
- package/skills/reproduce-bug/SKILL.md +358 -0
- package/skills/resolve-debt/SKILL.md +85 -0
- package/skills/resolve-debt/scripts/resolve-debt.py +584 -0
- package/skills/resolve-parallel/SKILL.md +45 -0
- package/skills/resolve-parallel/workflows/resolve-parallel.workflow.js +415 -0
- package/skills/resolve-pr-parallel/SKILL.md +68 -0
- package/skills/resolve-pr-parallel/workflows/resolve-pr-parallel.workflow.js +419 -0
- package/skills/resolve-todo-parallel/SKILL.md +57 -0
- package/skills/resolve-todo-parallel/workflows/resolve-todo-parallel.workflow.js +398 -0
- package/skills/review/SKILL.md +1621 -0
- package/skills/review/references/anti-slop-scanner-hook.md +40 -0
- package/skills/review/references/defect-classes-migrations.md +9 -0
- package/skills/review/references/generated-input-oracle-surfaces.md +15 -0
- package/skills/review/references/review-e2e-testing.md +116 -0
- package/skills/review/references/review-todo-structure.md +165 -0
- package/skills/review/references/risk-tier-and-fix-rounds.md +95 -0
- package/skills/review/references/semgrep-custom-rules.yaml +174 -0
- package/skills/review/references/ultrathink-phases.md +98 -0
- package/skills/review/references/wfs.md +6 -0
- package/skills/review/scripts/emit-review-trailer.sh +499 -0
- package/skills/review/scripts/ensure-semgrep.sh +99 -0
- package/skills/review/scripts/fix-round-seats.sh +197 -0
- package/skills/review/test/emit-review-trailer.test.sh +387 -0
- package/skills/review/test/ensure-semgrep.test.sh +111 -0
- package/skills/review/test/fix-round-seats.test.sh +237 -0
- package/skills/review/workflows/README.md +147 -0
- package/skills/review/workflows/review.workflow.js +667 -0
- package/skills/schedule/SKILL.md +796 -0
- package/skills/seo-aeo/SKILL.md +139 -0
- package/skills/seo-aeo/scripts/validate-csp.sh +233 -0
- package/skills/seo-aeo/scripts/validate-seo.sh +262 -0
- package/skills/ship/SKILL.md +3022 -0
- package/skills/ship/references/adr-ordinal-collision.md +47 -0
- package/skills/ship/references/affected-gate-contract.md +115 -0
- package/skills/ship/references/ci-run-diagnosis.md +29 -0
- package/skills/ship/references/ci-workflow-authoring.md +68 -0
- package/skills/ship/references/counsel-review-clo-attestation.md +38 -0
- package/skills/ship/references/cto-ruling-armed-push.md +5 -0
- package/skills/ship/references/decision-challenges-render.md +71 -0
- package/skills/ship/references/detached-battery-verdict.md +13 -0
- package/skills/ship/references/feature-tweet-draft.md +42 -0
- package/skills/ship/references/followthrough-issue-body-template.md +47 -0
- package/skills/ship/references/followthrough-stub-template.sh +92 -0
- package/skills/ship/references/merge-queue-dequeue.md +39 -0
- package/skills/ship/references/operator-holds.md +149 -0
- package/skills/ship/references/pipeline-tally-render.md +43 -0
- package/skills/ship/references/pr-overlap.md +153 -0
- package/skills/ship/references/queue-mode.md +7 -0
- package/skills/ship/references/ready-run-wait.md +36 -0
- package/skills/ship/references/red-on-main-quarantine.md +110 -0
- package/skills/ship/references/register-update-pr-pattern.md +88 -0
- package/skills/ship/references/settle-then-admin-merge.md +130 -0
- package/skills/ship/references/supabase-column-probe.md +13 -0
- package/skills/ship/scripts/auto-close-scan.sh +76 -0
- package/skills/ship/scripts/battery-owed.sh +403 -0
- package/skills/ship/scripts/hold-gate-eval.sh +410 -0
- package/skills/ship/scripts/net-issue-flow.sh +665 -0
- package/skills/ship/scripts/pr-overlap-preflight.sh +483 -0
- package/skills/ship/scripts/ship-pir-action-items-gate.sh +246 -0
- package/skills/ship/scripts/technical-ruling-gate.sh +444 -0
- package/skills/skill-creator/SKILL.md +299 -0
- package/skills/skill-creator/references/api-security.md +248 -0
- package/skills/skill-creator/references/authoring-levers.md +110 -0
- package/skills/skill-creator/references/be-clear-and-direct.md +587 -0
- package/skills/skill-creator/references/best-practices.md +431 -0
- package/skills/skill-creator/references/common-patterns.md +639 -0
- package/skills/skill-creator/references/core-principles.md +193 -0
- package/skills/skill-creator/references/executable-code.md +188 -0
- package/skills/skill-creator/references/iteration-and-testing.md +509 -0
- package/skills/skill-creator/references/official-spec.md +193 -0
- package/skills/skill-creator/references/recommended-structure.md +180 -0
- package/skills/skill-creator/references/skill-structure.md +396 -0
- package/skills/skill-creator/references/using-scripts.md +122 -0
- package/skills/skill-creator/references/using-templates.md +120 -0
- package/skills/skill-creator/references/workflows-and-validation.md +541 -0
- package/skills/skill-creator/scripts/init_skill.py +322 -0
- package/skills/skill-creator/scripts/package_skill.py +110 -0
- package/skills/skill-creator/scripts/quick_validate.py +64 -0
- package/skills/skill-creator/templates/router-skill.md +73 -0
- package/skills/skill-creator/templates/simple-skill.md +34 -0
- package/skills/skill-creator/workflows/add-reference.md +96 -0
- package/skills/skill-creator/workflows/add-script.md +104 -0
- package/skills/skill-creator/workflows/add-template.md +83 -0
- package/skills/skill-creator/workflows/add-workflow.md +128 -0
- package/skills/skill-creator/workflows/audit-skill.md +159 -0
- package/skills/skill-creator/workflows/create-domain-expertise-skill.md +623 -0
- package/skills/skill-creator/workflows/create-new-skill.md +207 -0
- package/skills/skill-creator/workflows/get-guidance.md +134 -0
- package/skills/skill-creator/workflows/upgrade-to-router.md +170 -0
- package/skills/skill-creator/workflows/verify-skill.md +226 -0
- package/skills/skill-security-scan/SKILL.md +145 -0
- package/skills/skill-security-scan/references/disclaimer.md +21 -0
- package/skills/skill-security-scan/references/first-party-allowlist.yaml +38 -0
- package/skills/skill-security-scan/references/override-artifact-schema.json +68 -0
- package/skills/skill-security-scan/references/override-mechanism.md +171 -0
- package/skills/skill-security-scan/references/redirect-domains.yaml +27 -0
- package/skills/skill-security-scan/references/regex-patterns.md +136 -0
- package/skills/skill-security-scan/references/rules/code-exec.yaml +70 -0
- package/skills/skill-security-scan/references/rules/filesystem-boundary.yaml +29 -0
- package/skills/skill-security-scan/references/rules/manifest.yaml +44 -0
- package/skills/skill-security-scan/references/rules/supply-chain.yaml +36 -0
- package/skills/skill-security-scan/references/scan-meta-schema.json +63 -0
- package/skills/skill-security-scan/references/test-fixtures/clean-soleur-style.skill.md +23 -0
- package/skills/skill-security-scan/references/test-fixtures/clean-third-party.skill.md +26 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-codeexec.skill.md +23 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-curl-pipe-bash.skill.md +69 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-prompt-injection.skill.md +17 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-telemetry-beacon.skill.md +23 -0
- package/skills/skill-security-scan/references/typosquat-targets.yaml +65 -0
- package/skills/skill-security-scan/scripts/check-codeexec.sh +41 -0
- package/skills/skill-security-scan/scripts/check-filesystem-boundary.sh +19 -0
- package/skills/skill-security-scan/scripts/check-prompt-injection.sh +95 -0
- package/skills/skill-security-scan/scripts/check-supply-chain.sh +219 -0
- package/skills/skill-security-scan/scripts/check-telemetry-surface.sh +126 -0
- package/skills/skill-security-scan/scripts/lib.sh +197 -0
- package/skills/skill-security-scan/scripts/parse-override.sh +231 -0
- package/skills/skill-security-scan/scripts/run-scan.sh +342 -0
- package/skills/skill-security-scan/scripts/run-self-test.sh +95 -0
- package/skills/skill-security-scan/test/argv-ceiling.test.sh +180 -0
- package/skills/skill-security-scan/test/meta-dir-reap.test.sh +411 -0
- package/skills/skill-security-scan/test/parse-override.test.sh +607 -0
- package/skills/skill-security-scan/test/redact-pii-ghs-shape.test.sh +251 -0
- package/skills/social-distribute/SKILL.md +485 -0
- package/skills/spec-templates/SKILL.md +274 -0
- package/skills/sync/SKILL.md +49 -0
- package/skills/test-browser/SKILL.md +464 -0
- package/skills/test-browser/references/feature-map.md +161 -0
- package/skills/test-fix-loop/SKILL.md +159 -0
- package/skills/test-fix-loop/references/determinism-checklist.md +154 -0
- package/skills/triage/SKILL.md +402 -0
- package/skills/trigger-cron/SKILL.md +136 -0
- package/skills/trigger-cron/scripts/trigger.sh +198 -0
- package/skills/user-set-role/SKILL.md +147 -0
- package/skills/user-set-role/scripts/set-role.sh +218 -0
- package/skills/user-story-writer/SKILL.md +77 -0
- package/skills/ux-audit/SKILL.md +251 -0
- package/skills/ux-audit/references/finding.schema.json +62 -0
- package/skills/ux-audit/references/route-list.yaml +95 -0
- package/skills/ux-audit/scripts/bot-fixture.ts +270 -0
- package/skills/ux-audit/scripts/bot-signin.ts +135 -0
- package/skills/ux-audit/scripts/dedup-hash.ts +46 -0
- package/skills/work/SKILL.md +1479 -0
- package/skills/work/references/end-of-work-resume.md +7 -0
- package/skills/work/references/hook-test-main-cwd.md +24 -0
- package/skills/work/references/key-principles.md +83 -0
- package/skills/work/references/property-testing.md +122 -0
- package/skills/work/references/sql-security-definer-rpc-scaffold.sql +78 -0
- package/skills/work/references/work-agent-teams.md +97 -0
- package/skills/work/references/work-lifecycle-parallel.md +147 -0
- package/skills/work/references/work-lockfile-bumps.md +97 -0
- package/skills/work/references/work-scratch-sandboxes.md +212 -0
- package/skills/work/references/work-subagent-fanout.md +61 -0
- package/skills/work/references/work-test-harness-sharp-edges.md +73 -0
- package/skills/xcode-test/SKILL.md +360 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# render-c4-model.sh — Render the compiled LikeC4 model artifact from a repo's .c4 sources.
|
|
3
|
+
#
|
|
4
|
+
# Usage: bash <plugin>/scripts/render-c4-model.sh [--root DIR] [--out PATH] [--help]
|
|
5
|
+
#
|
|
6
|
+
# Compiles every LikeC4 DSL source (*.c4) under <root>/knowledge-base/engineering/
|
|
7
|
+
# architecture/diagrams/ into the layouted model.likec4.json that the web Knowledge
|
|
8
|
+
# Base viewer renders at runtime (the browser ships @likec4/diagram WITHOUT the
|
|
9
|
+
# compiler, so the JSON must be precompiled and committed).
|
|
10
|
+
#
|
|
11
|
+
# PLUGIN-OWNED (ADR-235 amendment, #8542 follow-up). It lived at the Soleur repo's
|
|
12
|
+
# scripts/regenerate-c4-model.sh, which a self-hosted install does not have, so the
|
|
13
|
+
# merge resolver could never regenerate in a customer repo. That path is now a thin
|
|
14
|
+
# wrapper for this repo's own callers; this file is the one renderer.
|
|
15
|
+
#
|
|
16
|
+
# --root DIR The repository whose diagrams to render. Default: the git top level of
|
|
17
|
+
# the current directory. The CODE comes from beside this script; only the
|
|
18
|
+
# DATA comes from --root (ADR-179's code-root / data-root split).
|
|
19
|
+
# --out PATH Write the validated, canonicalized model to PATH instead of the tracked
|
|
20
|
+
# artifact. Used by plugins/soleur/test/c4-model-freshness.test.sh to render
|
|
21
|
+
# to a temp path with identical logic, then byte-diff against the committed
|
|
22
|
+
# artifact. Default: <root>/.../diagrams/model.likec4.json.
|
|
23
|
+
#
|
|
24
|
+
# Pinned to likec4@1.50.0 — MUST match apps/web-platform/Dockerfile +
|
|
25
|
+
# package.json @likec4/core/@likec4/diagram (guarded by c4-likec4-version-pin.test.ts).
|
|
26
|
+
# A CLI/client version skew silently desyncs the rendered diagram.
|
|
27
|
+
#
|
|
28
|
+
# BUMPING LIKEC4 — the version is half of a pair with LIKEC4_BEFORE. The version pins ONE
|
|
29
|
+
# package; `--before=<date>` resolves its ~190 transitive deps as of that date, so a
|
|
30
|
+
# tarball published minutes ago (which npm's CDN can 404, #9300) is never requested.
|
|
31
|
+
# 1. Pick the new version, then a date that is the day AFTER its publish day and >= 3 days
|
|
32
|
+
# old (a date-only --before is midnight UTC and EXCLUSIVE: a version published at 17:11Z
|
|
33
|
+
# on day D is invisible to --before=D and fails with ETARGET; claude-code 2.1.284 is a
|
|
34
|
+
# live example of that arithmetic, not a likec4 fact):
|
|
35
|
+
# npm view likec4@<version> time --json
|
|
36
|
+
# 2. Move LIKEC4_VERSION and LIKEC4_BEFORE together in EVERY site in one commit: this
|
|
37
|
+
# script, plugins/soleur/lib/c4-from-components.ts, the `Install likec4 CLI` steps
|
|
38
|
+
# in .github/workflows/ci.yml and main-health-monitor.yml, and the `cli-tools` stage
|
|
39
|
+
# of apps/web-platform/Dockerfile (the date is a literal there). Every one of those
|
|
40
|
+
# installs must be exactly `npm install -g likec4@<version> --before=<date>
|
|
41
|
+
# --ignore-scripts` (a Dockerfile one prefixed `RUN `): the tests exercise the binary a
|
|
42
|
+
# scripts-off install makes, so the shipped one must match. The claude-code install is the
|
|
43
|
+
# exception (its postinstall places the binary). Sweep with: git grep 'likec4@1\.'
|
|
44
|
+
# c4-likec4-version-pin.test.ts asserts parity, the age floor, the flag and the exact form.
|
|
45
|
+
# Deliberately version-only (no --before): package.json (installed by lock-based
|
|
46
|
+
# `npm ci --ignore-scripts`) and the interactive `validate` recipes in the architecture skill docs,
|
|
47
|
+
# which also run scripts-on (they are asserted for the version only).
|
|
48
|
+
# A claude-code bump needs no date (its tree is exact-pinned platform packages with
|
|
49
|
+
# nothing floating) but claude-cli-pin-knows-models.test.ts must stay green.
|
|
50
|
+
# Policy: the date moves with a likec4 bump, or sooner if a transitive advisory affects
|
|
51
|
+
# the CLI; the tree is otherwise frozen on purpose. A version bump that forgets the date
|
|
52
|
+
# fails the install with ETARGET (the registry knows publish times; the offline guard
|
|
53
|
+
# does not). A private registry mirror that serves metadata WITHOUT per-version publish
|
|
54
|
+
# times does not fail: npm silently ignores --before there (measured against
|
|
55
|
+
# npm-pick-manifest), so the pin is inert on that mirror and the tree floats again.
|
|
56
|
+
#
|
|
57
|
+
# Renders OFF-TREE to a temp path and validates structurally BEFORE publishing:
|
|
58
|
+
# `likec4 export json` exits 0 even on an unresolved-reference / empty model, so
|
|
59
|
+
# an exit-0 check is NOT proof of a good artifact — see learnings
|
|
60
|
+
# 2026-06-05-external-cli-exit-0-is-not-proof-validate-the-artifact.md and
|
|
61
|
+
# apps/web-platform/server/c4-render.ts. Three publish gates below: a clean
|
|
62
|
+
# diagnostic stream, a non-empty object-typed elements map, and a non-empty
|
|
63
|
+
# object-typed views map — so neither a broken .c4 source nor a failed layout
|
|
64
|
+
# can clobber the good committed artifact.
|
|
65
|
+
#
|
|
66
|
+
# WRITES EXACTLY ONE FILE, the output path. The merge resolver commits whatever this
|
|
67
|
+
# changes, and asserts nothing else moved (resolve-regenerable-conflicts.sh, D4).
|
|
68
|
+
#
|
|
69
|
+
# Idempotent: rerunning against unchanged sources produces byte-identical output.
|
|
70
|
+
|
|
71
|
+
set -euo pipefail
|
|
72
|
+
|
|
73
|
+
LIKEC4_VERSION="1.50.0"
|
|
74
|
+
LIKEC4_BEFORE="2026-09-28"
|
|
75
|
+
|
|
76
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
77
|
+
CANONICAL_CLI="$SCRIPT_DIR/../lib/c4-canonical-cli.mjs"
|
|
78
|
+
ROOT=""
|
|
79
|
+
OUT=""
|
|
80
|
+
|
|
81
|
+
while [[ $# -gt 0 ]]; do
|
|
82
|
+
case "$1" in
|
|
83
|
+
--help)
|
|
84
|
+
sed -n '2,/^$/s/^# \{0,1\}//p' "${BASH_SOURCE[0]}"
|
|
85
|
+
exit 0
|
|
86
|
+
;;
|
|
87
|
+
--root)
|
|
88
|
+
[[ -n "${2:-}" ]] || { echo "ERROR: --root requires a DIR argument" >&2; exit 2; }
|
|
89
|
+
ROOT="$2"
|
|
90
|
+
shift 2
|
|
91
|
+
;;
|
|
92
|
+
--out)
|
|
93
|
+
[[ -n "${2:-}" ]] || { echo "ERROR: --out requires a PATH argument" >&2; exit 2; }
|
|
94
|
+
OUT="$2"
|
|
95
|
+
shift 2
|
|
96
|
+
;;
|
|
97
|
+
*)
|
|
98
|
+
echo "ERROR: unknown argument: $1 (try --help)" >&2
|
|
99
|
+
exit 2
|
|
100
|
+
;;
|
|
101
|
+
esac
|
|
102
|
+
done
|
|
103
|
+
|
|
104
|
+
if [[ -z "$ROOT" ]]; then
|
|
105
|
+
ROOT="$(git rev-parse --show-toplevel 2>/dev/null)" \
|
|
106
|
+
|| { echo "ERROR: not inside a git work tree and no --root given" >&2; exit 2; }
|
|
107
|
+
fi
|
|
108
|
+
ROOT="$(cd "$ROOT" 2>/dev/null && pwd)" || { echo "ERROR: --root is not a directory" >&2; exit 2; }
|
|
109
|
+
DIAGRAMS_DIR="$ROOT/knowledge-base/engineering/architecture/diagrams"
|
|
110
|
+
[[ -n "$OUT" ]] || OUT="$DIAGRAMS_DIR/model.likec4.json"
|
|
111
|
+
|
|
112
|
+
if [[ ! -d "$DIAGRAMS_DIR" ]]; then
|
|
113
|
+
echo "ERROR: diagrams directory not found at $DIAGRAMS_DIR" >&2
|
|
114
|
+
exit 1
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
# Guard: at least one DSL source. NOT "spec.c4 + model.c4 + views.c4": soleur:sync writes
|
|
118
|
+
# generated-components.c4, spec.c4 and views.c4 into a customer repo and never model.c4
|
|
119
|
+
# (that one belongs to soleur:architecture), so the all-three form refused every plainly
|
|
120
|
+
# synced repo. What makes a render trustworthy is the two gates below, not a file list.
|
|
121
|
+
# Every extension likec4 1.50.0 compiles, at any depth — likec4 walks the whole directory.
|
|
122
|
+
if [[ -z "$(find "$DIAGRAMS_DIR" -type f \( -name '*.c4' -o -name '*.likec4' -o -name '*.like-c4' \) -print -quit)" ]]; then
|
|
123
|
+
echo "ERROR: no .c4 source (*.c4, *.likec4 or *.like-c4) in $DIAGRAMS_DIR" >&2
|
|
124
|
+
exit 1
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
[[ -f "$CANONICAL_CLI" ]] || { echo "ERROR: canonicalizer not found beside this script at $CANONICAL_CLI" >&2; exit 1; }
|
|
128
|
+
|
|
129
|
+
# A missing tool is a machine problem, not a fault in the .c4 source: name it (rc 2, like a usage error).
|
|
130
|
+
for _tool in jq node npx mktemp; do
|
|
131
|
+
command -v "$_tool" >/dev/null 2>&1 \
|
|
132
|
+
|| { echo "ERROR: rendering the C4 model needs jq, node and npx on PATH; '$_tool' is missing" >&2; exit 2; }
|
|
133
|
+
done
|
|
134
|
+
|
|
135
|
+
TMP="$(mktemp -d)"
|
|
136
|
+
PUBLISH_TMP=""
|
|
137
|
+
trap 'rm -rf "$TMP"; [[ -n "$PUBLISH_TMP" ]] && rm -f "$PUBLISH_TMP"' EXIT
|
|
138
|
+
RENDER_LOG="$TMP/render.log"
|
|
139
|
+
|
|
140
|
+
# Render off-tree with the pinned CLI, capturing all diagnostics. A non-zero
|
|
141
|
+
# exit is a hard failure; but likec4 ALSO exits 0 on broken sources, so the
|
|
142
|
+
# exit code alone is never sufficient (see the three gates below).
|
|
143
|
+
# CI is UNSET for the child and colour forced off: under CI likec4 switches to a timestamped,
|
|
144
|
+
# ANSI-coloured reporter that the anchored DIAG_RE below cannot match, and a syntax error
|
|
145
|
+
# would then publish a truncated model at rc 0 (measured under CI=true). ANSI is also
|
|
146
|
+
# stripped from the log as a second line of defence.
|
|
147
|
+
if ! ( cd "$DIAGRAMS_DIR" && env -u CI -u FORCE_COLOR NO_COLOR=1 npx -y --ignore-scripts --before="${LIKEC4_BEFORE}" "likec4@${LIKEC4_VERSION}" export json --no-use-dot -o "$TMP/model.likec4.json" . ) >"$RENDER_LOG" 2>&1; then
|
|
148
|
+
echo "ERROR: likec4 export exited non-zero — refusing to overwrite $OUT" >&2
|
|
149
|
+
cat "$RENDER_LOG" >&2
|
|
150
|
+
exit 1
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
# exit-0 is NOT proof. likec4@1.50.0 has TWO source-fault modes that both exit 0:
|
|
154
|
+
# (1) unresolved reference / missing spec.c4 -> an EMPTY-elements model
|
|
155
|
+
# (the #4966 case; see apps/web-platform/server/c4-render.ts).
|
|
156
|
+
# (2) a syntax error -> likec4 recovers by dropping the bad fragment, prints
|
|
157
|
+
# `Invalid <file>` + `Line N:` (or `Could not resolve …`), and STILL emits
|
|
158
|
+
# a non-empty (now-incomplete) model — so element-count alone misses it.
|
|
159
|
+
# Gate on ALL of: a clean diagnostic stream, a non-empty elements map, and a
|
|
160
|
+
# non-empty views map. Element-count is the version-robust backstop; the
|
|
161
|
+
# diagnostic grep catches mode (2); the views gate catches the container/
|
|
162
|
+
# graphviz-fallback shape (#8861). On error we never publish, so a broken .c4
|
|
163
|
+
# can never clobber the good committed artifact.
|
|
164
|
+
# Anchors keep the markers off the workspace-path line likec4 echoes (`workspace:
|
|
165
|
+
# /abs/path …`): `^Invalid ` and the indented `Line N:` form (` Line 274:`)
|
|
166
|
+
# can't match a repo path, so a checkout dir containing those substrings can't
|
|
167
|
+
# false-FAIL. `Could not resolve` is a distinctive likec4 phrase.
|
|
168
|
+
DIAG_RE='^([0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)? +[A-Z]+ +[^ ]+ +)?Invalid |Could not resolve|^[[:space:]]+Line [0-9]+:'
|
|
169
|
+
_esc="$(printf '\033')"
|
|
170
|
+
sed "s/${_esc}\[[0-9;]*m//g" "$RENDER_LOG" >"$RENDER_LOG.plain" && mv -f "$RENDER_LOG.plain" "$RENDER_LOG"
|
|
171
|
+
if grep -qE "$DIAG_RE" "$RENDER_LOG"; then
|
|
172
|
+
echo "ERROR: likec4 reported a source validation error — refusing to overwrite $OUT" >&2
|
|
173
|
+
grep -E "$DIAG_RE" "$RENDER_LOG" >&2
|
|
174
|
+
echo " Fix the .c4 source (run: cd $DIAGRAMS_DIR && npx -y likec4@${LIKEC4_VERSION} validate --no-use-dot .)" >&2
|
|
175
|
+
exit 1
|
|
176
|
+
fi
|
|
177
|
+
if ! jq -e '(.elements | objects | length) > 0' "$TMP/model.likec4.json" >/dev/null 2>&1; then
|
|
178
|
+
echo "ERROR: likec4 produced an empty/degenerate model — refusing to overwrite $OUT" >&2
|
|
179
|
+
echo " Fix the .c4 source (run: cd $DIAGRAMS_DIR && npx -y likec4@${LIKEC4_VERSION} validate --no-use-dot .)" >&2
|
|
180
|
+
exit 1
|
|
181
|
+
fi
|
|
182
|
+
# Elements-but-no-views is OUR layout failing, never the user's source (#8740):
|
|
183
|
+
# a successful layout always emits at least `index`, even with no `views {}`
|
|
184
|
+
# block. `objects | length` shares the server's plain-object semantics — a
|
|
185
|
+
# non-object `views` (string/array) counts 0 here as it does in
|
|
186
|
+
# c4ModelCounts/plainObjectSize — so a malformed export is refused, not
|
|
187
|
+
# published. Keep both writers' predicates strict in lockstep.
|
|
188
|
+
if ! jq -e '(.views | objects | length) > 0' "$TMP/model.likec4.json" >/dev/null 2>&1; then
|
|
189
|
+
echo "ERROR: likec4 produced a model with elements but no views — a layout failure, not a .c4 source fault — refusing to overwrite $OUT" >&2
|
|
190
|
+
tail -20 "$RENDER_LOG" >&2
|
|
191
|
+
echo " Do NOT edit the .c4 source: retry the render; if it persists, reproduce with: cd $DIAGRAMS_DIR && npx -y likec4@${LIKEC4_VERSION} export json --no-use-dot ." >&2
|
|
192
|
+
exit 1
|
|
193
|
+
fi
|
|
194
|
+
|
|
195
|
+
# Canonicalize AFTER all gates (never instead of them): one JSON value per
|
|
196
|
+
# line with every view `hash` blanked, so git can merge two regenerations whose
|
|
197
|
+
# edits touch different values (ADR-235, #8542). Node serializes, never jq —
|
|
198
|
+
# jq reformats numbers. The web app (c4-render.ts) and the plugin
|
|
199
|
+
# (generate-c4-from-components.ts) emit these same bytes through the same
|
|
200
|
+
# module, so no writer reformats another's file.
|
|
201
|
+
if ! node "$CANONICAL_CLI" "$TMP/model.likec4.json" >"$TMP/canonical.json"; then
|
|
202
|
+
echo "ERROR: could not canonicalize the rendered model — refusing to overwrite $OUT" >&2
|
|
203
|
+
exit 1
|
|
204
|
+
fi
|
|
205
|
+
|
|
206
|
+
# Publish only on success, atomically: copy into the destination directory then
|
|
207
|
+
# rename. An intra-filesystem rename is atomic, so a crash mid-write can never
|
|
208
|
+
# leave a truncated model.likec4.json on the tracked path (a bare `cp` onto $OUT
|
|
209
|
+
# is not atomic). The temp lands beside $OUT (a dotfile, never a tracked .c4) so
|
|
210
|
+
# the rename stays on one filesystem; the EXIT trap reaps it if cp/mv aborts.
|
|
211
|
+
OUT_DIR="$(dirname "$OUT")"
|
|
212
|
+
mkdir -p "$OUT_DIR"
|
|
213
|
+
PUBLISH_TMP="$(mktemp "$OUT_DIR/.model.likec4.json.XXXXXX")"
|
|
214
|
+
cp "$TMP/canonical.json" "$PUBLISH_TMP"
|
|
215
|
+
mv -f "$PUBLISH_TMP" "$OUT"
|
|
216
|
+
PUBLISH_TMP="" # renamed onto $OUT — nothing left for the trap to clean
|
|
217
|
+
echo "Regenerated $OUT ($(jq '.elements | length' "$OUT") elements, $(jq '.relations | length' "$OUT") relations, $(jq '.views | length' "$OUT") views)"
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# resolve-git-root.sh -- Sourceable helper to detect bare repos and resolve GIT_ROOT
|
|
4
|
+
#
|
|
5
|
+
# Usage: source this file. It sets GIT_ROOT, GIT_COMMON_ROOT, and IS_BARE.
|
|
6
|
+
# Do NOT execute directly.
|
|
7
|
+
#
|
|
8
|
+
# Variables set:
|
|
9
|
+
# GIT_ROOT -- absolute path to the repository root (bare or non-bare)
|
|
10
|
+
# GIT_COMMON_ROOT -- absolute path to the shared repo root across all worktrees
|
|
11
|
+
# (equals GIT_ROOT when not in a worktree)
|
|
12
|
+
# IS_BARE -- "true" or "false"
|
|
13
|
+
#
|
|
14
|
+
# On error (not inside a git repo), returns 1 without calling exit.
|
|
15
|
+
# Does not call set or modify the caller's shell options.
|
|
16
|
+
|
|
17
|
+
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
18
|
+
echo "Error: resolve-git-root.sh must be sourced, not executed." >&2
|
|
19
|
+
echo "Usage: source path/to/resolve-git-root.sh" >&2
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
IS_BARE=false
|
|
24
|
+
if [[ "$(git rev-parse --is-bare-repository 2>/dev/null)" == "true" ]]; then
|
|
25
|
+
IS_BARE=true
|
|
26
|
+
_resolve_git_dir=$(git rev-parse --absolute-git-dir 2>/dev/null)
|
|
27
|
+
if [[ "$_resolve_git_dir" == */.git ]]; then
|
|
28
|
+
GIT_ROOT="${_resolve_git_dir%/.git}"
|
|
29
|
+
else
|
|
30
|
+
GIT_ROOT="$_resolve_git_dir"
|
|
31
|
+
fi
|
|
32
|
+
unset _resolve_git_dir
|
|
33
|
+
else
|
|
34
|
+
GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null) || {
|
|
35
|
+
echo "Error: Not inside a git repository." >&2
|
|
36
|
+
return 1
|
|
37
|
+
}
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Validate that GIT_ROOT resolves to an actual directory
|
|
41
|
+
if [[ ! -d "$GIT_ROOT" ]]; then
|
|
42
|
+
echo "Error: GIT_ROOT resolved to non-existent path: $GIT_ROOT" >&2
|
|
43
|
+
return 1
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# Resolve common root (shared across worktrees)
|
|
47
|
+
# git rev-parse --git-common-dir returns the shared .git dir; may be relative,
|
|
48
|
+
# so cd+pwd resolves to absolute. Strip trailing /.git for the repo root.
|
|
49
|
+
_resolve_common_dir=$(cd "$(git rev-parse --git-common-dir 2>/dev/null)" && pwd)
|
|
50
|
+
if [[ "$_resolve_common_dir" == */.git ]]; then
|
|
51
|
+
GIT_COMMON_ROOT="${_resolve_common_dir%/.git}"
|
|
52
|
+
else
|
|
53
|
+
GIT_COMMON_ROOT="$_resolve_common_dir"
|
|
54
|
+
fi
|
|
55
|
+
unset _resolve_common_dir
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# resolve-regenerable-conflicts.sh — complete a merge whose ONLY conflicts are on generated
|
|
3
|
+
# artifacts, by regenerating them from the merged sources.
|
|
4
|
+
#
|
|
5
|
+
# Usage: bash "${CLAUDE_PLUGIN_ROOT}/scripts/resolve-regenerable-conflicts.sh" <base-ref>
|
|
6
|
+
# (run from inside the repository being merged)
|
|
7
|
+
#
|
|
8
|
+
# WHY THIS EXISTS (#8377, ADR-235). A generated file that is COMMITTED conflicts with every
|
|
9
|
+
# other branch that regenerates it, and side-picking is always wrong: `--ours` and `--theirs`
|
|
10
|
+
# each produce an artifact that matches neither side's sources. The correct resolution is to
|
|
11
|
+
# take the merged SOURCES and re-run the generator over them. The one such product is
|
|
12
|
+
# knowledge-base/engineering/architecture/diagrams/model.likec4.json, which the web-platform C4
|
|
13
|
+
# viewer fetches as a committed blob (apps/web-platform/app/api/kb/c4/project/route.ts).
|
|
14
|
+
#
|
|
15
|
+
# ── THE CONTRACT: TWO OUTCOMES ─────────────────────────────────────────────────────────────
|
|
16
|
+
# exit 0 the merge completed and was COMMITTED. The caller may push.
|
|
17
|
+
# exit non-0 nothing was touched. The tree is byte-identical to entry.
|
|
18
|
+
# Every exit prints one stdout line `SOLEUR_REGEN_ON_CONFLICT … rc=N` (rc=1 carries
|
|
19
|
+
# class=na|failed|interrupted and a reason slug) and, on refusal, one human line on stderr
|
|
20
|
+
# prefixed `[regen-on-conflict]` naming the next action.
|
|
21
|
+
#
|
|
22
|
+
# ── HOW: RENDER FROM GIT OBJECTS FIRST, TOUCH THE WORKTREE LAST (ADR-235 amendment 2026-09-23)
|
|
23
|
+
# 1. `git merge-tree` computes the merge without touching anything and yields the merged TREE.
|
|
24
|
+
# 2. The tracked, cleanly-merged LikeC4 sources are copied out of that tree's OBJECTS into a
|
|
25
|
+
# private staging dir, and the renderer runs there. Nothing untracked, ignored, symlinked
|
|
26
|
+
# or configured in the worktree can reach the render, and the renderer cannot write the
|
|
27
|
+
# worktree. Every render failure, timeout or kill therefore happens with the tree untouched.
|
|
28
|
+
# 3. Only then: re-check nothing moved, `git merge --no-commit`, write the rendered bytes,
|
|
29
|
+
# assert the index is exactly the merged tree plus those bytes, commit, and assert no commit
|
|
30
|
+
# hook changed the result.
|
|
31
|
+
#
|
|
32
|
+
# NEVER PUSHES — callers own the push. NO LOCK — per-worktree index/HEAD/MERGE_HEAD serialise
|
|
33
|
+
# runs within a worktree; the HEAD and clean-tree re-checks make a lost race refuse.
|
|
34
|
+
set -uo pipefail
|
|
35
|
+
|
|
36
|
+
# The PLUGIN directory: this script's own, made absolute before any `cd` (ADR-179 A17).
|
|
37
|
+
_plugin_scripts_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd -P)" || _plugin_scripts_dir=""
|
|
38
|
+
readonly PLUGIN_SCRIPTS_DIR="$_plugin_scripts_dir"
|
|
39
|
+
|
|
40
|
+
# Shared context-sanitize lib (#10395), beside this script under lib/. When it
|
|
41
|
+
# is unreadable the same-name fallbacks carry each site's pre-change strip set —
|
|
42
|
+
# never weaker than today.
|
|
43
|
+
_ctx_lib="${PLUGIN_SCRIPTS_DIR:-/nonexistent}/lib/context-sanitize.sh"
|
|
44
|
+
# shellcheck source=/dev/null
|
|
45
|
+
[[ -r "$_ctx_lib" ]] && . "$_ctx_lib" || true
|
|
46
|
+
declare -F soleur_ctx_sanitize >/dev/null 2>&1 \
|
|
47
|
+
|| soleur_ctx_sanitize() { LC_ALL=C tr -d '\000-\037\177'; }
|
|
48
|
+
declare -F soleur_ctx_sanitize_nl >/dev/null 2>&1 \
|
|
49
|
+
|| soleur_ctx_sanitize_nl() { LC_ALL=C tr -d '\000-\011\013-\037\177'; }
|
|
50
|
+
# The REPO: the caller's, from the CWD — never BASH_SOURCE/../.., which is the plugin.
|
|
51
|
+
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)"
|
|
52
|
+
|
|
53
|
+
# The render budget, matching generate-c4-from-components.ts (a cold npx install measured 151s).
|
|
54
|
+
REGEN_TIMEOUT_S=600
|
|
55
|
+
BASE=""; BASE_SHA=""; HEAD_SHA=""; ARM=""; ROOT_SRC="-"
|
|
56
|
+
WORK=""; RENDER_PID=""; MERGING=0
|
|
57
|
+
|
|
58
|
+
# One line per exit for machines (stdout), one for humans (stderr).
|
|
59
|
+
_marker() { printf 'SOLEUR_REGEN_ON_CONFLICT rc=1 class=%s reason=%s\n' "$1" "$2"; }
|
|
60
|
+
# Strip control characters: the tail of a renderer log is attacker-influenced text.
|
|
61
|
+
_clean() { soleur_ctx_sanitize_nl | tail -n 4 | tr '\n' '|' | sed 's/|$//; s/|/ | /g'; }
|
|
62
|
+
|
|
63
|
+
# na <slug> <message> — refuse before anything was touched.
|
|
64
|
+
na() { _marker na "$1"; echo "[regen-on-conflict] not applicable: $2" >&2; exit 1; }
|
|
65
|
+
# fail <slug> <message> — a regeneration problem, still before anything was touched.
|
|
66
|
+
fail() { _marker failed "$1"; echo "[regen-on-conflict] regen failed: $2" >&2; exit 1; }
|
|
67
|
+
# bail <slug> <message> — refuse AFTER the merge started: unwind, and VERIFY the unwind.
|
|
68
|
+
# BAIL_CLASS is `failed` except for a signal, which reports `interrupted` wherever it lands.
|
|
69
|
+
BAIL_CLASS=failed
|
|
70
|
+
bail() {
|
|
71
|
+
_marker "$BAIL_CLASS" "$1"
|
|
72
|
+
local unwound="merge aborted, nothing committed"
|
|
73
|
+
[[ -n "$REPO_ROOT" ]] && git -C "$REPO_ROOT" merge --abort 2>/dev/null
|
|
74
|
+
if [[ -n "$REPO_ROOT" && -f "$(git -C "$REPO_ROOT" rev-parse --git-dir 2>/dev/null)/MERGE_HEAD" ]]; then
|
|
75
|
+
unwound="could NOT unwind: a merge is still in progress — run: git merge --abort"
|
|
76
|
+
fi
|
|
77
|
+
echo "[regen-on-conflict] regen failed: $2 — $unwound" >&2
|
|
78
|
+
exit 1
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# Canonical copy of test-helpers.sh's assert_fixture_dir (P1a pins every tracked copy byte-equal;
|
|
82
|
+
# the P1b scanner recognises only this name). Here it backstops the staging parent, which the
|
|
83
|
+
# explicit `case` before it already refuses with a marker — its bare exit 2 is not reached.
|
|
84
|
+
assert_fixture_dir() {
|
|
85
|
+
case "${1-}" in
|
|
86
|
+
"") printf 'FATAL: fixture dir is EMPTY; git -C "" would operate on %s\n' "$PWD" >&2; exit 2 ;;
|
|
87
|
+
*/../*|*/..) printf 'FATAL: fixture dir %s contains ..; refusing\n' "$1" >&2; exit 2 ;;
|
|
88
|
+
/proc/*|/sys/*|/dev/*) printf 'FATAL: fixture dir %s is a synthetic-fs path; refusing\n' "$1" >&2; exit 2 ;;
|
|
89
|
+
/|//|/.) printf 'FATAL: fixture dir resolves to the filesystem root; refusing\n' >&2; exit 2 ;;
|
|
90
|
+
/*) : ;;
|
|
91
|
+
*) printf 'FATAL: fixture dir %s is RELATIVE; refusing\n' "$1" >&2; exit 2 ;;
|
|
92
|
+
esac
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
_cleanup() {
|
|
96
|
+
[[ -n "$RENDER_PID" ]] && kill -TERM "$RENDER_PID" 2>/dev/null
|
|
97
|
+
[[ -n "$WORK" && -d "$WORK" ]] && rm -rf -- "$WORK"
|
|
98
|
+
}
|
|
99
|
+
_on_signal() {
|
|
100
|
+
if [[ "$MERGING" -eq 1 ]]; then
|
|
101
|
+
BAIL_CLASS=interrupted; bail interrupted "interrupted during the merge"
|
|
102
|
+
fi
|
|
103
|
+
_cleanup
|
|
104
|
+
_marker interrupted signal
|
|
105
|
+
echo "[regen-on-conflict] interrupted — nothing was touched; re-run when ready" >&2
|
|
106
|
+
exit 1
|
|
107
|
+
}
|
|
108
|
+
trap _cleanup EXIT
|
|
109
|
+
trap _on_signal INT TERM HUP
|
|
110
|
+
|
|
111
|
+
[[ -n "$REPO_ROOT" ]] || na not-a-repo "not inside a git work tree — cd into the repository being merged and re-run"
|
|
112
|
+
|
|
113
|
+
# plugin_root -> sets PLUGIN_ROOT and ROOT_SRC (no subshell, so both survive), or returns 1 with
|
|
114
|
+
# the reason in PLUGIN_ROOT_WHY. The sibling wins; a bare ${CLAUDE_PLUGIN_ROOT}
|
|
115
|
+
# (no `:-`, ADR-179 A12) is read only when it is absent. The plugin.json check is a sanity
|
|
116
|
+
# check, not a boundary (ADR-179 A11, A17).
|
|
117
|
+
PLUGIN_ROOT=""; PLUGIN_ROOT_WHY=""
|
|
118
|
+
plugin_root() {
|
|
119
|
+
local root=""
|
|
120
|
+
if [[ -n "$PLUGIN_SCRIPTS_DIR" && -f "$PLUGIN_SCRIPTS_DIR/render-c4-model.sh" ]]; then
|
|
121
|
+
root="$(cd "$PLUGIN_SCRIPTS_DIR/.." 2>/dev/null && pwd -P)" || root=""
|
|
122
|
+
ROOT_SRC="sibling"
|
|
123
|
+
elif [[ -n "${CLAUDE_PLUGIN_ROOT+set}" && "${CLAUDE_PLUGIN_ROOT}" == /* ]]; then
|
|
124
|
+
root="$(cd "${CLAUDE_PLUGIN_ROOT}" 2>/dev/null && pwd -P)" || root=""
|
|
125
|
+
ROOT_SRC="env"
|
|
126
|
+
if [[ -z "$root" || ! -f "$root/scripts/render-c4-model.sh" ]]; then
|
|
127
|
+
PLUGIN_ROOT_WHY="CLAUDE_PLUGIN_ROOT=${CLAUDE_PLUGIN_ROOT} has no scripts/render-c4-model.sh"
|
|
128
|
+
return 1
|
|
129
|
+
fi
|
|
130
|
+
else
|
|
131
|
+
PLUGIN_ROOT_WHY="no render-c4-model.sh beside this resolver and no absolute CLAUDE_PLUGIN_ROOT"
|
|
132
|
+
return 1
|
|
133
|
+
fi
|
|
134
|
+
[[ -n "$root" ]] || { PLUGIN_ROOT_WHY="could not resolve the plugin root"; return 1; }
|
|
135
|
+
if ! grep -q '"name"[[:space:]]*:[[:space:]]*"soleur"' "$root/.claude-plugin/plugin.json" 2>/dev/null; then
|
|
136
|
+
PLUGIN_ROOT_WHY="$root/.claude-plugin/plugin.json does not name soleur"
|
|
137
|
+
return 1
|
|
138
|
+
fi
|
|
139
|
+
PLUGIN_ROOT="$root"
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
# ── THE RESOLVABLE SET ─────────────────────────────────────────────────────────────────────
|
|
143
|
+
# One hardcoded member, not a manifest (ADR-235: a manifest is a parse surface and invites
|
|
144
|
+
# re-tracking generated files). The test seam is ARGV-only (--test-resolvable <tsv>): an
|
|
145
|
+
# inherited env var reaching an unattended commit was a demonstrated command channel (#8384).
|
|
146
|
+
# Each argv-producing line carries an ARGV-SOURCE marker; the suite pins the set. An arm's argv
|
|
147
|
+
# is a PREFIX: the resolver appends `--root <staging> --out <file>`.
|
|
148
|
+
RESOLVABLE_PATHS=()
|
|
149
|
+
RESOLVABLE_ARGVS=() # one TAB-joined argv prefix per path, index-aligned with the above
|
|
150
|
+
if [[ "${1:-}" == "--test-resolvable" ]]; then
|
|
151
|
+
_tsv="${2:-}"
|
|
152
|
+
[[ -f "$_tsv" ]] || na bad-args "--test-resolvable: '$_tsv' is not a file"
|
|
153
|
+
while IFS=$'\t' read -r _p _rest; do
|
|
154
|
+
[[ -n "$_p" ]] || continue
|
|
155
|
+
RESOLVABLE_PATHS+=("$_p"); RESOLVABLE_ARGVS+=("$_rest") # ARGV-SOURCE: test-seam
|
|
156
|
+
done < "$_tsv"
|
|
157
|
+
shift 2
|
|
158
|
+
ARM="test-seam"
|
|
159
|
+
else
|
|
160
|
+
RESOLVABLE_PATHS=("knowledge-base/engineering/architecture/diagrams/model.likec4.json") # RESOLVABLE-SET: default
|
|
161
|
+
ARM="plugin"
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
BASE="${1:-}"
|
|
165
|
+
[[ -n "$BASE" ]] || na bad-args "no base ref given — re-run as: resolve-regenerable-conflicts.sh <base-ref> (e.g. origin/main)"
|
|
166
|
+
cd "$REPO_ROOT" || na not-a-repo "cannot enter repo root $REPO_ROOT"
|
|
167
|
+
BASE_SHA="$(git rev-parse --verify --quiet "$BASE^{commit}")" \
|
|
168
|
+
|| na bad-base "base ref '$BASE' does not resolve to a commit — git fetch it first"
|
|
169
|
+
HEAD_SHA="$(git rev-parse --verify --quiet HEAD)" || na no-head "HEAD does not resolve to a commit"
|
|
170
|
+
|
|
171
|
+
# _clean_or_why -> empty when the tree is clean for our purposes, else the reason.
|
|
172
|
+
# MERGE_HEAD first (its remedy differs). `-uall` so status.showUntrackedFiles=no cannot hide an
|
|
173
|
+
# untracked file; `--ignored` is NOT used — ignored files are invisible to the merge unless the
|
|
174
|
+
# merged tree adds the same path, which _collisions checks.
|
|
175
|
+
_clean_or_why() {
|
|
176
|
+
[[ ! -f "$(git rev-parse --git-dir)/MERGE_HEAD" ]] || { printf 'a merge is already in progress — finish it or run git merge --abort'; return; }
|
|
177
|
+
local st; st="$(git status --porcelain --untracked-files=all)"
|
|
178
|
+
[[ -z "$st" ]] || printf 'working tree is not clean (%s) — commit or discard your changes' \
|
|
179
|
+
"$(printf '%s\n' "$st" | head -n1 | cut -c4- | soleur_ctx_sanitize | cut -c1-200)"
|
|
180
|
+
}
|
|
181
|
+
_why="$(_clean_or_why)"; [[ -z "$_why" ]] || na dirty-tree "$_why, then re-run"
|
|
182
|
+
|
|
183
|
+
# ── CLASSIFY: merge-tree, NUL-framed ───────────────────────────────────────────────────────
|
|
184
|
+
# A relative XDG_CACHE_HOME is invalid and ignored (XDG Base Directory spec): relative to which cwd?
|
|
185
|
+
_cache="${XDG_CACHE_HOME:-}"; [[ "$_cache" == /* ]] || _cache="${HOME:-/nonexistent}/.cache"
|
|
186
|
+
case "$_cache" in
|
|
187
|
+
*/../*|*/..|/proc/*|/sys/*|/dev/*|/|//|/.) fail no-staging "unusable cache dir for staging ($_cache) — set XDG_CACHE_HOME to a normal absolute directory" ;;
|
|
188
|
+
/*) : ;;
|
|
189
|
+
*) fail no-staging "HOME is not an absolute path ($_cache)" ;;
|
|
190
|
+
esac
|
|
191
|
+
assert_fixture_dir "$_cache"
|
|
192
|
+
WORK_PARENT="$_cache/soleur"
|
|
193
|
+
if mkdir -p "$WORK_PARENT" 2>/dev/null && chmod 700 "$WORK_PARENT" 2>/dev/null && WORK="$(mktemp -d "$WORK_PARENT/regen.XXXXXX")"; then :
|
|
194
|
+
else fail no-staging "cannot create a private staging dir under $WORK_PARENT"; fi
|
|
195
|
+
chmod 700 "$WORK"
|
|
196
|
+
|
|
197
|
+
mt_rc=0
|
|
198
|
+
git merge-tree --write-tree -z --name-only "$BASE_SHA" "$HEAD_SHA" >"$WORK/mt" 2>"$WORK/mt.err" || mt_rc=$?
|
|
199
|
+
[[ "$mt_rc" -ne 0 ]] || na no-conflict "no conflict between HEAD and $BASE — nothing to resolve; merge it normally"
|
|
200
|
+
if [[ "$mt_rc" -ge 2 ]]; then
|
|
201
|
+
grep -q 'unknown option\|usage: git merge-tree' "$WORK/mt.err" 2>/dev/null \
|
|
202
|
+
&& na old-git "git merge-tree --write-tree needs git >= 2.38 (you have $(git --version | cut -d' ' -f3)) — upgrade git, or resolve by hand"
|
|
203
|
+
na merge-tree-failed "git merge-tree failed (rc=$mt_rc): $(_clean <"$WORK/mt.err")"
|
|
204
|
+
fi
|
|
205
|
+
|
|
206
|
+
# Records: <tree> NUL, conflicted paths NUL…, empty NUL, then messages as
|
|
207
|
+
# <N> NUL <N paths> NUL <type> NUL <text> NUL. Only a CONFLICT (contents) is resolvable: every
|
|
208
|
+
# other kind (modify/delete, rename/rename, add/add, distinct types) decides whether a file
|
|
209
|
+
# should EXIST, which regenerating cannot answer.
|
|
210
|
+
TREE=""; conflicted=(); content_ok=$'\x1f'
|
|
211
|
+
_state=tree; _n=0; _mpaths=()
|
|
212
|
+
while IFS= read -r -d '' rec; do
|
|
213
|
+
case "$_state" in
|
|
214
|
+
tree) TREE="$rec"; _state=paths ;;
|
|
215
|
+
paths) if [[ -z "$rec" ]]; then _state=count; else conflicted+=("$rec"); fi ;;
|
|
216
|
+
count)
|
|
217
|
+
_n="$rec"; _mpaths=()
|
|
218
|
+
[[ "$_n" =~ ^[0-9]+$ ]] || na merge-tree-format "unparseable merge-tree output"
|
|
219
|
+
if [[ "$_n" -eq 0 ]]; then _state="type"; else _state="mpath"; fi ;;
|
|
220
|
+
mpath) _mpaths+=("$rec"); [[ "${#_mpaths[@]}" -lt "$_n" ]] || _state="type" ;;
|
|
221
|
+
type) _type="$rec"; _state=text ;;
|
|
222
|
+
text)
|
|
223
|
+
case "$_type" in
|
|
224
|
+
"CONFLICT (contents)") for _mp in ${_mpaths[@]+"${_mpaths[@]}"}; do content_ok+="$_mp"$'\x1f'; done ;;
|
|
225
|
+
CONFLICT*) na unresolvable-kind "$(printf '%s' "$rec" | _clean) — resolve this merge by hand" ;;
|
|
226
|
+
esac
|
|
227
|
+
_state=count ;;
|
|
228
|
+
esac
|
|
229
|
+
done <"$WORK/mt"
|
|
230
|
+
[[ "$TREE" =~ ^[0-9a-f]{40,64}$ && "${#conflicted[@]}" -gt 0 ]] \
|
|
231
|
+
|| na merge-tree-format "merge-tree reported rc=$mt_rc but no conflicted path was parsed"
|
|
232
|
+
|
|
233
|
+
_argv_for() { # <path> -> echoes the TAB-joined argv prefix, or returns 1
|
|
234
|
+
local i
|
|
235
|
+
for i in "${!RESOLVABLE_PATHS[@]}"; do
|
|
236
|
+
[[ "${RESOLVABLE_PATHS[$i]}" == "$1" ]] && { printf '%s' "${RESOLVABLE_ARGVS[$i]:-}"; return 0; }
|
|
237
|
+
done
|
|
238
|
+
return 1
|
|
239
|
+
}
|
|
240
|
+
for p in "${conflicted[@]}"; do
|
|
241
|
+
[[ "$content_ok" == *$'\x1f'"$p"$'\x1f'* ]] \
|
|
242
|
+
|| na unresolvable-kind "$p is not a plain content conflict — resolve this merge by hand"
|
|
243
|
+
_argv_for "$p" >/dev/null || na not-regenerable "conflicted path is not regenerable: $p — resolve this merge by hand"
|
|
244
|
+
done
|
|
245
|
+
|
|
246
|
+
# The production arm is resolved only now that a regenerable conflict exists.
|
|
247
|
+
if [[ "$ARM" == "plugin" ]]; then
|
|
248
|
+
plugin_root \
|
|
249
|
+
|| fail no-plugin-root "no usable Soleur plugin root ($PLUGIN_ROOT_WHY) — set CLAUDE_PLUGIN_ROOT to the installed plugin (the directory whose .claude-plugin/plugin.json names soleur) and re-run"
|
|
250
|
+
RESOLVABLE_ARGVS=("$(printf 'bash\t%s' "$PLUGIN_ROOT/scripts/render-c4-model.sh")") # ARGV-SOURCE: plugin
|
|
251
|
+
fi
|
|
252
|
+
|
|
253
|
+
# ── STAGE: tracked sources out of the merged tree's objects ────────────────────────────────
|
|
254
|
+
# Allowlist, not blocklist: only regular-file LikeC4 sources are copied. A symlink or gitlink
|
|
255
|
+
# anywhere under the directory, or a likec4 config (which likec4 would load, the js/ts forms as
|
|
256
|
+
# code), is REFUSED rather than skipped — rendering without it would not be the repo's model.
|
|
257
|
+
assert_fixture_dir "$_cache"; assert_fixture_dir "$REPO_ROOT" # re-stated for fixture-scan's window
|
|
258
|
+
STAGE="$WORK/root"; OUT="$WORK/out"; mkdir -p "$STAGE" "$OUT"
|
|
259
|
+
_staged_dirs=$'\x1f'
|
|
260
|
+
for p in "${conflicted[@]}"; do
|
|
261
|
+
_dir="$(dirname -- "$p")"
|
|
262
|
+
[[ "$_staged_dirs" == *$'\x1f'"$_dir"$'\x1f'* ]] && continue
|
|
263
|
+
_staged_dirs+="$_dir"$'\x1f'
|
|
264
|
+
git ls-tree -r -z --full-tree "$TREE" -- "$_dir/" >"$WORK/ls" 2>/dev/null \
|
|
265
|
+
|| fail stage-failed "could not list $_dir in the merged tree"
|
|
266
|
+
while IFS= read -r -d '' ent; do
|
|
267
|
+
_meta="${ent%%$'\t'*}"; _path="${ent#*$'\t'}"
|
|
268
|
+
_mode="${_meta%% *}"; _obj="${_meta##* }"
|
|
269
|
+
case "/$_path/" in */../*|*/./*) na unsafe-path "refusing path $_path in the merged tree" ;; esac
|
|
270
|
+
case "$_mode" in
|
|
271
|
+
120000) na symlink-source "$_path is a symlink in the merged tree — the renderer would follow it outside the merge; replace it with a regular file" ;;
|
|
272
|
+
160000) na gitlink-source "$_path is a submodule in the merged tree — its sources are not part of the merge" ;;
|
|
273
|
+
esac
|
|
274
|
+
case "${_path##*/}" in
|
|
275
|
+
likec4.config.*|.likec4rc|.likec4.config.json)
|
|
276
|
+
na likec4-config "$_path would configure the render (the .js/.ts forms run as code) — regenerate by hand" ;;
|
|
277
|
+
esac
|
|
278
|
+
[[ "$_mode" == 100644 || "$_mode" == 100755 ]] || continue
|
|
279
|
+
case "$_path" in
|
|
280
|
+
*.c4|*.likec4|*.like-c4)
|
|
281
|
+
mkdir -p "$STAGE/$(dirname -- "$_path")"
|
|
282
|
+
git cat-file blob "$_obj" >"$STAGE/$_path" || fail stage-failed "could not read $_path from the merged tree"
|
|
283
|
+
chmod 600 "$STAGE/$_path" ;;
|
|
284
|
+
esac
|
|
285
|
+
done <"$WORK/ls"
|
|
286
|
+
done
|
|
287
|
+
for p in "${conflicted[@]}"; do
|
|
288
|
+
_m="$(git ls-tree -z --full-tree "$TREE" -- "$p" | cut -d' ' -f1)"
|
|
289
|
+
[[ "$_m" == 100644 || "$_m" == 100755 ]] || na not-a-file "$p is not a regular file in the merged tree — resolve this merge by hand"
|
|
290
|
+
done
|
|
291
|
+
|
|
292
|
+
# ── RENDER, in the background so a signal is handled at once ──────────────────────────────
|
|
293
|
+
_to=()
|
|
294
|
+
if command -v timeout >/dev/null 2>&1; then _to=(timeout -k 10 "$REGEN_TIMEOUT_S")
|
|
295
|
+
elif command -v gtimeout >/dev/null 2>&1; then _to=(gtimeout -k 10 "$REGEN_TIMEOUT_S"); fi
|
|
296
|
+
outs=()
|
|
297
|
+
for i in "${!conflicted[@]}"; do
|
|
298
|
+
p="${conflicted[$i]}"
|
|
299
|
+
IFS=$'\t' read -r -a _argv <<<"$(_argv_for "$p")"
|
|
300
|
+
[[ "${#_argv[@]}" -gt 0 ]] || fail empty-command "empty regeneration command for $p"
|
|
301
|
+
out="$OUT/$i"; outs+=("$out")
|
|
302
|
+
echo "[regen-on-conflict] regenerating $p (runs likec4 through npx; a cold cache takes minutes)" >&2
|
|
303
|
+
${_to[@]+"${_to[@]}"} "${_argv[@]}" --root "$STAGE" --out "$out" >"$WORK/log.$i" 2>&1 &
|
|
304
|
+
RENDER_PID=$!
|
|
305
|
+
_rc=0; wait "$RENDER_PID" || _rc=$?
|
|
306
|
+
RENDER_PID=""
|
|
307
|
+
if [[ "$_rc" -ne 0 ]]; then
|
|
308
|
+
_w="exited $_rc"; [[ "$_rc" -eq 124 && "${#_to[@]}" -gt 0 ]] && _w="timed out after ${REGEN_TIMEOUT_S}s"
|
|
309
|
+
fail render-failed "the renderer $_w for $p: $(_clean <"$WORK/log.$i")"
|
|
310
|
+
fi
|
|
311
|
+
[[ -s "$out" ]] || fail no-output "the renderer did not produce $p"
|
|
312
|
+
! grep -qE '^(<{7}|={7}|>{7})( |$)' -- "$out" || fail markers "the rendered $p still contains conflict markers"
|
|
313
|
+
done
|
|
314
|
+
|
|
315
|
+
# ── APPLY: only now is the worktree touched ────────────────────────────────────────────────
|
|
316
|
+
[[ "$(git rev-parse --verify --quiet HEAD)" == "$HEAD_SHA" ]] \
|
|
317
|
+
|| na head-moved "HEAD moved during the render — nothing was touched; re-run"
|
|
318
|
+
_why="$(_clean_or_why)"; [[ -z "$_why" ]] || na dirty-tree "the worktree changed during the render ($_why) — nothing was touched; re-run"
|
|
319
|
+
# A path the merge ADDS that exists on disk (untracked or ignored) would be overwritten.
|
|
320
|
+
while IFS= read -r -d '' _a; do
|
|
321
|
+
[[ -e "$_a" || -L "$_a" ]] && na would-overwrite "the merge adds $_a, which exists here untracked or ignored — move it aside and re-run"
|
|
322
|
+
done < <(git diff -z --name-only --diff-filter=A "$HEAD_SHA" "$TREE")
|
|
323
|
+
|
|
324
|
+
MERGING=1
|
|
325
|
+
merge_err="$(git merge --no-ff --no-commit -m "Merge $BASE (${BASE_SHA:0:12}); regenerated ${conflicted[*]}" "$BASE_SHA" 2>&1 >/dev/null)" || true
|
|
326
|
+
if [[ ! -f "$(git rev-parse --git-dir)/MERGE_HEAD" ]]; then
|
|
327
|
+
bail merge-not-started "the merge did not start: $(printf '%s' "${merge_err:-no output}" | _clean)"
|
|
328
|
+
fi
|
|
329
|
+
for i in "${!conflicted[@]}"; do
|
|
330
|
+
p="${conflicted[$i]}"
|
|
331
|
+
[[ ! -L "$p" ]] || bail symlink-artifact "refusing to write through symlink $p"
|
|
332
|
+
cp -- "$OUT/$i" "$REPO_ROOT/$p" && git add -- "$p" || bail stage-failed "could not write $p"
|
|
333
|
+
[[ "$(git rev-parse ":$p")" == "$(git hash-object --path="$p" -- "${outs[$i]}")" ]] \
|
|
334
|
+
|| bail staged-mismatch "the staged $p is not the rendered bytes"
|
|
335
|
+
done
|
|
336
|
+
[[ -z "$(git diff --name-only --diff-filter=U)" ]] || bail residual-conflict "conflicts remain after regeneration"
|
|
337
|
+
# The index must be exactly the merged tree plus the regenerated paths — nothing else.
|
|
338
|
+
_want="$(printf '%s\n' "${conflicted[@]}" | LC_ALL=C sort)"
|
|
339
|
+
_got="$(git diff --cached -z --name-only "$TREE" | tr '\0' '\n' | LC_ALL=C sort)"
|
|
340
|
+
[[ "$_got" == "$_want" ]] || bail index-mismatch "the index differs from the merged tree beyond the regenerated paths: $(printf '%s' "$_got" | _clean)"
|
|
341
|
+
|
|
342
|
+
_expect_tree="$(git write-tree)" || bail write-tree "could not write the index tree"
|
|
343
|
+
# From here a signal is RECORDED, not acted on: the commit either lands or fails on its own, and
|
|
344
|
+
# the marker must describe the repo as it is. The default disposition would exit with no marker.
|
|
345
|
+
_sig_late=""
|
|
346
|
+
trap '_sig_late=1' INT TERM HUP
|
|
347
|
+
commit_err="$(git commit --no-edit 2>&1 >/dev/null)" \
|
|
348
|
+
|| bail commit-failed "the merge commit failed: $(printf '%s' "$commit_err" | _clean)"
|
|
349
|
+
MERGING=0
|
|
350
|
+
if [[ "$(git rev-parse "HEAD^{tree}")" != "$_expect_tree" || "$(git rev-parse HEAD^1)" != "$HEAD_SHA" \
|
|
351
|
+
|| "$(git rev-parse HEAD^2 2>/dev/null)" != "$BASE_SHA" ]]; then
|
|
352
|
+
_undone="it was undone"
|
|
353
|
+
if ! git reset -q --keep "$HEAD_SHA" 2>/dev/null || [[ "$(git rev-parse HEAD)" != "$HEAD_SHA" ]]; then
|
|
354
|
+
_undone="could NOT undo it (reset --keep refused; the hook left local edits) — HEAD is the rejected merge commit; review, then run: git reset --keep $HEAD_SHA"
|
|
355
|
+
fi
|
|
356
|
+
_marker failed commit-hook-changed-tree
|
|
357
|
+
echo "[regen-on-conflict] regen failed: a commit hook changed the merge commit — $_undone; resolve by hand" >&2
|
|
358
|
+
exit 1
|
|
359
|
+
fi
|
|
360
|
+
[[ -z "$_sig_late" ]] || echo "[regen-on-conflict] a signal arrived during git commit; the commit had already completed and is verified" >&2
|
|
361
|
+
|
|
362
|
+
csv="$(IFS=,; printf '%s' "${conflicted[*]}")"
|
|
363
|
+
printf 'SOLEUR_REGEN_ON_CONFLICT paths=%s arm=%s root_src=%s rc=0\n' "$csv" "$ARM" "$ROOT_SRC"
|