@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,252 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Suite for plugins/soleur/scripts/sync-pr-behind.sh -- specifically its regenerable-conflict
|
|
3
|
+
# arm (#8377, ADR-235).
|
|
4
|
+
#
|
|
5
|
+
# ── SCOPE, STATED HONESTLY ──────────────────────────────────────────────────────────────────
|
|
6
|
+
# This covers the branch the resolver added and the two outcomes the caller must distinguish:
|
|
7
|
+
# resolver rc 0 -> the merge is already committed; DO NOT merge again; push; succeed.
|
|
8
|
+
# resolver non-zero -> today's behaviour, unchanged: exit 6 with a clean tree.
|
|
9
|
+
# It does NOT cover the gh-polling loop, the BEHIND cap, or exit 7 -- those predate this change
|
|
10
|
+
# and have no suite; adding one is not this PR's subject. Saying so beats implying otherwise by
|
|
11
|
+
# a suite name that suggests whole-script coverage.
|
|
12
|
+
#
|
|
13
|
+
# ── HOW THE SEAM IS BUILT ───────────────────────────────────────────────────────────────────
|
|
14
|
+
# `gh` is a PATH stub that reports OPEN DIRTY once, then OPEN CLEAN. The stub REFUSES a request
|
|
15
|
+
# it did not expect (exit 64) rather than answering every question identically -- a fake that
|
|
16
|
+
# answers regardless of argv puts the seam above everything the caller's request shape encodes,
|
|
17
|
+
# so a caller querying the wrong thing would still read the right fixture.
|
|
18
|
+
export TMPDIR="${TMPDIR:-/var/tmp}"
|
|
19
|
+
|
|
20
|
+
set -uo pipefail
|
|
21
|
+
|
|
22
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
23
|
+
SUT="$SCRIPT_DIR/sync-pr-behind.sh"
|
|
24
|
+
|
|
25
|
+
passes=0; fails=0; CASES_RUN=0; FAILED=()
|
|
26
|
+
pass() { passes=$((passes + 1)); echo " PASS: $1"; }
|
|
27
|
+
fail() { fails=$((fails + 1)); FAILED+=("$1"); echo " FAIL: $1" >&2; }
|
|
28
|
+
|
|
29
|
+
_iv_p="$passes"; _iv_f="$fails"; _iv_n="${#FAILED[@]}"
|
|
30
|
+
{ pass "self-test"; fail "self-test"; } >/dev/null 2>&1
|
|
31
|
+
if [[ "$passes" -ne $((_iv_p + 1)) || "$fails" -ne $((_iv_f + 1)) || "${#FAILED[@]}" -ne $((_iv_n + 1)) ]]; then
|
|
32
|
+
printf '[FATAL] instrument self-test: the verdict helpers did not both record\n' >&2; exit 1
|
|
33
|
+
fi
|
|
34
|
+
passes=0; fails=0; FAILED=(); CASES_RUN=0
|
|
35
|
+
|
|
36
|
+
[[ -f "$SUT" ]] || { echo "[FATAL] SUT not found at $SUT" >&2; exit 1; }
|
|
37
|
+
|
|
38
|
+
assert_fixture_dir() {
|
|
39
|
+
case "${1-}" in
|
|
40
|
+
"") printf 'FATAL: fixture dir is EMPTY; git -C "" would operate on %s\n' "$PWD" >&2; exit 2 ;;
|
|
41
|
+
*/../*|*/..) printf 'FATAL: fixture dir %s contains ..; refusing\n' "$1" >&2; exit 2 ;;
|
|
42
|
+
/proc/*|/sys/*|/dev/*) printf 'FATAL: fixture dir %s is a synthetic-fs path; refusing\n' "$1" >&2; exit 2 ;;
|
|
43
|
+
/|//|/.) printf 'FATAL: fixture dir resolves to the filesystem root; refusing\n' >&2; exit 2 ;;
|
|
44
|
+
/*) : ;;
|
|
45
|
+
*) printf 'FATAL: fixture dir %s is RELATIVE; refusing\n' "$1" >&2; exit 2 ;;
|
|
46
|
+
esac
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
SANDBOX="$(mktemp -d)"; assert_fixture_dir "$SANDBOX"
|
|
50
|
+
trap 'rm -rf "$SANDBOX"' EXIT
|
|
51
|
+
# The resolver stages sources under XDG_CACHE_HOME; keep that inside the sandbox too.
|
|
52
|
+
export XDG_CACHE_HOME="$SANDBOX/xdg-cache"
|
|
53
|
+
|
|
54
|
+
MODEL="knowledge-base/engineering/architecture/diagrams/model.likec4.json"
|
|
55
|
+
SRC="knowledge-base/engineering/architecture/diagrams/model.c4"
|
|
56
|
+
_git() { git -C "$1" -c user.email=t@t -c user.name=t "${@:2}"; }
|
|
57
|
+
|
|
58
|
+
# mkfix <name> <conflict-kind> — a repo with a real `origin` remote (a local bare clone, so the
|
|
59
|
+
# push path is exercised for real rather than stubbed) and a conflict of the requested kind.
|
|
60
|
+
mkfix() {
|
|
61
|
+
local name="$1" kind="$2"
|
|
62
|
+
local root="$SANDBOX/$name"; assert_fixture_dir "$root"
|
|
63
|
+
local up="$root/upstream.git" wt="$root/wt"
|
|
64
|
+
mkdir -p "$up" "$wt"
|
|
65
|
+
git init -q --bare "$up"
|
|
66
|
+
|
|
67
|
+
mkdir -p "$wt/knowledge-base/engineering/architecture/diagrams" \
|
|
68
|
+
"$wt/plugins/soleur/scripts" "$wt/plugins/soleur/.claude-plugin"
|
|
69
|
+
printf 'first\nx\nlast\n' > "$wt/$SRC"
|
|
70
|
+
printf '{"v":"base"}\n' > "$wt/$MODEL"
|
|
71
|
+
printf 'readme base\n' > "$wt/README.md"
|
|
72
|
+
# BOTH scripts are COPIED INTO THE FIXTURE, and for sync-pr-behind.sh that is mandatory,
|
|
73
|
+
# not stylistic: it resolves its own repo root from ${BASH_SOURCE[0]}/../../.. and `cd`s
|
|
74
|
+
# there. Run from the tracked path it would operate on the REAL repository regardless of
|
|
75
|
+
# this fixture -- measured: the first run of this suite reported the developer's own branch
|
|
76
|
+
# name and exited 6 against the live worktree. Copying it makes that walk land in $wt.
|
|
77
|
+
cp "$SCRIPT_DIR/sync-pr-behind.sh" "$wt/plugins/soleur/scripts/"
|
|
78
|
+
cp "$SCRIPT_DIR/resolve-regenerable-conflicts.sh" "$wt/plugins/soleur/scripts/"
|
|
79
|
+
# The resolver runs the renderer BESIDE ITSELF (ADR-235 amendment), so the stub goes there
|
|
80
|
+
# with a plugin.json the resolver's identity check accepts. It takes the real renderer's
|
|
81
|
+
# `--root <staging> --out <file>` argv as the resolver passes it, and refuses any other shape.
|
|
82
|
+
printf '{\n "name": "soleur"\n}\n' > "$wt/plugins/soleur/.claude-plugin/plugin.json"
|
|
83
|
+
cat > "$wt/plugins/soleur/scripts/render-c4-model.sh" <<STUB
|
|
84
|
+
#!/usr/bin/env bash
|
|
85
|
+
set -euo pipefail
|
|
86
|
+
[[ "\$#" -eq 4 && "\$1" == "--root" && -d "\$2" && "\$3" == "--out" ]] || { echo "stub renderer: bad argv: \$*" >&2; exit 64; }
|
|
87
|
+
R="\$2"
|
|
88
|
+
printf '{"from":"%s|%s"}\n' "\$(head -1 "\$R/$SRC")" "\$(tail -1 "\$R/$SRC")" | tee "\$4" >/dev/null
|
|
89
|
+
STUB
|
|
90
|
+
chmod +x "$wt/plugins/soleur/scripts/render-c4-model.sh"
|
|
91
|
+
_git "$wt" init -q -b main
|
|
92
|
+
# Identity in LOCAL config, not only on `_git`'s `-c`: the SUT's own merge runs in this
|
|
93
|
+
# repo and reads config, so without these it only had an identity where the developer's
|
|
94
|
+
# GLOBAL config supplied one. Same defect as resolve-regenerable-conflicts.test.sh, which
|
|
95
|
+
# failed 14 rows on a CI runner (#8384, run 35588718251); this suite was found by sweeping
|
|
96
|
+
# the PR's suites under HOME=$(mktemp -d) GIT_CONFIG_GLOBAL=/dev/null.
|
|
97
|
+
git -C "$wt" config user.email t@t
|
|
98
|
+
git -C "$wt" config user.name t
|
|
99
|
+
_git "$wt" remote add origin "$up"
|
|
100
|
+
_git "$wt" add -A >/dev/null; _git "$wt" commit -q -m base
|
|
101
|
+
_git "$wt" push -q origin main
|
|
102
|
+
|
|
103
|
+
_git "$wt" checkout -q -b feature
|
|
104
|
+
sed -i 's/^last$/last-FEATURE/' "$wt/$SRC"
|
|
105
|
+
printf '{"v":"feature"}\n' > "$wt/$MODEL"
|
|
106
|
+
[[ "$kind" == "unresolvable" ]] && printf 'readme FEATURE\n' > "$wt/README.md"
|
|
107
|
+
_git "$wt" add -A >/dev/null; _git "$wt" commit -q -m feature
|
|
108
|
+
_git "$wt" push -q -u origin feature
|
|
109
|
+
|
|
110
|
+
_git "$wt" checkout -q main
|
|
111
|
+
sed -i 's/^first$/first-MAIN/' "$wt/$SRC"
|
|
112
|
+
printf '{"v":"main"}\n' > "$wt/$MODEL"
|
|
113
|
+
[[ "$kind" == "unresolvable" ]] && printf 'readme MAIN\n' > "$wt/README.md"
|
|
114
|
+
_git "$wt" add -A >/dev/null; _git "$wt" commit -q -m main
|
|
115
|
+
_git "$wt" push -q origin main
|
|
116
|
+
_git "$wt" checkout -q feature
|
|
117
|
+
|
|
118
|
+
# STRICT gh stub: answers only the query the SUT is expected to make, refuses anything else.
|
|
119
|
+
mkdir -p "$root/bin"
|
|
120
|
+
cat > "$root/bin/gh" <<'GH'
|
|
121
|
+
#!/usr/bin/env bash
|
|
122
|
+
# The merge-queue read (#9454) is the one other request the SUT makes: it asks
|
|
123
|
+
# `gh api graphql ... isInMergeQueue` and expects `not_queued` / `queued` back (--jq).
|
|
124
|
+
# This suite's PR is never queued; a graphql call WITHOUT the queue fields is still a miss.
|
|
125
|
+
if [[ "$1 $2" == "api graphql" ]]; then
|
|
126
|
+
case "$*" in
|
|
127
|
+
*isInMergeQueue*mergeQueueEntry*) echo not_queued; exit 0 ;;
|
|
128
|
+
*) echo "STUB-MISS: gh api graphql without the merge-queue fields: $*" >&2; exit 64 ;;
|
|
129
|
+
esac
|
|
130
|
+
fi
|
|
131
|
+
if [[ "$1 $2" != "pr view" ]]; then
|
|
132
|
+
echo "STUB-MISS: unexpected gh invocation: $*" >&2; exit 64
|
|
133
|
+
fi
|
|
134
|
+
# The standalone loop first checks the PR's head branch (kind=wrong_branch, exit 12).
|
|
135
|
+
# Answer it with the fixture branch; it is not a state read, so it is not counted.
|
|
136
|
+
for a in "$@"; do [[ "$a" == "headRefName" ]] && { echo "feature"; exit 0; }; done
|
|
137
|
+
for a in "$@"; do [[ "$a" == "state,mergeStateStatus" ]] && found=1; done
|
|
138
|
+
if [[ -z "${found:-}" ]]; then
|
|
139
|
+
echo "STUB-MISS: gh pr view without the expected --json fields: $*" >&2; exit 64
|
|
140
|
+
fi
|
|
141
|
+
n="$(cat "${GH_CALLS:?}" 2>/dev/null || echo 0)"; echo $((n + 1)) > "$GH_CALLS"
|
|
142
|
+
if [[ "$n" -eq 0 ]]; then echo "OPEN DIRTY"; else echo "OPEN CLEAN"; fi
|
|
143
|
+
GH
|
|
144
|
+
chmod +x "$root/bin/gh"
|
|
145
|
+
printf '%s' "$root"
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
run_sut() {
|
|
149
|
+
# SPLIT, not `local root="$1" wt="$root/wt"`: within one `local` statement the later
|
|
150
|
+
# assignment does not see the earlier name, so under `set -u` that form aborts the function
|
|
151
|
+
# with "root: unbound variable" -- and the caller reads the empty output as a SUT that
|
|
152
|
+
# printed nothing, which looks exactly like the bug this suite is here to detect.
|
|
153
|
+
local root="$1"
|
|
154
|
+
local wt="$root/wt"
|
|
155
|
+
local out rc=0
|
|
156
|
+
out="$(cd "$wt" && GH_CALLS="$root/gh.calls" PATH="$root/bin:$PATH" \
|
|
157
|
+
bash "$wt/plugins/soleur/scripts/sync-pr-behind.sh" 123 2>&1)" || rc=$?
|
|
158
|
+
printf '%s\n%s' "$out" "$rc"
|
|
159
|
+
}
|
|
160
|
+
sut_rc() { tail -n1 <<<"$1"; }
|
|
161
|
+
sut_out() { sed '$d' <<<"$1"; }
|
|
162
|
+
|
|
163
|
+
# RELOCATION SELF-TEST. The failure mode this guards is silent and total: a SUT that walks
|
|
164
|
+
# to the real repo answers every case from a tree the fixture never built, and the verdicts
|
|
165
|
+
# look ordinary. Require the fixture's own branch name in the output before reading anything.
|
|
166
|
+
_rt_root="$(mkfix relocation resolvable)"
|
|
167
|
+
_rt_out="$(sut_out "$(run_sut "$_rt_root")")"
|
|
168
|
+
if ! grep -q 'branch: feature' <<<"$_rt_out"; then
|
|
169
|
+
printf '[FATAL] relocation self-test: the SUT did not report the fixture branch.\n' >&2
|
|
170
|
+
printf ' It is operating on some other repository, so every case below is void.\n' >&2
|
|
171
|
+
printf ' got: %s\n' "$_rt_out" >&2
|
|
172
|
+
exit 1
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
echo "=== sync-pr-behind: regenerable-conflict arm ==="
|
|
176
|
+
|
|
177
|
+
# ── rc 0: the conflict is regenerable -> merged, regenerated, pushed ───────────────────────
|
|
178
|
+
echo ""
|
|
179
|
+
echo "--- resolver rc 0: merge is completed and pushed ---"
|
|
180
|
+
root="$(mkfix ok resolvable)"; wt="$root/wt"
|
|
181
|
+
res="$(run_sut "$root")"
|
|
182
|
+
CASES_RUN=$((CASES_RUN + 1))
|
|
183
|
+
[[ "$(sut_rc "$res")" == "0" ]] && pass "exits 0 on a regenerable conflict" \
|
|
184
|
+
|| fail "exited $(sut_rc "$res"): $(sut_out "$res")"
|
|
185
|
+
CASES_RUN=$((CASES_RUN + 1))
|
|
186
|
+
if grep -q 'regenerable conflict resolved' <<<"$(sut_out "$res")"; then
|
|
187
|
+
pass "reports that the regenerable path was taken"
|
|
188
|
+
else
|
|
189
|
+
fail "the regenerable arm is invisible in the output: $(sut_out "$res")"
|
|
190
|
+
fi
|
|
191
|
+
CASES_RUN=$((CASES_RUN + 1))
|
|
192
|
+
[[ "$(cat "$wt/$MODEL")" == *'first-MAIN|last-FEATURE'* ]] \
|
|
193
|
+
&& pass "the artifact was regenerated from the MERGED sources" \
|
|
194
|
+
|| fail "artifact is $(cat "$wt/$MODEL") — regen did not see the merged tree"
|
|
195
|
+
CASES_RUN=$((CASES_RUN + 1))
|
|
196
|
+
# The merge must have reached the REMOTE: this is what distinguishes "resolved" from
|
|
197
|
+
# "resolved locally and silently not pushed", and the resolver deliberately never pushes.
|
|
198
|
+
if _git "$root/upstream.git" rev-parse feature >/dev/null 2>&1 \
|
|
199
|
+
&& [[ "$(_git "$wt" rev-parse feature)" == "$(_git "$root/upstream.git" rev-parse feature)" ]]; then
|
|
200
|
+
pass "the merge commit was pushed (the caller owns the push, not the resolver)"
|
|
201
|
+
else
|
|
202
|
+
fail "the remote feature ref does not match local HEAD — the merge was never pushed"
|
|
203
|
+
fi
|
|
204
|
+
CASES_RUN=$((CASES_RUN + 1))
|
|
205
|
+
[[ -z "$(_git "$wt" status --porcelain)" ]] && pass "the worktree is clean afterwards" \
|
|
206
|
+
|| fail "worktree dirty: $(_git "$wt" status --porcelain)"
|
|
207
|
+
|
|
208
|
+
# ── non-zero: a non-regenerable conflict is refused exactly as before ──────────────────────
|
|
209
|
+
echo ""
|
|
210
|
+
echo "--- resolver non-zero: unchanged exit 6, tree untouched ---"
|
|
211
|
+
root="$(mkfix bad unresolvable)"; wt="$root/wt"
|
|
212
|
+
head_before="$(_git "$wt" rev-parse HEAD)"
|
|
213
|
+
res="$(run_sut "$root")"
|
|
214
|
+
CASES_RUN=$((CASES_RUN + 1))
|
|
215
|
+
[[ "$(sut_rc "$res")" == "6" ]] && pass "exits 6 on a non-regenerable conflict" \
|
|
216
|
+
|| fail "expected exit 6, got $(sut_rc "$res"): $(sut_out "$res")"
|
|
217
|
+
CASES_RUN=$((CASES_RUN + 1))
|
|
218
|
+
[[ "$(_git "$wt" rev-parse HEAD)" == "$head_before" ]] && pass "HEAD did not move" \
|
|
219
|
+
|| fail "HEAD moved on a conflict that should have been refused"
|
|
220
|
+
CASES_RUN=$((CASES_RUN + 1))
|
|
221
|
+
[[ -z "$(_git "$wt" status --porcelain)" ]] && pass "the tree is clean (merge aborted)" \
|
|
222
|
+
|| fail "tree left dirty: $(_git "$wt" status --porcelain)"
|
|
223
|
+
CASES_RUN=$((CASES_RUN + 1))
|
|
224
|
+
if grep -q 'manual resolution required' <<<"$(sut_out "$res")"; then
|
|
225
|
+
pass "reports that manual resolution is required"
|
|
226
|
+
else
|
|
227
|
+
fail "the refusal is not reported: $(sut_out "$res")"
|
|
228
|
+
fi
|
|
229
|
+
CASES_RUN=$((CASES_RUN + 1))
|
|
230
|
+
if grep -q 'STUB-MISS' <<<"$(sut_out "$res")"; then
|
|
231
|
+
fail "the gh stub was called in a way it did not expect — the fixture is not exercising the real request shape"
|
|
232
|
+
else
|
|
233
|
+
pass "no STUB-MISS: the SUT queried gh exactly as the stub expects"
|
|
234
|
+
fi
|
|
235
|
+
|
|
236
|
+
echo ""
|
|
237
|
+
echo "cases_run=$CASES_RUN passes=$passes fails=$fails ledger=${#FAILED[@]}"
|
|
238
|
+
_min_cases=10
|
|
239
|
+
if [[ "$CASES_RUN" -lt "$_min_cases" ]]; then
|
|
240
|
+
printf '[FATAL] assertion floor: only %s case(s) ran, floor is %s\n' "$CASES_RUN" "$_min_cases" >&2; exit 1
|
|
241
|
+
fi
|
|
242
|
+
if [[ $((passes + fails)) -ne "$CASES_RUN" ]]; then
|
|
243
|
+
printf '[FATAL] %s verdicts for %s cases\n' "$((passes + fails))" "$CASES_RUN" >&2; exit 1
|
|
244
|
+
fi
|
|
245
|
+
if [[ "${#FAILED[@]}" -ne "$fails" ]]; then
|
|
246
|
+
printf '[FATAL] ledger/counter disagree: %s vs %s\n' "${#FAILED[@]}" "$fails" >&2; exit 1
|
|
247
|
+
fi
|
|
248
|
+
if [[ "${#FAILED[@]}" -ne 0 ]]; then
|
|
249
|
+
printf '[FATAL] %s failing assertion(s):\n' "${#FAILED[@]}" >&2
|
|
250
|
+
printf ' - %s\n' "${FAILED[@]}" >&2; exit 1
|
|
251
|
+
fi
|
|
252
|
+
echo "sync-pr-behind: all $passes assertions passed"
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# taste-profile-update.sh — context-keyed design taste-profile writer/validator
|
|
3
|
+
# (#5990 · FR7 · ADR-090). Rides FR6 declarative context-injection (ADR-086):
|
|
4
|
+
# the committed taste-profile.md is agent-writable content, so per ADR-086
|
|
5
|
+
# §Consequences (content-trust ≠ path-trust) THIS helper is the sanitizing
|
|
6
|
+
# boundary — every model-supplied token (context, axis, value, date) is validated
|
|
7
|
+
# before it reaches the committed file that FR6 re-injects.
|
|
8
|
+
#
|
|
9
|
+
# Modes:
|
|
10
|
+
# write: taste-profile-update.sh <profile.md> <context> <axis> <value> <today-YYYY-MM-DD>
|
|
11
|
+
# validate: taste-profile-update.sh --validate <profile.md>
|
|
12
|
+
#
|
|
13
|
+
# Model: entries keyed by (context, axis) → value, ordered by RECENCY
|
|
14
|
+
# (last_reinforced, tie-break reinforce_count). No numeric weighting/scoring.
|
|
15
|
+
# Contradiction fires only within the SAME (context, axis); resolution = supersede,
|
|
16
|
+
# logged to contradictions[]. Automated writes bump `last_updated` only — never
|
|
17
|
+
# `last_reviewed` (freshness convention / context-reviewed-gate.sh).
|
|
18
|
+
#
|
|
19
|
+
# jq + bash only. Whole-file re-render from the parsed frontmatter + transformed
|
|
20
|
+
# JSON block (the machine block is the source of truth; the human tables are
|
|
21
|
+
# regenerated). Atomic tmp+mv; original preserved on any failure.
|
|
22
|
+
set -uo pipefail
|
|
23
|
+
|
|
24
|
+
# --- allowlists / sanitizers (the content-trust boundary) --------------------
|
|
25
|
+
CONTEXT_ALLOW=" landing-page marketing-site dashboard app-ui docs email component "
|
|
26
|
+
AXIS_ALLOW=" aesthetic-direction "
|
|
27
|
+
# value = a short lowercase-hyphen aesthetic-direction slug (≤40 chars). The closed
|
|
28
|
+
# charset + length cap is the injection defense: no whitespace/punctuation means a
|
|
29
|
+
# value can never encode imperative prose that could steer a future FR6-primed session.
|
|
30
|
+
VALUE_RE='^[a-z][a-z0-9-]{0,39}$'
|
|
31
|
+
DATE_RE='^[0-9]{4}-[0-9]{2}-[0-9]{2}$'
|
|
32
|
+
|
|
33
|
+
die() { printf 'taste-profile-update: %s\n' "$1" >&2; exit 1; }
|
|
34
|
+
|
|
35
|
+
extract_json() {
|
|
36
|
+
# Emit the JSON between the data markers, dropping the ``` fences.
|
|
37
|
+
awk '/taste-profile:data:start/{f=1;next} /taste-profile:data:end/{f=0} f' "$1" \
|
|
38
|
+
| sed -e '/^```/d'
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# Frontmatter-scoped field read (house `c==1` idiom — only the block between the
|
|
42
|
+
# first two `---` lines, so a body line beginning with the key never matches).
|
|
43
|
+
fm_field() { awk -F': ' -v k="$1" 'FNR==1{c=0} /^---$/{c++; next} c==1 && $0 ~ "^"k":" {print $2; exit}' "$2"; }
|
|
44
|
+
|
|
45
|
+
validate_json() {
|
|
46
|
+
# $1 = json string. Returns 0 iff EVERY entry AND contradiction is well-formed
|
|
47
|
+
# (same allowlists/regex a fresh write enforces). This is the consumer read-path
|
|
48
|
+
# trust gate (ADR-090): it must cover the whole machine block, not just entries.
|
|
49
|
+
local j="$1"
|
|
50
|
+
echo "$j" | jq -e '.schema == 1 and (.entries|type=="array") and (.contradictions|type=="array")' >/dev/null 2>&1 || return 1
|
|
51
|
+
local bad
|
|
52
|
+
bad=$(echo "$j" | jq -r \
|
|
53
|
+
--arg ctxs "$CONTEXT_ALLOW" --arg axes "$AXIS_ALLOW" \
|
|
54
|
+
--arg valre "$VALUE_RE" --arg datere "$DATE_RE" '
|
|
55
|
+
def ok_ctx($c): ($ctxs | contains(" " + $c + " "));
|
|
56
|
+
def ok_axis($a): ($axes | contains(" " + $a + " "));
|
|
57
|
+
( [ .entries[]
|
|
58
|
+
| select(
|
|
59
|
+
( ok_ctx(.context) | not ) or ( ok_axis(.axis) | not )
|
|
60
|
+
or ( (.value|type) != "string" ) or ( .value | test($valre) | not )
|
|
61
|
+
or ( .last_reinforced | test($datere) | not )
|
|
62
|
+
or ( (.reinforce_count|type) != "number" ) or ( .reinforce_count < 1 )
|
|
63
|
+
) ] | length )
|
|
64
|
+
+ ( [ .contradictions[]
|
|
65
|
+
| select(
|
|
66
|
+
( ok_ctx(.context) | not ) or ( ok_axis(.axis) | not )
|
|
67
|
+
or ( (.old_value|type) != "string" ) or ( .old_value | test($valre) | not )
|
|
68
|
+
or ( (.new_value|type) != "string" ) or ( .new_value | test($valre) | not )
|
|
69
|
+
or ( .date | test($datere) | not )
|
|
70
|
+
or ( (.old_count|type) != "number" )
|
|
71
|
+
) ] | length )' 2>/dev/null)
|
|
72
|
+
[[ "$bad" == "0" ]] || return 1
|
|
73
|
+
return 0
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
render_file() {
|
|
77
|
+
# $1 profile path, $2 preserved last_reviewed, $3 review_cadence, $4 owner,
|
|
78
|
+
# $5 today (new last_updated), $6 json
|
|
79
|
+
local out reviewed cadence owner today json tables flags
|
|
80
|
+
out="$1"; reviewed="$2"; cadence="$3"; owner="$4"; today="$5"; json="$6"
|
|
81
|
+
# Recency order: most-recent first, higher reinforce_count breaks a same-date tie.
|
|
82
|
+
tables=$(echo "$json" | jq -r '
|
|
83
|
+
if (.entries|length)==0 then "_None yet._"
|
|
84
|
+
else (["| context | axis | value | last_reinforced | reinforced |",
|
|
85
|
+
"|---|---|---|---|---|"]
|
|
86
|
+
+ ( .entries | sort_by([.last_reinforced, .reinforce_count]) | reverse
|
|
87
|
+
| map("| \(.context) | \(.axis) | \(.value) | \(.last_reinforced) | \(.reinforce_count) |") ))
|
|
88
|
+
| join("\n")
|
|
89
|
+
end') || return 1
|
|
90
|
+
flags=$(echo "$json" | jq -r '
|
|
91
|
+
if (.contradictions|length)==0 then "_None yet._"
|
|
92
|
+
else ( .contradictions | sort_by(.date) | reverse
|
|
93
|
+
| map("- \(.date) — `\(.context)`/`\(.axis)`: `\(.old_value)` (reinforced \(.old_count)×) superseded by `\(.new_value)`") )
|
|
94
|
+
| join("\n")
|
|
95
|
+
end') || return 1
|
|
96
|
+
local compact
|
|
97
|
+
compact=$(echo "$json" | jq -c '.') || return 1
|
|
98
|
+
cat > "$out" <<EOF
|
|
99
|
+
---
|
|
100
|
+
last_updated: $today
|
|
101
|
+
last_reviewed: $reviewed
|
|
102
|
+
review_cadence: $cadence
|
|
103
|
+
owner: $owner
|
|
104
|
+
---
|
|
105
|
+
# Design Taste Profile
|
|
106
|
+
|
|
107
|
+
Learned operator design preferences, keyed by \`(context, axis)\` and ordered by
|
|
108
|
+
recency. Loaded into design sessions via FR6 (\`frontend-design\` skill \`context_queries\`)
|
|
109
|
+
and a direct Read (\`ux-design-lead\` agent). See ADR-090.
|
|
110
|
+
|
|
111
|
+
<!-- Machine block owned by plugins/soleur/scripts/taste-profile-update.sh — do not hand-edit. -->
|
|
112
|
+
<!-- taste-profile:data:start -->
|
|
113
|
+
\`\`\`json
|
|
114
|
+
$compact
|
|
115
|
+
\`\`\`
|
|
116
|
+
<!-- taste-profile:data:end -->
|
|
117
|
+
|
|
118
|
+
## Reinforced Aesthetics
|
|
119
|
+
|
|
120
|
+
$tables
|
|
121
|
+
|
|
122
|
+
## Contradiction Flags
|
|
123
|
+
|
|
124
|
+
$flags
|
|
125
|
+
EOF
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
# --- validate mode -----------------------------------------------------------
|
|
129
|
+
if [[ "${1:-}" == "--validate" ]]; then
|
|
130
|
+
profile="${2:-}"
|
|
131
|
+
[[ -n "$profile" && -f "$profile" ]] || die "validate: profile not found: ${2:-<none>}"
|
|
132
|
+
json="$(extract_json "$profile")"
|
|
133
|
+
[[ -n "$json" ]] || die "validate: no machine block in $profile"
|
|
134
|
+
validate_json "$json" || die "validate: profile failed schema/allowlist checks"
|
|
135
|
+
exit 0
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
# --- write mode --------------------------------------------------------------
|
|
139
|
+
[[ $# -eq 5 ]] || die "usage: <profile.md> <context> <axis> <value> <today> | --validate <profile.md>"
|
|
140
|
+
profile="$1"; context="$2"; axis="$3"; value="$4"; today="$5"
|
|
141
|
+
[[ -f "$profile" ]] || die "profile not found: $profile"
|
|
142
|
+
|
|
143
|
+
# Token validation — the ADR-086 content-trust boundary. Reject → exit non-zero,
|
|
144
|
+
# original untouched (no write attempted).
|
|
145
|
+
[[ "$CONTEXT_ALLOW" == *" $context "* ]] || die "context not in allowlist: $context"
|
|
146
|
+
[[ "$AXIS_ALLOW" == *" $axis "* ]] || die "axis not in allowlist: $axis"
|
|
147
|
+
[[ "$value" =~ $VALUE_RE ]] || die "value must match $VALUE_RE"
|
|
148
|
+
[[ "$today" =~ $DATE_RE ]] || die "date must match $DATE_RE"
|
|
149
|
+
|
|
150
|
+
json="$(extract_json "$profile")"
|
|
151
|
+
[[ -n "$json" ]] || die "no machine block in $profile"
|
|
152
|
+
validate_json "$json" || die "existing profile failed validation (refusing to write over a corrupt file)"
|
|
153
|
+
|
|
154
|
+
new_json="$(echo "$json" | jq -c --arg ctx "$context" --arg axis "$axis" --arg val "$value" --arg today "$today" '
|
|
155
|
+
( .entries | map(select(.context==$ctx and .axis==$axis)) | .[0] ) as $ex
|
|
156
|
+
| ( if ($ex != null) and ($ex.value != $val)
|
|
157
|
+
then .contradictions += [{context:$ctx, axis:$axis, old_value:$ex.value, new_value:$val, old_count:$ex.reinforce_count, date:$today}]
|
|
158
|
+
else . end )
|
|
159
|
+
| .entries = (
|
|
160
|
+
( .entries | map(select((.context==$ctx and .axis==$axis) | not)) )
|
|
161
|
+
+ [ { context:$ctx, axis:$axis, value:$val, last_reinforced:$today,
|
|
162
|
+
reinforce_count: ( if ($ex != null and $ex.value==$val) then ($ex.reinforce_count + 1) else 1 end ) } ]
|
|
163
|
+
)
|
|
164
|
+
')" || die "jq transform failed"
|
|
165
|
+
[[ -n "$new_json" ]] || die "jq produced empty output"
|
|
166
|
+
|
|
167
|
+
reviewed="$(fm_field last_reviewed "$profile")"
|
|
168
|
+
cadence="$(fm_field review_cadence "$profile")"
|
|
169
|
+
owner="$(fm_field owner "$profile")"
|
|
170
|
+
|
|
171
|
+
# lint-trap-ownership: ok — allocates "${profile}.tmp.XXXXXX" BESIDE the target
|
|
172
|
+
# file (never /tmp); mv'd into place on success, rm -f'd on render failure.
|
|
173
|
+
# Residual is one sibling file per SIGKILL inside a two-statement window.
|
|
174
|
+
tmp="$(mktemp "${profile}.tmp.XXXXXX")" || die "mktemp failed"
|
|
175
|
+
if render_file "$tmp" "$reviewed" "$cadence" "$owner" "$today" "$new_json"; then
|
|
176
|
+
mv -f "$tmp" "$profile"
|
|
177
|
+
else
|
|
178
|
+
rm -f "$tmp"
|
|
179
|
+
die "render failed; original preserved"
|
|
180
|
+
fi
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# taste-profile-update.test.sh — fixture harness for the context-keyed taste-profile
|
|
3
|
+
# helper (#5990 · FR7 · ADR-090). Pattern mirrors .claude/hooks/skill-context-queries.test.sh.
|
|
4
|
+
#
|
|
5
|
+
# jq + bash only. Each test builds a fresh fixture profile in a temp dir, runs the
|
|
6
|
+
# helper, and asserts on the resulting file (or exit code). No network, no git needed.
|
|
7
|
+
set -uo pipefail
|
|
8
|
+
|
|
9
|
+
SCRIPT_DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
10
|
+
HELPER="$SCRIPT_DIR/taste-profile-update.sh"
|
|
11
|
+
|
|
12
|
+
pass=0
|
|
13
|
+
fail=0
|
|
14
|
+
pass() { printf ' \033[0;32mPASS\033[0m %s\n' "$1"; pass=$((pass + 1)); }
|
|
15
|
+
fail() { printf ' \033[0;31mFAIL\033[0m %s\n' "$1"; fail=$((fail + 1)); }
|
|
16
|
+
|
|
17
|
+
TMP_ROOT="$(mktemp -d)"
|
|
18
|
+
trap 'rm -rf "$TMP_ROOT"' EXIT
|
|
19
|
+
|
|
20
|
+
# Build a fresh seed profile; echoes its path.
|
|
21
|
+
mk_profile() {
|
|
22
|
+
local d p
|
|
23
|
+
d="$(mktemp -d "$TMP_ROOT/prof.XXXXXX")"
|
|
24
|
+
p="$d/taste-profile.md"
|
|
25
|
+
cat > "$p" <<'EOF'
|
|
26
|
+
---
|
|
27
|
+
last_updated: 2026-07-01
|
|
28
|
+
last_reviewed: 2026-07-01
|
|
29
|
+
review_cadence: quarterly
|
|
30
|
+
owner: CPO
|
|
31
|
+
---
|
|
32
|
+
# Design Taste Profile
|
|
33
|
+
|
|
34
|
+
<!-- Machine block owned by plugins/soleur/scripts/taste-profile-update.sh — do not hand-edit. -->
|
|
35
|
+
<!-- taste-profile:data:start -->
|
|
36
|
+
```json
|
|
37
|
+
{"schema":1,"entries":[],"contradictions":[]}
|
|
38
|
+
```
|
|
39
|
+
<!-- taste-profile:data:end -->
|
|
40
|
+
|
|
41
|
+
## Reinforced Aesthetics
|
|
42
|
+
|
|
43
|
+
_None yet._
|
|
44
|
+
|
|
45
|
+
## Contradiction Flags
|
|
46
|
+
|
|
47
|
+
_None yet._
|
|
48
|
+
EOF
|
|
49
|
+
echo "$p"
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# Extract the JSON machine block from a profile file.
|
|
53
|
+
data_of() {
|
|
54
|
+
awk '/taste-profile:data:start/{f=1;next} /taste-profile:data:end/{f=0} f' "$1" \
|
|
55
|
+
| sed -e '/^```/d'
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
echo "== taste-profile-update.sh =="
|
|
59
|
+
|
|
60
|
+
# 1. Upsert + reinforce (reinforce_count increments; recency date set)
|
|
61
|
+
p="$(mk_profile)"
|
|
62
|
+
bash "$HELPER" "$p" dashboard aesthetic-direction minimalist 2026-07-05 >/dev/null 2>&1
|
|
63
|
+
bash "$HELPER" "$p" dashboard aesthetic-direction minimalist 2026-07-06 >/dev/null 2>&1
|
|
64
|
+
n=$(data_of "$p" | jq '[.entries[] | select(.context=="dashboard" and .value=="minimalist")] | length' 2>/dev/null)
|
|
65
|
+
c=$(data_of "$p" | jq '.entries[] | select(.context=="dashboard" and .value=="minimalist") | .reinforce_count' 2>/dev/null)
|
|
66
|
+
lr=$(data_of "$p" | jq -r '.entries[] | select(.context=="dashboard" and .value=="minimalist") | .last_reinforced' 2>/dev/null)
|
|
67
|
+
if [[ "$n" == "1" && "$c" == "2" && "$lr" == "2026-07-06" ]]; then
|
|
68
|
+
pass "upsert+reinforce (one entry, count=2, recency updated)"
|
|
69
|
+
else fail "upsert+reinforce (got n=$n count=$c lr=$lr)"; fi
|
|
70
|
+
|
|
71
|
+
# 2. Same-context contradiction: differing value → contradictions[] entry + supersede
|
|
72
|
+
p="$(mk_profile)"
|
|
73
|
+
bash "$HELPER" "$p" landing-page aesthetic-direction editorial 2026-07-05 >/dev/null 2>&1
|
|
74
|
+
bash "$HELPER" "$p" landing-page aesthetic-direction maximalist 2026-07-06 >/dev/null 2>&1
|
|
75
|
+
cval=$(data_of "$p" | jq -r '.entries[] | select(.context=="landing-page") | .value' 2>/dev/null)
|
|
76
|
+
flag=$(data_of "$p" | jq '[.contradictions[] | select(.context=="landing-page" and .old_value=="editorial" and .new_value=="maximalist")] | length' 2>/dev/null)
|
|
77
|
+
if [[ "$cval" == "maximalist" && "$flag" == "1" ]]; then
|
|
78
|
+
pass "same-context contradiction flag fires + supersedes (old=editorial→new=maximalist)"
|
|
79
|
+
else fail "same-context contradiction (got value=$cval flag=$flag)"; fi
|
|
80
|
+
|
|
81
|
+
# 3. Cross-context is NOT a contradiction (dashboard + landing coexist)
|
|
82
|
+
p="$(mk_profile)"
|
|
83
|
+
bash "$HELPER" "$p" dashboard aesthetic-direction minimalist 2026-07-05 >/dev/null 2>&1
|
|
84
|
+
bash "$HELPER" "$p" landing-page aesthetic-direction maximalist 2026-07-06 >/dev/null 2>&1
|
|
85
|
+
ecount=$(data_of "$p" | jq '.entries | length' 2>/dev/null)
|
|
86
|
+
ccount=$(data_of "$p" | jq '.contradictions | length' 2>/dev/null)
|
|
87
|
+
if [[ "$ecount" == "2" && "$ccount" == "0" ]]; then
|
|
88
|
+
pass "cross-context NON-contradiction (2 entries, 0 flags)"
|
|
89
|
+
else fail "cross-context (got entries=$ecount contradictions=$ccount)"; fi
|
|
90
|
+
|
|
91
|
+
# 4. Reject out-of-allowlist context (preserve original)
|
|
92
|
+
p="$(mk_profile)"; before="$(cat "$p")"
|
|
93
|
+
if bash "$HELPER" "$p" 'prod; rm -rf /' aesthetic-direction minimalist 2026-07-05 >/dev/null 2>&1; then
|
|
94
|
+
fail "reject bad context (helper returned 0)"
|
|
95
|
+
else
|
|
96
|
+
[[ "$(cat "$p")" == "$before" ]] && pass "reject bad context + preserve original" || fail "bad context mutated file"
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
# 5. Reject out-of-allowlist axis
|
|
100
|
+
p="$(mk_profile)"; before="$(cat "$p")"
|
|
101
|
+
if bash "$HELPER" "$p" dashboard color-temperature minimalist 2026-07-05 >/dev/null 2>&1; then
|
|
102
|
+
fail "reject bad axis (helper returned 0)"
|
|
103
|
+
else
|
|
104
|
+
[[ "$(cat "$p")" == "$before" ]] && pass "reject out-of-allowlist axis + preserve" || fail "bad axis mutated file"
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
# 6. Reject metachar/whitespace value
|
|
108
|
+
p="$(mk_profile)"; before="$(cat "$p")"
|
|
109
|
+
if bash "$HELPER" "$p" dashboard aesthetic-direction 'max; touch /tmp/x' 2026-07-05 >/dev/null 2>&1; then
|
|
110
|
+
fail "reject metachar value (helper returned 0)"
|
|
111
|
+
else
|
|
112
|
+
[[ "$(cat "$p")" == "$before" ]] && pass "reject metachar value + preserve" || fail "bad value mutated file"
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# 7. Reject malformed date
|
|
116
|
+
p="$(mk_profile)"; before="$(cat "$p")"
|
|
117
|
+
if bash "$HELPER" "$p" dashboard aesthetic-direction minimalist 'yesterday' >/dev/null 2>&1; then
|
|
118
|
+
fail "reject bad date (helper returned 0)"
|
|
119
|
+
else
|
|
120
|
+
[[ "$(cat "$p")" == "$before" ]] && pass "reject malformed date + preserve" || fail "bad date mutated file"
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
# 8. Freshness: last_updated bumped, last_reviewed byte-unchanged
|
|
124
|
+
p="$(mk_profile)"
|
|
125
|
+
rev_before=$(awk -F': ' '/^last_reviewed:/{print $2; exit}' "$p")
|
|
126
|
+
bash "$HELPER" "$p" docs aesthetic-direction editorial 2026-07-09 >/dev/null 2>&1
|
|
127
|
+
upd=$(awk -F': ' '/^last_updated:/{print $2; exit}' "$p")
|
|
128
|
+
rev_after=$(awk -F': ' '/^last_reviewed:/{print $2; exit}' "$p")
|
|
129
|
+
if [[ "$upd" == "2026-07-09" && "$rev_after" == "$rev_before" ]]; then
|
|
130
|
+
pass "freshness: last_updated bumped, last_reviewed unchanged"
|
|
131
|
+
else fail "freshness (last_updated=$upd last_reviewed=$rev_after expected_rev=$rev_before)"; fi
|
|
132
|
+
|
|
133
|
+
# 9. --validate: passes on a clean profile, fails on a tampered one
|
|
134
|
+
p="$(mk_profile)"
|
|
135
|
+
bash "$HELPER" "$p" app-ui aesthetic-direction brutalist 2026-07-05 >/dev/null 2>&1
|
|
136
|
+
if bash "$HELPER" --validate "$p" >/dev/null 2>&1; then pass "--validate passes on clean profile"; else fail "--validate rejected a clean profile"; fi
|
|
137
|
+
# tamper: inject an out-of-allowlist axis directly into the JSON
|
|
138
|
+
python3 - "$p" <<'PY' 2>/dev/null || true
|
|
139
|
+
import re,sys,json
|
|
140
|
+
f=sys.argv[1]; s=open(f).read()
|
|
141
|
+
m=re.search(r'```json\n(.*?)\n```', s, re.S)
|
|
142
|
+
d=json.loads(m.group(1)); d["entries"].append({"context":"docs","axis":"evil-axis","value":"x","last_reinforced":"2026-07-05","reinforce_count":1})
|
|
143
|
+
s=s[:m.start(1)]+json.dumps(d)+s[m.end(1):]; open(f,"w").write(s)
|
|
144
|
+
PY
|
|
145
|
+
if bash "$HELPER" --validate "$p" >/dev/null 2>&1; then fail "--validate passed a tampered profile"; else pass "--validate fails on tampered profile"; fi
|
|
146
|
+
|
|
147
|
+
# 9b. --validate also covers contradictions[] (not just entries[]) — the consumer
|
|
148
|
+
# read-path trust gate must certify the whole machine block (security P3-1 / user-impact F2).
|
|
149
|
+
p="$(mk_profile)"
|
|
150
|
+
bash "$HELPER" "$p" landing-page aesthetic-direction editorial 2026-07-05 >/dev/null 2>&1
|
|
151
|
+
python3 - "$p" <<'PY' 2>/dev/null || true
|
|
152
|
+
import re,sys,json
|
|
153
|
+
f=sys.argv[1]; s=open(f).read()
|
|
154
|
+
m=re.search(r'```json\n(.*?)\n```', s, re.S)
|
|
155
|
+
d=json.loads(m.group(1)); d["contradictions"].append({"context":"landing-page","axis":"aesthetic-direction","old_value":"editorial; rm -rf /","new_value":"maximalist","old_count":1,"date":"2026-07-06"})
|
|
156
|
+
s=s[:m.start(1)]+json.dumps(d)+s[m.end(1):]; open(f,"w").write(s)
|
|
157
|
+
PY
|
|
158
|
+
if bash "$HELPER" --validate "$p" >/dev/null 2>&1; then fail "--validate passed a poisoned contradictions[] entry"; else pass "--validate fails on poisoned contradictions[] (whole-block coverage)"; fi
|
|
159
|
+
|
|
160
|
+
# 10. No decay/confidence tokens in the helper source (recency, not numeric decay)
|
|
161
|
+
if grep -qiE 'halflife|confidence|decay_' "$HELPER" 2>/dev/null; then
|
|
162
|
+
fail "helper contains decay/confidence tokens"
|
|
163
|
+
else pass "helper is recency-only (no decay/confidence tokens)"; fi
|
|
164
|
+
|
|
165
|
+
echo ""
|
|
166
|
+
echo "== $pass passed, $fail failed =="
|
|
167
|
+
[[ "$fail" -eq 0 ]] || exit 1
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# write-budget-marker.sh <dim> — write the classified `budget-capped` artifact
|
|
3
|
+
# for a ship/merge-pr phase-7 poll gate STOP (#9403). Emits nothing; exits 0
|
|
4
|
+
# always (fail-open like the tally itself). Extracted so the ship↔merge-pr
|
|
5
|
+
# mirror carries one implementation, not a byte-copied block.
|
|
6
|
+
set -uo pipefail
|
|
7
|
+
|
|
8
|
+
dim="${1:?usage: write-budget-marker.sh <dim>}"
|
|
9
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
10
|
+
|
|
11
|
+
show="$(bash "$ROOT/scripts/pipeline-tally.sh" show 2>/dev/null || true)"
|
|
12
|
+
cnt="$(printf '%s\n' "$show" | grep -o "${dim}=[0-9]*" | head -1 | cut -d= -f2 || true)"
|
|
13
|
+
cap="$(printf '%s\n' "$show" | grep -o "cap:${dim}=[0-9]*" | head -1 | cut -d= -f2 || true)"
|
|
14
|
+
# $() strips the newline before tr sees it; tr inside the substitution would
|
|
15
|
+
# map it to a stray '-'. Marker lands in the specs/<feature>/ dir the resume
|
|
16
|
+
# contract greps — the same shape the skills' classified-stop blocks write.
|
|
17
|
+
b="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || true)"
|
|
18
|
+
ss="knowledge-base/project/specs/$(printf '%s' "${b:-HEAD}" | tr -c 'A-Za-z0-9._-' '-')"
|
|
19
|
+
mkdir -p "$ss" 2>/dev/null \
|
|
20
|
+
&& printf 'status: budget-capped\nbudget-capped: %s=%s/%s\nresume: bash "%s/scripts/pipeline-tally.sh" init --max-%s <N>, then re-run the skill\n' \
|
|
21
|
+
"$dim" "${cnt:-0}" "${cap:-0}" "$ROOT" "$(printf '%s' "$dim" | tr '_' '-')" \
|
|
22
|
+
>> "$ss/session-state.md" || true
|
|
23
|
+
exit 0
|