@mmerterden/multi-agent-pipeline 20.2.0 → 20.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +923 -1
- package/README.md +104 -81
- package/README.tr.md +103 -62
- package/docs/FIGMA_PIPELINE.md +35 -35
- package/docs/adr/0006-skills-core-external-split.md +1 -1
- package/docs/adr/0007-multi-tool-adapter-framework.md +6 -0
- package/docs/adr/0008-installer-modularization-and-secret-leak-defense.md +7 -0
- package/docs/architecture.md +50 -14
- package/docs/best-practices.md +1 -1
- package/docs/ecosystem.md +56 -32
- package/docs/facts.json +10 -10
- package/docs/features.md +97 -5
- package/docs/recovery-guide.md +7 -14
- package/docs/server-readiness.md +31 -24
- package/index.js +1 -1
- package/install/_common.mjs +3 -5
- package/install/_platform-filter.mjs +23 -1
- package/install/_unattended-profile.mjs +321 -75
- package/install/claude.mjs +51 -10
- package/install/codex.mjs +2 -0
- package/install/copilot.mjs +2 -0
- package/install/index.mjs +30 -17
- package/install/templates/claude-hooks.json +16 -5
- package/install/templates/copilot-instructions.md +1 -1
- package/install/templates/multi-agent-autopilot-awake.plist.template +48 -0
- package/install/templates/multi-agent-autopilot.plist.template +12 -5
- package/install/unattended-profile-legacy.json +80 -0
- package/manifest.json +616 -483
- package/package.json +8 -3
- package/pipeline/agents/code-reviewer.md +10 -0
- package/pipeline/agents/plan-critic.md +98 -0
- package/pipeline/agents/security-auditor.md +10 -0
- package/pipeline/agents/task-clarifier.md +10 -0
- package/pipeline/commands/multi-agent/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/analysis/SKILL.md +6 -2
- package/pipeline/commands/multi-agent/analysis-jira/SKILL.md +12 -1
- package/pipeline/commands/multi-agent/analysis-resolve/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/autopilot/SKILL.md +6 -2
- package/pipeline/commands/multi-agent/autopilot-off/SKILL.md +36 -6
- package/pipeline/commands/multi-agent/autopilot-on/SKILL.md +77 -12
- package/pipeline/commands/multi-agent/autopilot-status/SKILL.md +29 -8
- package/pipeline/commands/multi-agent/build-optimize/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/channels/SKILL.md +9 -9
- package/pipeline/commands/multi-agent/complaint-analysis/SKILL.md +5 -1
- package/pipeline/commands/multi-agent/create-jira/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/design-check/SKILL.md +16 -11
- package/pipeline/commands/multi-agent/diff-explain/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/doctor/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/feedback/SKILL.md +5 -1
- package/pipeline/commands/multi-agent/forget/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/graph/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/help/SKILL.md +37 -39
- package/pipeline/commands/multi-agent/ios-coding-standard/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/issue/SKILL.md +7 -1
- package/pipeline/commands/multi-agent/jira/SKILL.md +7 -1
- package/pipeline/commands/multi-agent/kill/SKILL.md +9 -3
- package/pipeline/commands/multi-agent/language/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/log/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/manual-test/SKILL.md +5 -0
- package/pipeline/commands/multi-agent/model/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/prune-logs/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/prune-prompts/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/purge/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/refactor/SKILL.md +5 -0
- package/pipeline/commands/multi-agent/research/SKILL.md +49 -0
- package/pipeline/commands/multi-agent/resume/SKILL.md +29 -6
- package/pipeline/commands/multi-agent/review/SKILL.md +28 -9
- package/pipeline/commands/multi-agent/review-analysis/SKILL.md +5 -1
- package/pipeline/commands/multi-agent/review-issue/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/review-jira/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/route-off/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/route-on/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/route-status/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/routines/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/save/SKILL.md +6 -2
- package/pipeline/commands/multi-agent/scaffold/SKILL.md +47 -0
- package/pipeline/commands/multi-agent/scan/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/search/SKILL.md +12 -8
- package/pipeline/commands/multi-agent/security-review/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/serve/SKILL.md +62 -0
- package/pipeline/commands/multi-agent/setup/SKILL.md +27 -36
- package/pipeline/commands/multi-agent/stack/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/status/SKILL.md +10 -9
- package/pipeline/commands/multi-agent/steer/SKILL.md +5 -1
- package/pipeline/commands/multi-agent/store-ready/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/sync/SKILL.md +13 -13
- package/pipeline/commands/multi-agent/test/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/test-accessibility/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/test-dark-mode/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/test-dynamic-type/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/test-screenshots/SKILL.md +5 -1
- package/pipeline/commands/multi-agent/testflight-validation/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/uninstall/SKILL.md +5 -1
- package/pipeline/commands/multi-agent/update/SKILL.md +4 -0
- package/pipeline/contract/CHANGELOG.md +74 -0
- package/pipeline/contract/README.md +126 -0
- package/pipeline/contract/build.mjs +427 -0
- package/pipeline/contract/fixtures/answer-result.json +11 -0
- package/pipeline/contract/fixtures/error-invalid-request.json +8 -0
- package/pipeline/contract/fixtures/error-unauthorized.json +5 -0
- package/pipeline/contract/fixtures/error-unsigned.json +5 -0
- package/pipeline/contract/fixtures/issues-empty.json +18 -0
- package/pipeline/contract/fixtures/launch-plan.json +31 -0
- package/pipeline/contract/fixtures/runs-awaiting-question.json +70 -0
- package/pipeline/contract/fixtures/runs-empty.json +6 -0
- package/pipeline/contract/fixtures/runs-failed.json +84 -0
- package/pipeline/contract/fixtures/runs-old-schema.json +70 -0
- package/pipeline/contract/fixtures/runs-pr-opened-redacted.json +101 -0
- package/pipeline/contract/fixtures/runs-pr-opened.json +106 -0
- package/pipeline/contract/fixtures/runs-running.json +84 -0
- package/pipeline/contract/fixtures/worktrees-empty.json +4 -0
- package/pipeline/contract/frozen/toolbox.json +107 -0
- package/pipeline/contract/manifest.json +263 -0
- package/pipeline/contract/types/index.d.ts +343 -0
- package/pipeline/lib/_jira-auth.sh +6 -2
- package/pipeline/lib/account-resolver.sh +1 -1
- package/pipeline/lib/autopilot-state.sh +19 -0
- package/pipeline/lib/context-link-extractor.sh +12 -5
- package/pipeline/lib/credential-inventory.sh +12 -5
- package/pipeline/lib/credential-store.sh +116 -185
- package/pipeline/lib/fetch-confluence.sh +44 -3
- package/pipeline/lib/fetch-document.sh +3 -4
- package/pipeline/lib/fetch-fortify.sh +1 -1
- package/pipeline/lib/figma-mcp-refresh.sh +2 -2
- package/pipeline/lib/figma-token.sh +5 -1
- package/pipeline/lib/issue-fetcher.sh +233 -16
- package/pipeline/lib/json-file-lock.mjs +172 -0
- package/pipeline/lib/model-dispatch.sh +21 -12
- package/pipeline/lib/model-rung.sh +6 -1
- package/pipeline/lib/multi-repo-pipeline.sh +1 -1
- package/pipeline/lib/outbound-gate.mjs +46 -16
- package/pipeline/lib/parse-complaints.sh +14 -7
- package/pipeline/lib/plan-todos.sh +3 -3
- package/pipeline/lib/post-pr-review.sh +9 -9
- package/pipeline/lib/pr-request-location.mjs +85 -0
- package/pipeline/lib/regular-file.mjs +153 -0
- package/pipeline/lib/repo-hygiene.sh +17 -0
- package/pipeline/lib/route-state.sh +5 -1
- package/pipeline/lib/run-paths.sh +3 -2
- package/pipeline/lib/stack-detect.sh +19 -1
- package/pipeline/lib/unattended-profile-check.mjs +178 -0
- package/pipeline/lib/unattended-settings-location.mjs +28 -0
- package/pipeline/lib/unattended.mjs +76 -0
- package/pipeline/lib/unattended.sh +32 -0
- package/pipeline/lib/untrusted.mjs +76 -0
- package/pipeline/lib/user-facing.mjs +82 -0
- package/pipeline/lib/user-facing.sh +58 -0
- package/pipeline/multi-agent-refs/_dev-context.md +1 -1
- package/pipeline/multi-agent-refs/analysis/evidence.md +4 -0
- package/pipeline/multi-agent-refs/analysis/locked.md +2 -2
- package/pipeline/multi-agent-refs/analysis/render.md +4 -3
- package/pipeline/multi-agent-refs/analysis/resolve.md +3 -1
- package/pipeline/multi-agent-refs/analysis/synthesis.md +4 -5
- package/pipeline/multi-agent-refs/analysis-template.md +10 -17
- package/pipeline/multi-agent-refs/channels/jira.md +1 -1
- package/pipeline/multi-agent-refs/component-dispatch.md +3 -3
- package/pipeline/multi-agent-refs/conventions-defaults.md +32 -32
- package/pipeline/multi-agent-refs/cross-cli-contract.md +10 -17
- package/pipeline/multi-agent-refs/features/autopilot-circuit-breaker.md +37 -9
- package/pipeline/multi-agent-refs/features/autopilot-operations.md +277 -0
- package/pipeline/multi-agent-refs/features/constitution.md +196 -0
- package/pipeline/multi-agent-refs/features/doctor.md +6 -3
- package/pipeline/multi-agent-refs/features/external-context-injection.md +6 -1
- package/pipeline/multi-agent-refs/features/jira-context.md +1 -1
- package/pipeline/multi-agent-refs/features/maturity-followup.md +43 -23
- package/pipeline/multi-agent-refs/features/model-fallback.md +9 -0
- package/pipeline/multi-agent-refs/features/phone-api.md +306 -0
- package/pipeline/multi-agent-refs/features/plan-critic.md +159 -0
- package/pipeline/multi-agent-refs/features/research.md +150 -0
- package/pipeline/multi-agent-refs/features/review-decision.md +185 -0
- package/pipeline/multi-agent-refs/features/scaffold.md +160 -0
- package/pipeline/multi-agent-refs/features/security-audit.md +6 -2
- package/pipeline/multi-agent-refs/features/skill-conformance.md +4 -1
- package/pipeline/multi-agent-refs/features/stack-adapters.md +116 -0
- package/pipeline/multi-agent-refs/features/unattended-gates.md +316 -0
- package/pipeline/multi-agent-refs/features/unattended-security.md +731 -0
- package/pipeline/multi-agent-refs/features/url-enrichment.md +2 -2
- package/pipeline/multi-agent-refs/features/usage-reporting.md +127 -31
- package/pipeline/multi-agent-refs/features/verify-by-test.md +1 -1
- package/pipeline/multi-agent-refs/features/visual-evidence.md +7 -7
- package/pipeline/multi-agent-refs/keychain.md +6 -11
- package/pipeline/multi-agent-refs/payload-contracts.md +2 -2
- package/pipeline/multi-agent-refs/phases/log-format.md +2 -3
- package/pipeline/multi-agent-refs/phases/modes.md +10 -12
- package/pipeline/multi-agent-refs/phases/operations.md +11 -5
- package/pipeline/multi-agent-refs/phases/phase-0-init.md +73 -81
- package/pipeline/multi-agent-refs/phases/phase-1-plan.md +22 -22
- package/pipeline/multi-agent-refs/phases/phase-2-dev.md +42 -66
- package/pipeline/multi-agent-refs/phases/phase-3-review.md +45 -79
- package/pipeline/multi-agent-refs/phases/phase-4-commit.md +28 -38
- package/pipeline/multi-agent-refs/phases/phase-5-report.md +27 -25
- package/pipeline/multi-agent-refs/phases.md +1 -1
- package/pipeline/multi-agent-refs/picker-contract.md +1 -1
- package/pipeline/multi-agent-refs/progress-contract.md +13 -16
- package/pipeline/multi-agent-refs/readiness-review.md +1 -1
- package/pipeline/multi-agent-refs/research/engine.md +91 -0
- package/pipeline/multi-agent-refs/rules.md +6 -4
- package/pipeline/multi-agent-refs/setup/repo-discovery.md +2 -2
- package/pipeline/multi-agent-refs/tracker-contract.md +2 -2
- package/pipeline/multi-agent-refs/unattended-contract.md +68 -16
- package/pipeline/rules/figma-pipeline.md +12 -12
- package/pipeline/schemas/agent-state.schema.json +480 -18
- package/pipeline/schemas/analysis-spec.schema.json +4 -4
- package/pipeline/schemas/answer-request.schema.json +24 -0
- package/pipeline/schemas/answer-result.schema.json +28 -0
- package/pipeline/schemas/autopilot-config.schema.json +111 -13
- package/pipeline/schemas/command-parameters.schema.json +99 -0
- package/pipeline/schemas/constitution.schema.json +56 -0
- package/pipeline/schemas/contract-error.schema.json +52 -0
- package/pipeline/schemas/design-check-config.schema.json +5 -1
- package/pipeline/schemas/issues.schema.json +61 -0
- package/pipeline/schemas/launch-plan.schema.json +46 -0
- package/pipeline/schemas/launch-request.schema.json +45 -0
- package/pipeline/schemas/launch.json +61 -0
- package/pipeline/schemas/launch.schema.json +84 -0
- package/pipeline/schemas/phases.json +2 -2
- package/pipeline/schemas/phases.schema.json +68 -0
- package/pipeline/schemas/phone-devices.schema.json +61 -0
- package/pipeline/schemas/phone-signed-request.schema.json +67 -0
- package/pipeline/schemas/plan-critique.schema.json +99 -0
- package/pipeline/schemas/plan-todos.schema.json +7 -7
- package/pipeline/schemas/planning-output.schema.json +5 -0
- package/pipeline/schemas/pr-request.schema.json +46 -0
- package/pipeline/schemas/prefs.schema.json +82 -7
- package/pipeline/schemas/research-output.schema.json +118 -0
- package/pipeline/schemas/review-file-exclusions.schema.json +25 -0
- package/pipeline/schemas/reviewer-output.schema.json +40 -4
- package/pipeline/schemas/run-questions.json +392 -0
- package/pipeline/schemas/run-questions.schema.json +118 -0
- package/pipeline/schemas/runs-index.schema.json +189 -0
- package/pipeline/schemas/scaffold-manifest.schema.json +43 -0
- package/pipeline/schemas/secret-patterns.schema.json +28 -0
- package/pipeline/schemas/stack-adapters.json +527 -0
- package/pipeline/schemas/stack-adapters.schema.json +184 -0
- package/pipeline/schemas/token-budget.json +1 -1
- package/pipeline/schemas/token-budget.schema.json +26 -0
- package/pipeline/schemas/triage-output.schema.json +64 -3
- package/pipeline/schemas/unattended-policy.json +139 -0
- package/pipeline/schemas/unattended-policy.schema.json +73 -0
- package/pipeline/schemas/unattended-profile.json +248 -0
- package/pipeline/schemas/unattended-profile.schema.json +198 -0
- package/pipeline/schemas/worktrees.schema.json +51 -0
- package/pipeline/scripts/README.md +1 -0
- package/pipeline/scripts/_autopilot-config.mjs +130 -0
- package/pipeline/scripts/_autopilot-ops.mjs +567 -0
- package/pipeline/scripts/_autopilot-outcomes.mjs +174 -0
- package/pipeline/scripts/_command-contract.mjs +384 -0
- package/pipeline/scripts/_cost.mjs +40 -0
- package/pipeline/scripts/_notices.mjs +160 -0
- package/pipeline/scripts/_phone-auth.mjs +485 -0
- package/pipeline/scripts/_pre-existing.mjs +294 -0
- package/pipeline/scripts/_redact.mjs +77 -0
- package/pipeline/scripts/_run-paths.mjs +4 -2
- package/pipeline/scripts/_stack-adapter.mjs +678 -0
- package/pipeline/scripts/_stack-routing.mjs +1 -1
- package/pipeline/scripts/agent-guard.py +348 -37
- package/pipeline/scripts/agent-guard.sh +41 -13
- package/pipeline/scripts/analysis-story-tree.mjs +79 -3
- package/pipeline/scripts/answer-question.mjs +181 -0
- package/pipeline/scripts/audit-log-rotate.sh +1 -4
- package/pipeline/scripts/audit-log.sh +4 -4
- package/pipeline/scripts/autopilot-arming.mjs +389 -21
- package/pipeline/scripts/autopilot-awake.mjs +255 -0
- package/pipeline/scripts/autopilot-intake.mjs +137 -36
- package/pipeline/scripts/autopilot-menubar.swift +156 -44
- package/pipeline/scripts/autopilot-publish.mjs +1625 -0
- package/pipeline/scripts/autopilot-runner.mjs +1678 -222
- package/pipeline/scripts/autopilot-status.sh +198 -33
- package/pipeline/scripts/build-lock.sh +120 -0
- package/pipeline/scripts/build-references.mjs +4 -1
- package/pipeline/scripts/build-stack-plugins.mjs +59 -22
- package/pipeline/scripts/capture-flush.sh +1 -1
- package/pipeline/scripts/capture-resume.sh +13 -9
- package/pipeline/scripts/check-derived-drift.mjs +52 -11
- package/pipeline/scripts/commands.mjs +88 -0
- package/pipeline/scripts/constitution.mjs +362 -0
- package/pipeline/scripts/contract-server.mjs +776 -0
- package/pipeline/scripts/cost-analyze.mjs +89 -39
- package/pipeline/scripts/diff-explain.mjs +12 -1
- package/pipeline/scripts/doctor.mjs +77 -28
- package/pipeline/scripts/evidence-gate.mjs +192 -12
- package/pipeline/scripts/feedback-send.mjs +4 -2
- package/pipeline/scripts/gate-ledger.mjs +449 -0
- package/pipeline/scripts/gc-abandoned.sh +132 -13
- package/pipeline/scripts/gen-facts.mjs +31 -15
- package/pipeline/scripts/gen-mode-dispatch.mjs +3 -3
- package/pipeline/scripts/github-ssh-setup.sh +140 -29
- package/pipeline/scripts/graph-mermaid.mjs +4 -1
- package/pipeline/scripts/issues.mjs +236 -0
- package/pipeline/scripts/jira-attach.sh +6 -2
- package/pipeline/scripts/jira-search.sh +4 -3
- package/pipeline/scripts/keychain-save.sh +125 -24
- package/pipeline/scripts/keychain.py +63 -93
- package/pipeline/scripts/launch-request.mjs +747 -0
- package/pipeline/scripts/localize-commands.mjs +4 -10
- package/pipeline/scripts/log-metric.sh +6 -5
- package/pipeline/scripts/maturity-followup.mjs +13 -4
- package/pipeline/scripts/memory-save.sh +25 -0
- package/pipeline/scripts/migrate-prefs.mjs +4 -3
- package/pipeline/scripts/open-questions-gate.mjs +276 -0
- package/pipeline/scripts/phase-tracker.sh +41 -27
- package/pipeline/scripts/phase0-exit-gate.mjs +22 -4
- package/pipeline/scripts/phone-devices.mjs +224 -0
- package/pipeline/scripts/plan-coverage-gate.mjs +200 -66
- package/pipeline/scripts/plan-critique-gate.mjs +591 -0
- package/pipeline/scripts/pr-request.mjs +188 -0
- package/pipeline/scripts/pre-commit-check.sh +115 -4
- package/pipeline/scripts/probe-evidence-capability.sh +44 -5
- package/pipeline/scripts/record-phase.mjs +71 -0
- package/pipeline/scripts/render-agent-log-cost.sh +17 -2
- package/pipeline/scripts/render-cost-summary.sh +1 -1
- package/pipeline/scripts/render-work-summary.sh +1 -1
- package/pipeline/scripts/require-supported-version.sh +4 -1
- package/pipeline/scripts/research-gate.mjs +704 -0
- package/pipeline/scripts/review-decision-gate.mjs +403 -0
- package/pipeline/scripts/routine-registry.mjs +5 -2
- package/pipeline/scripts/runs-index.mjs +135 -27
- package/pipeline/scripts/scaffold-gate.mjs +393 -0
- package/pipeline/scripts/skill-conformance.mjs +25 -8
- package/pipeline/scripts/skill-siblings.mjs +2 -1
- package/pipeline/scripts/smoke-cross-cli-behavior.sh +32 -6
- package/pipeline/scripts/smoke-schema-validation.sh +6 -2
- package/pipeline/scripts/spec-consistency-gate.mjs +469 -0
- package/pipeline/scripts/symbol-existence-gate.mjs +450 -0
- package/pipeline/scripts/test-gap-scan.mjs +40 -2
- package/pipeline/scripts/test-integrity-gate.mjs +20 -4
- package/pipeline/scripts/test-strength.mjs +484 -0
- package/pipeline/scripts/test-summary.mjs +651 -0
- package/pipeline/scripts/triage-memory.mjs +49 -9
- package/pipeline/scripts/unattended_policy.py +2786 -0
- package/pipeline/scripts/uninstall.mjs +10 -10
- package/pipeline/scripts/update-issue-progress.sh +1 -1
- package/pipeline/scripts/usage-identity.mjs +288 -0
- package/pipeline/scripts/usage-register.mjs +185 -63
- package/pipeline/scripts/usage-report.mjs +230 -66
- package/pipeline/scripts/validate-complaint-doc.mjs +28 -10
- package/pipeline/scripts/validate-planning.mjs +6 -0
- package/pipeline/scripts/verify-citations.mjs +151 -38
- package/pipeline/scripts/verify.mjs +58 -18
- package/pipeline/scripts/worktree-prepare.sh +126 -0
- package/pipeline/scripts/worktrees.mjs +124 -0
- package/pipeline/scripts/write-state.mjs +48 -17
- package/pipeline/skills/.skill-manifest.json +222 -226
- package/pipeline/skills/.skills-index.json +77 -88
- package/pipeline/skills/shared/README.md +44 -45
- package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +3 -2
- package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +3 -2
- package/pipeline/skills/shared/core/multi-agent/SKILL.md +10 -9
- package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +6 -5
- package/pipeline/skills/shared/core/multi-agent-analysis-jira/SKILL.md +11 -3
- package/pipeline/skills/shared/core/multi-agent-analysis-resolve/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-autopilot/SKILL.md +4 -3
- package/pipeline/skills/shared/core/multi-agent-autopilot-off/SKILL.md +32 -6
- package/pipeline/skills/shared/core/multi-agent-autopilot-on/SKILL.md +66 -8
- package/pipeline/skills/shared/core/multi-agent-autopilot-status/SKILL.md +27 -9
- package/pipeline/skills/shared/core/multi-agent-build-optimize/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +7 -4
- package/pipeline/skills/shared/core/multi-agent-complaint-analysis/SKILL.md +3 -2
- package/pipeline/skills/shared/core/multi-agent-create-jira/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +7 -5
- package/pipeline/skills/shared/core/multi-agent-diff-explain/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-doctor/SKILL.md +3 -2
- package/pipeline/skills/shared/core/multi-agent-feedback/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-forget/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-garbage-collect/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-graph/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-ios-coding-standard/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-issue/SKILL.md +3 -2
- package/pipeline/skills/shared/core/multi-agent-jira/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-kill/SKILL.md +7 -4
- package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-log/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-manual-test/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-model/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-prune-logs/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-prune-prompts/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-purge/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-research/SKILL.md +35 -0
- package/pipeline/skills/shared/core/multi-agent-resume/SKILL.md +7 -3
- package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +7 -5
- package/pipeline/skills/shared/core/multi-agent-review-analysis/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-review-issue/SKILL.md +3 -2
- package/pipeline/skills/shared/core/multi-agent-review-jira/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-route-off/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-route-on/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-route-status/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-routines/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-save/SKILL.md +3 -2
- package/pipeline/skills/shared/core/multi-agent-scaffold/SKILL.md +30 -0
- package/pipeline/skills/shared/core/multi-agent-scan/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-search/SKILL.md +4 -3
- package/pipeline/skills/shared/core/multi-agent-security-review/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-serve/SKILL.md +60 -0
- package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +8 -8
- package/pipeline/skills/shared/core/multi-agent-stack/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-status/SKILL.md +7 -8
- package/pipeline/skills/shared/core/multi-agent-steer/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-store-ready/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +10 -10
- package/pipeline/skills/shared/core/multi-agent-test/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-test-accessibility/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-test-dark-mode/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-test-dynamic-type/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-test-screenshots/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-testflight-validation/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-uninstall/SKILL.md +3 -2
- package/pipeline/skills/shared/core/multi-agent-update/SKILL.md +2 -1
- package/pipeline/skills/shared/external/NOTICE-avdlee-swiftui-agent-skill.md +46 -0
- package/pipeline/skills/shared/external/NOTICE-dimillian-skills.md +9 -3
- package/pipeline/skills/shared/external/NOTICE-paul-hudson-skills.md +54 -0
- package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +9 -11
- package/pipeline/skills/shared/external/NOTICE-vibeship-spawner-skills.md +203 -0
- package/pipeline/skills/shared/external/NOTICE-xcode-build-skills.md +10 -3
- package/pipeline/skills/shared/external/accessibility-compliance-accessibility-audit/SKILL.md +131 -25
- package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +4 -3
- package/pipeline/skills/shared/external/alarmkit/SKILL.md +2 -1
- package/pipeline/skills/shared/external/android-architecture/SKILL.md +85 -76
- package/pipeline/skills/shared/external/android-build-quality-gates/SKILL.md +51 -3
- package/pipeline/skills/shared/external/android-build-quality-gates/references/patterns.md +9 -0
- package/pipeline/skills/shared/external/android-datastore/SKILL.md +4 -3
- package/pipeline/skills/shared/external/android-design-tokens-codegen/SKILL.md +4 -3
- package/pipeline/skills/shared/external/android-jetpack-compose-expert/SKILL.md +106 -181
- package/pipeline/skills/shared/external/android-jetpack-compose-expert/references/patterns.md +147 -0
- package/pipeline/skills/shared/external/android-mvi-viewmodel/SKILL.md +45 -4
- package/pipeline/skills/shared/external/android-performance/SKILL.md +27 -2
- package/pipeline/skills/shared/external/android-performance/references/patterns.md +37 -37
- package/pipeline/skills/shared/external/api-patterns/SKILL.md +111 -67
- package/pipeline/skills/shared/external/api-patterns/references/contract-details.md +128 -0
- package/pipeline/skills/shared/external/api-security-best-practices/SKILL.md +136 -186
- package/pipeline/skills/shared/external/api-security-best-practices/references/abuse-controls.md +140 -0
- package/pipeline/skills/shared/external/api-security-best-practices/references/identity-and-access.md +207 -0
- package/pipeline/skills/shared/external/api-security-best-practices/references/operations.md +66 -0
- package/pipeline/skills/shared/external/api-security-best-practices/references/request-handling.md +175 -0
- package/pipeline/skills/shared/external/app-clips/SKILL.md +2 -0
- package/pipeline/skills/shared/external/app-intents/SKILL.md +2 -0
- package/pipeline/skills/shared/external/app-store-changelog/SKILL.md +4 -3
- package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +2 -0
- package/pipeline/skills/shared/external/app-store-review/SKILL.md +2 -0
- package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +2 -0
- package/pipeline/skills/shared/external/architecture/SKILL.md +106 -39
- package/pipeline/skills/shared/external/architecture/references/adr-and-review.md +76 -0
- package/pipeline/skills/shared/external/authentication/SKILL.md +2 -0
- package/pipeline/skills/shared/external/avkit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/background-processing/SKILL.md +2 -1
- package/pipeline/skills/shared/external/backlog/SKILL.md +3 -2
- package/pipeline/skills/shared/external/callkit-voip/SKILL.md +2 -0
- package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +3 -2
- package/pipeline/skills/shared/external/clean-code/SKILL.md +192 -90
- package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +2 -1
- package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/compose-components/SKILL.md +4 -4
- package/pipeline/skills/shared/external/compose-navigation/SKILL.md +22 -22
- package/pipeline/skills/shared/external/compose-navigation/references/patterns.md +10 -10
- package/pipeline/skills/shared/external/compose-testing/SKILL.md +13 -6
- package/pipeline/skills/shared/external/compose-testing/references/patterns.md +59 -59
- package/pipeline/skills/shared/external/contacts-framework/SKILL.md +2 -0
- package/pipeline/skills/shared/external/context-compression/SKILL.md +118 -250
- package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +2 -0
- package/pipeline/skills/shared/external/core-data/SKILL.md +2 -0
- package/pipeline/skills/shared/external/core-motion/SKILL.md +2 -0
- package/pipeline/skills/shared/external/core-nfc/SKILL.md +2 -0
- package/pipeline/skills/shared/external/coreml/SKILL.md +2 -1
- package/pipeline/skills/shared/external/council/SKILL.md +2 -1
- package/pipeline/skills/shared/external/cryptokit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/css-modern/SKILL.md +3 -2
- package/pipeline/skills/shared/external/database-patterns/SKILL.md +3 -2
- package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +2 -0
- package/pipeline/skills/shared/external/debugging-strategies/SKILL.md +130 -20
- package/pipeline/skills/shared/external/debugging-strategies/references/hard-cases.md +54 -0
- package/pipeline/skills/shared/external/device-integrity/SKILL.md +2 -0
- package/pipeline/skills/shared/external/docker-expert/SKILL.md +137 -381
- package/pipeline/skills/shared/external/docker-expert/references/patterns.md +98 -0
- package/pipeline/skills/shared/external/energykit/SKILL.md +2 -1
- package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +3 -1
- package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +2 -2
- package/pipeline/skills/shared/external/fastapi-pro/SKILL.md +116 -185
- package/pipeline/skills/shared/external/fastapi-pro/references/app-structure.md +235 -0
- package/pipeline/skills/shared/external/fastapi-pro/references/testing-and-deployment.md +69 -0
- package/pipeline/skills/shared/external/firebase/SKILL.md +4 -3
- package/pipeline/skills/shared/external/github-actions-templates/SKILL.md +151 -293
- package/pipeline/skills/shared/external/github-actions-templates/references/patterns.md +96 -0
- package/pipeline/skills/shared/external/healthkit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/hig-components-content/SKILL.md +69 -72
- package/pipeline/skills/shared/external/hig-components-content/references/content-views.md +111 -0
- package/pipeline/skills/shared/external/hig-components-layout/SKILL.md +77 -86
- package/pipeline/skills/shared/external/hig-components-layout/references/containers.md +98 -0
- package/pipeline/skills/shared/external/hig-components-status/SKILL.md +150 -78
- package/pipeline/skills/shared/external/hig-components-system/SKILL.md +76 -97
- package/pipeline/skills/shared/external/hig-components-system/references/surfaces.md +98 -0
- package/pipeline/skills/shared/external/hig-foundations/SKILL.md +48 -76
- package/pipeline/skills/shared/external/hig-foundations/references/foundations-detail.md +132 -0
- package/pipeline/skills/shared/external/hig-inputs/SKILL.md +147 -106
- package/pipeline/skills/shared/external/hig-patterns/SKILL.md +61 -77
- package/pipeline/skills/shared/external/hig-patterns/references/patterns.md +92 -0
- package/pipeline/skills/shared/external/hig-platforms/SKILL.md +147 -77
- package/pipeline/skills/shared/external/hig-technologies/SKILL.md +61 -121
- package/pipeline/skills/shared/external/hig-technologies/references/technologies.md +108 -0
- package/pipeline/skills/shared/external/homekit-matter/SKILL.md +2 -0
- package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/html-semantic/SKILL.md +3 -2
- package/pipeline/skills/shared/external/humanizer/SKILL.md +2 -1
- package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +2 -0
- package/pipeline/skills/shared/external/ios-coding-standard/SKILL.md +2 -1
- package/pipeline/skills/shared/external/ios-coding-standard/references/STANDARD.md +14 -2
- package/pipeline/skills/shared/external/ios-coding-standard/references/rules.yml +2 -2
- package/pipeline/skills/shared/external/ios-debugger-agent/SKILL.md +4 -3
- package/pipeline/skills/shared/external/ios-localization/SKILL.md +8 -6
- package/pipeline/skills/shared/external/ios-localization/evals/evals.json +2 -2
- package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +11 -11
- package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +2 -1
- package/pipeline/skills/shared/external/ios-networking/SKILL.md +2 -0
- package/pipeline/skills/shared/external/ios-simulator/SKILL.md +2 -0
- package/pipeline/skills/shared/external/kotlin-coroutines-expert/SKILL.md +102 -193
- package/pipeline/skills/shared/external/kotlin-coroutines-expert/references/patterns.md +103 -0
- package/pipeline/skills/shared/external/live-activities/SKILL.md +4 -2
- package/pipeline/skills/shared/external/live-activities/evals/evals.json +2 -2
- package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +7 -9
- package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +3 -3
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +2 -2
- package/pipeline/skills/shared/external/macos-menubar-tuist-app/SKILL.md +4 -3
- package/pipeline/skills/shared/external/macos-spm-app-packaging/SKILL.md +5 -3
- package/pipeline/skills/shared/external/mapkit-location/SKILL.md +2 -0
- package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +2 -0
- package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/monorepo-architect/SKILL.md +149 -46
- package/pipeline/skills/shared/external/monorepo-architect/references/patterns.md +70 -0
- package/pipeline/skills/shared/external/musickit-audio/SKILL.md +2 -0
- package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/natural-language/SKILL.md +2 -0
- package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +3 -2
- package/pipeline/skills/shared/external/nodejs-backend-patterns/SKILL.md +91 -21
- package/pipeline/skills/shared/external/nodejs-backend-patterns/references/runtime-patterns.md +247 -0
- package/pipeline/skills/shared/external/nodejs-backend-patterns/references/testing-and-frameworks.md +57 -0
- package/pipeline/skills/shared/external/observability-engineer/SKILL.md +155 -232
- package/pipeline/skills/shared/external/observability-engineer/references/patterns.md +75 -0
- package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +2 -0
- package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +2 -2
- package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +18 -18
- package/pipeline/skills/shared/external/pdfkit/SKILL.md +2 -1
- package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +2 -0
- package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/permissionkit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +2 -1
- package/pipeline/skills/shared/external/push-notifications/SKILL.md +2 -0
- package/pipeline/skills/shared/external/python-patterns/SKILL.md +3 -2
- package/pipeline/skills/shared/external/react-best-practices/SKILL.md +3 -2
- package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +2 -2
- package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/rest-api-design/SKILL.md +3 -2
- package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +7 -7
- package/pipeline/skills/shared/external/retrofit-networking/references/patterns.md +69 -69
- package/pipeline/skills/shared/external/room-database/references/patterns.md +126 -126
- package/pipeline/skills/shared/external/search-first/SKILL.md +2 -1
- package/pipeline/skills/shared/external/security-review/SKILL.md +4 -3
- package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +2 -2
- package/pipeline/skills/shared/external/signal-community/SKILL.md +1 -1
- package/pipeline/skills/shared/external/skill-creator/SKILL.md +2 -1
- package/pipeline/skills/shared/external/speech-recognition/SKILL.md +2 -1
- package/pipeline/skills/shared/external/spm-build-analysis/SKILL.md +2 -0
- package/pipeline/skills/shared/external/storekit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swift-architecture/SKILL.md +2 -1
- package/pipeline/skills/shared/external/swift-charts/SKILL.md +2 -1
- package/pipeline/skills/shared/external/swift-codable/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +3 -1
- package/pipeline/skills/shared/external/swift-concurrency-expert/SKILL.md +5 -4
- package/pipeline/skills/shared/external/swift-concurrency-pro/SKILL.md +2 -1
- package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swift-language/SKILL.md +3 -1
- package/pipeline/skills/shared/external/swift-security/SKILL.md +2 -1
- package/pipeline/skills/shared/external/swift-testing/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swift-testing-pro/SKILL.md +2 -1
- package/pipeline/skills/shared/external/swift-testing-pro/references/new-features.md +10 -0
- package/pipeline/skills/shared/external/swiftdata/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swiftdata-pro/SKILL.md +2 -1
- package/pipeline/skills/shared/external/swiftlint/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/SKILL.md +3 -1
- package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +3 -1
- package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +3 -1
- package/pipeline/skills/shared/external/swiftui-performance-audit/SKILL.md +5 -4
- package/pipeline/skills/shared/external/swiftui-pro/SKILL.md +2 -1
- package/pipeline/skills/shared/external/swiftui-ui-patterns/SKILL.md +5 -4
- package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swiftui-view-refactor/SKILL.md +4 -3
- package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/tailwind-css/SKILL.md +3 -2
- package/pipeline/skills/shared/external/testing-backend/SKILL.md +3 -2
- package/pipeline/skills/shared/external/tipkit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +3 -2
- package/pipeline/skills/shared/external/vision-framework/SKILL.md +2 -0
- package/pipeline/skills/shared/external/vue-composition/SKILL.md +3 -2
- package/pipeline/skills/shared/external/weatherkit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/web-accessibility/SKILL.md +3 -2
- package/pipeline/skills/shared/external/web-performance/SKILL.md +3 -2
- package/pipeline/skills/shared/external/web-testing/SKILL.md +3 -2
- package/pipeline/skills/shared/external/widgetkit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +1 -1
- package/pipeline/skills/shared/external/xcode-build-benchmark/SKILL.md +2 -0
- package/pipeline/skills/shared/external/xcode-build-fixer/SKILL.md +2 -0
- package/pipeline/skills/shared/external/xcode-build-orchestrator/SKILL.md +2 -0
- package/pipeline/skills/shared/external/xcode-compilation-analyzer/SKILL.md +2 -0
- package/pipeline/skills/shared/external/xcode-project-analyzer/SKILL.md +2 -0
- package/pipeline/skills/skills-index.md +40 -41
- package/docs/token-budget-history.md +0 -24
- package/pipeline/skills/shared/external/agentflow/SKILL.md +0 -199
- package/pipeline/skills/shared/external/android-ui-verification/SKILL.md +0 -66
- package/pipeline/skills/shared/external/api-security-best-practices/references/auth.md +0 -299
- package/pipeline/skills/shared/external/api-security-best-practices/references/input-validation.md +0 -255
- package/pipeline/skills/shared/external/api-security-best-practices/references/rate-limiting.md +0 -167
- package/pipeline/skills/shared/external/closed-loop-delivery/SKILL.md +0 -116
- package/pipeline/skills/shared/external/ios-developer/SKILL.md +0 -216
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file _autopilot-outcomes.mjs - the one outcome contract for continuous mode.
|
|
3
|
+
*
|
|
4
|
+
* The runner writes an outcome per attempt into attempted.jsonl; intake reads
|
|
5
|
+
* it back to decide whether the item may run again; the breaker reads it to
|
|
6
|
+
* decide whether the machine is broken. All three have to agree on what each
|
|
7
|
+
* word means, so the words and their classes live here and nowhere else.
|
|
8
|
+
*
|
|
9
|
+
* TERMINAL the item is finished with us. Never queued again.
|
|
10
|
+
* RETRYABLE the attempt produced nothing. Queued again until `maxAttempts`,
|
|
11
|
+
* and each one counts toward that ceiling.
|
|
12
|
+
* PARKED the item is waiting for a person. Listed as awaiting, never
|
|
13
|
+
* re-run on its own, and its session and worktree are left alone.
|
|
14
|
+
* BLOCKED `blocked-*`: nothing ran. Arming or a precondition refused the
|
|
15
|
+
* item, which says nothing about the item or the machine, so it
|
|
16
|
+
* neither counts as an attempt nor feeds the breaker.
|
|
17
|
+
*
|
|
18
|
+
* Zero runtime dependencies (ADR-0004).
|
|
19
|
+
*
|
|
20
|
+
* @module pipeline/scripts/_autopilot-outcomes
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/** Every outcome word the runner writes, by name, so a typo is a ReferenceError. */
|
|
24
|
+
export const OUTCOME = Object.freeze({
|
|
25
|
+
PR_OPENED: "pr-opened",
|
|
26
|
+
PUSHED_AWAITING_PR: "pushed-awaiting-pr",
|
|
27
|
+
MERGED: "merged",
|
|
28
|
+
SKIPPED: "skipped",
|
|
29
|
+
COMPLETED_NO_PR: "completed-no-pr",
|
|
30
|
+
NEEDS_INPUT: "needs-input",
|
|
31
|
+
AWAITING_ANSWER: "awaiting-answer",
|
|
32
|
+
VERIFICATION_FAILED: "verification-failed",
|
|
33
|
+
FAILED: "failed",
|
|
34
|
+
BUILD_FAILED: "build-failed",
|
|
35
|
+
LAUNCH_FAILED: "launch-failed",
|
|
36
|
+
TIMED_OUT: "timed-out",
|
|
37
|
+
NO_STATE: "no-state",
|
|
38
|
+
UNKNOWN: "unknown",
|
|
39
|
+
DIED: "died",
|
|
40
|
+
RATE_LIMITED: "rate-limited",
|
|
41
|
+
BLOCKED_NO_PATH: "blocked-no-path",
|
|
42
|
+
BLOCKED_GUARD_MISSING: "blocked-guard-missing",
|
|
43
|
+
BLOCKED_SANDBOX_UNAVAILABLE: "blocked-sandbox-unavailable",
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* `completed-no-pr` is here because a run can stop legitimately without a PR -
|
|
48
|
+
* a question answered in chat, nothing to change - and running it again would
|
|
49
|
+
* repeat the same answer at the same cost.
|
|
50
|
+
*
|
|
51
|
+
* `pushed-awaiting-pr` is a verified branch the runner pushed to a host with no
|
|
52
|
+
* draft PR (Bitbucket). The work is delivered and the one step left is a
|
|
53
|
+
* person's, which touches neither the worktree nor the queue: a retry would
|
|
54
|
+
* push the same work again, and parking would hold the repo for a step that
|
|
55
|
+
* does not need it.
|
|
56
|
+
*/
|
|
57
|
+
export const TERMINAL = new Set([
|
|
58
|
+
OUTCOME.PR_OPENED,
|
|
59
|
+
OUTCOME.PUSHED_AWAITING_PR,
|
|
60
|
+
OUTCOME.MERGED,
|
|
61
|
+
OUTCOME.SKIPPED,
|
|
62
|
+
OUTCOME.COMPLETED_NO_PR,
|
|
63
|
+
]);
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* `died` - a run the supervisor lost track of - counts toward the item's
|
|
67
|
+
* attempts like the rest. `rate-limited` does too, and additionally has its own
|
|
68
|
+
* backoff in the runner, because the limit is the account's and the next item
|
|
69
|
+
* would hit it just the same.
|
|
70
|
+
*/
|
|
71
|
+
export const RETRYABLE = new Set([
|
|
72
|
+
OUTCOME.FAILED,
|
|
73
|
+
OUTCOME.BUILD_FAILED,
|
|
74
|
+
OUTCOME.LAUNCH_FAILED,
|
|
75
|
+
OUTCOME.TIMED_OUT,
|
|
76
|
+
OUTCOME.NO_STATE,
|
|
77
|
+
OUTCOME.UNKNOWN,
|
|
78
|
+
OUTCOME.DIED,
|
|
79
|
+
OUTCOME.RATE_LIMITED,
|
|
80
|
+
]);
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* `verification-failed` is parked rather than retryable: the run produced work
|
|
84
|
+
* and its own verification rejected it, so an automatic retry repeats the same
|
|
85
|
+
* work into the same rejection and bills for it twice. It is not terminal
|
|
86
|
+
* either, because nothing was delivered - it waits for a person to look.
|
|
87
|
+
*/
|
|
88
|
+
export const PARKED = new Set([
|
|
89
|
+
OUTCOME.NEEDS_INPUT,
|
|
90
|
+
OUTCOME.AWAITING_ANSWER,
|
|
91
|
+
OUTCOME.VERIFICATION_FAILED,
|
|
92
|
+
]);
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The `blocked-*` words written today: one per arming verdict, a checkout that
|
|
96
|
+
* is not on disk, a machine whose settings do not register the agent-guard
|
|
97
|
+
* hook the unattended contract relies on, and a profile file (or a checkout's
|
|
98
|
+
* own settings) that no longer holds the OS sandbox the contract rests on. classifyOutcome accepts the whole prefix family, because
|
|
99
|
+
* the runner writes `blocked-<blockedBy>` for whatever arming names.
|
|
100
|
+
*/
|
|
101
|
+
export const BLOCKED = new Set([
|
|
102
|
+
"blocked-credential",
|
|
103
|
+
"blocked-cost",
|
|
104
|
+
"blocked-cost-unknown",
|
|
105
|
+
"blocked-internal",
|
|
106
|
+
"blocked-config",
|
|
107
|
+
OUTCOME.BLOCKED_NO_PATH,
|
|
108
|
+
OUTCOME.BLOCKED_GUARD_MISSING,
|
|
109
|
+
OUTCOME.BLOCKED_SANDBOX_UNAVAILABLE,
|
|
110
|
+
]);
|
|
111
|
+
|
|
112
|
+
/** Prefix families. `stopped-<status>` is a run that ended mid-way. */
|
|
113
|
+
const STOPPED_PREFIX = "stopped-";
|
|
114
|
+
const BLOCKED_PREFIX = "blocked-";
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* The class of one outcome word, or null for a word this contract does not
|
|
118
|
+
* know. Null is deliberately not folded into any class: an unknown word in the
|
|
119
|
+
* ledger is a writer that drifted, and guessing its class hides that.
|
|
120
|
+
*
|
|
121
|
+
* @param {string} outcome
|
|
122
|
+
* @returns {"terminal"|"retryable"|"parked"|"blocked"|null}
|
|
123
|
+
*/
|
|
124
|
+
export function classifyOutcome(outcome) {
|
|
125
|
+
if (typeof outcome !== "string" || !outcome) return null;
|
|
126
|
+
if (TERMINAL.has(outcome)) return "terminal";
|
|
127
|
+
if (RETRYABLE.has(outcome)) return "retryable";
|
|
128
|
+
if (PARKED.has(outcome)) return "parked";
|
|
129
|
+
if (outcome.startsWith(STOPPED_PREFIX) && outcome.length > STOPPED_PREFIX.length) {
|
|
130
|
+
return "retryable";
|
|
131
|
+
}
|
|
132
|
+
if (outcome.startsWith(BLOCKED_PREFIX) && outcome.length > BLOCKED_PREFIX.length) {
|
|
133
|
+
return "blocked";
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export const isTerminal = (o) => classifyOutcome(o) === "terminal";
|
|
139
|
+
export const isRetryable = (o) => classifyOutcome(o) === "retryable";
|
|
140
|
+
export const isParked = (o) => classifyOutcome(o) === "parked";
|
|
141
|
+
export const isBlocked = (o) => classifyOutcome(o) === "blocked";
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The text a rate-limited session leaves behind. The first pattern is the CLI
|
|
145
|
+
* notice observed from a live session at its plan limit ("You've hit your
|
|
146
|
+
* weekly limit · resets 5am ..."), which is the whole message when the API
|
|
147
|
+
* error does not follow it. The rest are the API 429 / `rate_limit_error`
|
|
148
|
+
* shapes and a "usage limit reached ... resets" notice, expected but not yet
|
|
149
|
+
* observed from an unattended run.
|
|
150
|
+
*/
|
|
151
|
+
const RATE_LIMIT_PATTERNS = [
|
|
152
|
+
/\bhit your (?:[a-z]+ )?limit\b/i,
|
|
153
|
+
/\brate[_ -]?limit(?:ed|_error)?\b/i,
|
|
154
|
+
/\busage limit reached\b/i,
|
|
155
|
+
/\blimit reached\b.*\bresets?\b/i,
|
|
156
|
+
/\b429\b.*\b(?:too many requests|rate)/i,
|
|
157
|
+
/API Error:\s*429\b/i,
|
|
158
|
+
];
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Did this run stop because of a rate limit?
|
|
162
|
+
*
|
|
163
|
+
* Reads only the session's own row and the run's recorded halt reason - never
|
|
164
|
+
* the run log, where a task ABOUT rate limiting would match on its own prose.
|
|
165
|
+
*
|
|
166
|
+
* @param {{row?: object|null, state?: object|null}} evidence
|
|
167
|
+
* @returns {boolean}
|
|
168
|
+
*/
|
|
169
|
+
export function rateLimited({ row, state } = {}) {
|
|
170
|
+
const texts = [];
|
|
171
|
+
if (row && typeof row === "object") texts.push(JSON.stringify(row));
|
|
172
|
+
if (state && typeof state.haltReason === "string") texts.push(state.haltReason);
|
|
173
|
+
return texts.some((t) => RATE_LIMIT_PATTERNS.some((re) => re.test(t)));
|
|
174
|
+
}
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file _command-contract.mjs - the command surface as data: each command's
|
|
3
|
+
* parameters, whether a client offers it, and whether it destroys anything.
|
|
4
|
+
*
|
|
5
|
+
* Every `pipeline/commands/multi-agent/<id>/SKILL.md` declares, in frontmatter:
|
|
6
|
+
*
|
|
7
|
+
* parameters: [{name, kind, required?, repeat?, enum?}] one-line JSON
|
|
8
|
+
* gui: button | form | hidden
|
|
9
|
+
* destructive: true | false
|
|
10
|
+
* confirm: required | none
|
|
11
|
+
*
|
|
12
|
+
* `argument-hint` is what a person reads in autocomplete and `parameters` is
|
|
13
|
+
* what a client renders a form from. Two hand-written descriptions of one
|
|
14
|
+
* signature drift, so `checkCommand` holds them to each other. The rule, which
|
|
15
|
+
* is the whole of what "consistent" means here:
|
|
16
|
+
*
|
|
17
|
+
* 1. No arguments. A hint that is absent, empty, or starts with `(` declares
|
|
18
|
+
* none, and `parameters` must be `[]`.
|
|
19
|
+
* 2. Flags. The set of `--name` tokens anywhere in the hint - syntax and the
|
|
20
|
+
* prose after the ` - ` separator both, because several hints list flags
|
|
21
|
+
* only in the prose - equals the set of parameters named `--name`. A flag
|
|
22
|
+
* is never required.
|
|
23
|
+
* 3. Flag values, read in the syntax part only (prose is prose). `--x=...` or
|
|
24
|
+
* `--x <value>` takes a value, so its kind is not `flag`; a bare `--x`
|
|
25
|
+
* takes none, so its kind is `flag`. A value spelled as a list of bare
|
|
26
|
+
* words (`a|b|c`, `a,b,c`) makes the kind `enum` with exactly those
|
|
27
|
+
* values, and `,` makes it `repeat: true`.
|
|
28
|
+
* 4. Positionals. The syntax part (before the first ` - `) splits at top
|
|
29
|
+
* level into slots: a `[...]`, `<...>`, quoted or bare token. A slot whose
|
|
30
|
+
* text starts with `--` is a flag group, not a positional. The parameters
|
|
31
|
+
* not named `--...` match the remaining slots one to one, in order:
|
|
32
|
+
* `[...]` is `required: false`, any other slot `required: true`; text
|
|
33
|
+
* ending in `...` is `repeat: true`.
|
|
34
|
+
* 5. Positional enums. A slot of two or more bare lowercase alternatives
|
|
35
|
+
* (`[en|tr]`) must be `kind: "enum"` with exactly those values. A
|
|
36
|
+
* positional of kind `flag` is a literal keyword (`[autopilot]`), so its
|
|
37
|
+
* name must equal the slot's text.
|
|
38
|
+
*
|
|
39
|
+
* Surface rules: `destructive: true` needs `confirm: required`; a `button`
|
|
40
|
+
* takes no required parameter; a `form` has at least one parameter.
|
|
41
|
+
*
|
|
42
|
+
* Zero runtime dependencies (ADR-0004): the frontmatter reader is line-based
|
|
43
|
+
* like lint-skills.mjs, and `parameters` is JSON so it parses without YAML.
|
|
44
|
+
*
|
|
45
|
+
* @module pipeline/scripts/_command-contract
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
49
|
+
import { join } from "node:path";
|
|
50
|
+
|
|
51
|
+
export const CONTRACT_VERSION = "1.0.0";
|
|
52
|
+
export const PARAMETER_KINDS = [
|
|
53
|
+
"run-id",
|
|
54
|
+
"branch",
|
|
55
|
+
"pull-request",
|
|
56
|
+
"issue-key",
|
|
57
|
+
"path",
|
|
58
|
+
"text",
|
|
59
|
+
"enum",
|
|
60
|
+
"flag",
|
|
61
|
+
];
|
|
62
|
+
export const GUI_SURFACES = ["button", "form", "hidden"];
|
|
63
|
+
export const CONFIRM_VALUES = ["required", "none"];
|
|
64
|
+
|
|
65
|
+
/** The separator every hint uses between its syntax and its prose. */
|
|
66
|
+
const HINT_SEPARATOR = " - ";
|
|
67
|
+
|
|
68
|
+
/** Unquote one YAML scalar the way a YAML parser would for the two quote styles. */
|
|
69
|
+
export function yamlScalar(value) {
|
|
70
|
+
const v = String(value ?? "").trim();
|
|
71
|
+
if (v.length >= 2 && v.startsWith('"') && v.endsWith('"')) {
|
|
72
|
+
return v.slice(1, -1).replace(/\\(["\\])/g, "$1");
|
|
73
|
+
}
|
|
74
|
+
if (v.length >= 2 && v.startsWith("'") && v.endsWith("'")) {
|
|
75
|
+
return v.slice(1, -1).replace(/''/g, "'");
|
|
76
|
+
}
|
|
77
|
+
return v;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Top-level `key: value` lines of the frontmatter, values raw (still quoted).
|
|
82
|
+
*
|
|
83
|
+
* @param {string} raw whole SKILL.md text
|
|
84
|
+
* @returns {Record<string,string>|null} null when there is no frontmatter
|
|
85
|
+
*/
|
|
86
|
+
export function frontmatterFields(raw) {
|
|
87
|
+
if (!raw.startsWith("---\n")) return null;
|
|
88
|
+
const end = raw.indexOf("\n---", 4);
|
|
89
|
+
if (end === -1) return null;
|
|
90
|
+
const fields = {};
|
|
91
|
+
for (const line of raw.slice(4, end).split("\n")) {
|
|
92
|
+
const m = line.match(/^([a-zA-Z][a-zA-Z0-9-]*):\s*(.*)$/);
|
|
93
|
+
if (m) fields[m[1]] = m[2];
|
|
94
|
+
}
|
|
95
|
+
return fields;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Split text into top-level slots: `[...]`, `<...>`, quoted, or bare tokens. */
|
|
99
|
+
export function topLevelSlots(text) {
|
|
100
|
+
const slots = [];
|
|
101
|
+
let i = 0;
|
|
102
|
+
const closer = { "[": "]", "<": ">" };
|
|
103
|
+
while (i < text.length) {
|
|
104
|
+
const ch = text[i];
|
|
105
|
+
if (/\s/.test(ch)) {
|
|
106
|
+
i++;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const start = i;
|
|
110
|
+
if (ch === "[" || ch === "<") {
|
|
111
|
+
const stack = [closer[ch]];
|
|
112
|
+
let quote = null;
|
|
113
|
+
i++;
|
|
114
|
+
while (i < text.length && stack.length) {
|
|
115
|
+
const c = text[i];
|
|
116
|
+
if (quote) {
|
|
117
|
+
if (c === quote) quote = null;
|
|
118
|
+
} else if (c === '"' || c === "'") quote = c;
|
|
119
|
+
else if (c === "[" || c === "<") stack.push(closer[c]);
|
|
120
|
+
else if (c === stack[stack.length - 1]) stack.pop();
|
|
121
|
+
i++;
|
|
122
|
+
}
|
|
123
|
+
slots.push({ raw: text.slice(start, i), bracket: ch, inner: text.slice(start + 1, i - 1) });
|
|
124
|
+
} else if (ch === '"' || ch === "'") {
|
|
125
|
+
const close = text.indexOf(ch, i + 1);
|
|
126
|
+
i = close === -1 ? text.length : close + 1;
|
|
127
|
+
slots.push({ raw: text.slice(start, i), bracket: ch, inner: text.slice(start + 1, i - 1) });
|
|
128
|
+
} else {
|
|
129
|
+
while (i < text.length && !/\s/.test(text[i])) i++;
|
|
130
|
+
slots.push({ raw: text.slice(start, i), bracket: null, inner: text.slice(start, i) });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return slots.map((s) => {
|
|
134
|
+
const inner = s.inner.trim();
|
|
135
|
+
const repeat = /\.\.\.\s*$/.test(inner);
|
|
136
|
+
return {
|
|
137
|
+
...s,
|
|
138
|
+
inner,
|
|
139
|
+
optional: s.bracket === "[",
|
|
140
|
+
repeat,
|
|
141
|
+
isFlagGroup: inner.startsWith("--"),
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const BARE_WORD = /^[a-z0-9][a-z0-9-]*$/;
|
|
147
|
+
|
|
148
|
+
/** A value spelled as a list of bare words, or null when it is a placeholder. */
|
|
149
|
+
function wordList(value) {
|
|
150
|
+
for (const sep of ["|", ","]) {
|
|
151
|
+
if (!value.includes(sep)) continue;
|
|
152
|
+
const words = value.split(sep).map((w) => w.trim());
|
|
153
|
+
if (words.length >= 2 && words.every((w) => BARE_WORD.test(w))) {
|
|
154
|
+
return { words, repeat: sep === "," };
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* What the syntax part says about each flag it names: whether it takes a value
|
|
162
|
+
* and, when the value is a word list, which words.
|
|
163
|
+
*/
|
|
164
|
+
function flagShapes(syntax) {
|
|
165
|
+
const shapes = new Map();
|
|
166
|
+
// A value belongs to its flag only inside one top-level slot, so
|
|
167
|
+
// `[--dry-run] [target]` never reads `target` as the flag's value.
|
|
168
|
+
for (const slot of topLevelSlots(syntax)) {
|
|
169
|
+
const tokens = slot.inner
|
|
170
|
+
.replace(/[[\]]/g, " ")
|
|
171
|
+
.split(/\s+|\|(?=\s*--)/)
|
|
172
|
+
.filter(Boolean);
|
|
173
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
174
|
+
const m = tokens[i].match(/^(--[a-z][a-z0-9-]*)(=(.*))?$/);
|
|
175
|
+
if (!m) continue;
|
|
176
|
+
let value = null;
|
|
177
|
+
if (m[2] !== undefined) value = m[3];
|
|
178
|
+
else {
|
|
179
|
+
const next = tokens[i + 1];
|
|
180
|
+
if (next !== undefined && !next.startsWith("--") && next !== "|") value = next;
|
|
181
|
+
}
|
|
182
|
+
shapes.set(m[1], { takesValue: value !== null, list: value ? wordList(value) : null });
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return shapes;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Everything the hint declares, in the shape `checkCommand` compares against.
|
|
190
|
+
*
|
|
191
|
+
* @param {string|undefined} hint the unquoted argument-hint
|
|
192
|
+
*/
|
|
193
|
+
export function parseHint(hint) {
|
|
194
|
+
const text = String(hint ?? "").trim();
|
|
195
|
+
if (text === "" || text.startsWith("(")) {
|
|
196
|
+
return { noArgs: true, flags: new Set(), shapes: new Map(), slots: [] };
|
|
197
|
+
}
|
|
198
|
+
const cut = text.indexOf(HINT_SEPARATOR);
|
|
199
|
+
const syntax = cut === -1 ? text : text.slice(0, cut);
|
|
200
|
+
const flags = new Set(text.match(/--[a-z][a-z0-9-]*/g) ?? []);
|
|
201
|
+
const slots = topLevelSlots(syntax).filter((s) => !s.isFlagGroup);
|
|
202
|
+
return { noArgs: false, flags, shapes: flagShapes(syntax), slots };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Parse the `parameters:` line. Returns {value} or {error}. */
|
|
206
|
+
export function parseParameters(rawValue) {
|
|
207
|
+
if (rawValue === undefined) return { error: "missing required field: parameters" };
|
|
208
|
+
try {
|
|
209
|
+
const value = JSON.parse(rawValue);
|
|
210
|
+
if (!Array.isArray(value)) return { error: "parameters must be a JSON array" };
|
|
211
|
+
return { value };
|
|
212
|
+
} catch (err) {
|
|
213
|
+
return { error: `parameters is not one-line JSON (${err.message})` };
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** Fill the documented defaults so a consumer never has to know them. */
|
|
218
|
+
export function normalizeParameter(p) {
|
|
219
|
+
const out = {
|
|
220
|
+
name: p.name,
|
|
221
|
+
kind: p.kind,
|
|
222
|
+
required: p.required === true,
|
|
223
|
+
repeat: p.repeat === true,
|
|
224
|
+
};
|
|
225
|
+
if (Array.isArray(p.enum)) out.enum = [...p.enum];
|
|
226
|
+
return out;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const sameSet = (a, b) => a.length === b.length && a.every((x) => b.includes(x));
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Every contract violation in one command's frontmatter.
|
|
233
|
+
*
|
|
234
|
+
* @param {Record<string,string>} fields raw values from frontmatterFields()
|
|
235
|
+
* @returns {string[]}
|
|
236
|
+
*/
|
|
237
|
+
export function checkCommand(fields) {
|
|
238
|
+
const errors = [];
|
|
239
|
+
const parsed = parseParameters(fields.parameters);
|
|
240
|
+
if (parsed.error) errors.push(parsed.error);
|
|
241
|
+
const params = parsed.value ?? [];
|
|
242
|
+
|
|
243
|
+
const names = new Set();
|
|
244
|
+
params.forEach((p, i) => {
|
|
245
|
+
const at = `parameters[${i}]`;
|
|
246
|
+
if (!p || typeof p !== "object" || Array.isArray(p)) {
|
|
247
|
+
errors.push(`${at} is not an object`);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (typeof p.name !== "string" || !/^(--)?[a-z0-9][a-z0-9-]*$/.test(p.name)) {
|
|
251
|
+
errors.push(`${at}.name must be lowercase kebab-case, "--" prefixed for a flag`);
|
|
252
|
+
} else if (names.has(p.name)) errors.push(`${at}.name "${p.name}" is declared twice`);
|
|
253
|
+
else names.add(p.name);
|
|
254
|
+
if (!PARAMETER_KINDS.includes(p.kind)) {
|
|
255
|
+
errors.push(`${at}.kind must be one of ${PARAMETER_KINDS.join("|")}`);
|
|
256
|
+
}
|
|
257
|
+
for (const k of ["required", "repeat"]) {
|
|
258
|
+
if (k in p && typeof p[k] !== "boolean") errors.push(`${at}.${k} must be a boolean`);
|
|
259
|
+
}
|
|
260
|
+
if (p.kind === "enum" && !(Array.isArray(p.enum) && p.enum.length >= 1)) {
|
|
261
|
+
errors.push(`${at} is kind enum but has no enum values`);
|
|
262
|
+
}
|
|
263
|
+
if (p.kind !== "enum" && "enum" in p) errors.push(`${at} has enum values but is not kind enum`);
|
|
264
|
+
const extra = Object.keys(p).filter(
|
|
265
|
+
(k) => !["name", "kind", "required", "repeat", "enum"].includes(k),
|
|
266
|
+
);
|
|
267
|
+
if (extra.length) errors.push(`${at} has unknown keys: ${extra.join(", ")}`);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
const hint = parseHint(yamlScalar(fields["argument-hint"]));
|
|
271
|
+
const valid = params.filter((p) => p && typeof p.name === "string");
|
|
272
|
+
const flagParams = valid.filter((p) => p.name.startsWith("--"));
|
|
273
|
+
const positional = valid.filter((p) => !p.name.startsWith("--"));
|
|
274
|
+
|
|
275
|
+
if (hint.noArgs) {
|
|
276
|
+
if (params.length) errors.push("argument-hint declares no arguments but parameters is not []");
|
|
277
|
+
} else {
|
|
278
|
+
for (const f of hint.flags) {
|
|
279
|
+
if (!flagParams.some((p) => p.name === f)) {
|
|
280
|
+
errors.push(`argument-hint names ${f}, which parameters does not declare`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
for (const p of flagParams) {
|
|
284
|
+
if (!hint.flags.has(p.name)) {
|
|
285
|
+
errors.push(`parameter ${p.name} does not appear in argument-hint`);
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
if (p.required === true) errors.push(`flag ${p.name} cannot be required`);
|
|
289
|
+
const shape = hint.shapes.get(p.name);
|
|
290
|
+
if (!shape) continue;
|
|
291
|
+
if (shape.takesValue && p.kind === "flag") {
|
|
292
|
+
errors.push(`${p.name} takes a value in argument-hint, so its kind cannot be flag`);
|
|
293
|
+
}
|
|
294
|
+
if (!shape.takesValue && p.kind !== "flag") {
|
|
295
|
+
errors.push(`${p.name} takes no value in argument-hint, so its kind must be flag`);
|
|
296
|
+
}
|
|
297
|
+
if (shape.list) {
|
|
298
|
+
if (p.kind !== "enum" || !sameSet(p.enum ?? [], shape.list.words)) {
|
|
299
|
+
errors.push(
|
|
300
|
+
`${p.name} must be enum [${shape.list.words.join(", ")}] as argument-hint lists`,
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
if ((p.repeat === true) !== shape.list.repeat) {
|
|
304
|
+
errors.push(`${p.name} repeat must be ${shape.list.repeat} (argument-hint separator)`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (positional.length !== hint.slots.length) {
|
|
310
|
+
errors.push(
|
|
311
|
+
`argument-hint has ${hint.slots.length} positional slot(s) but parameters declares ${positional.length}`,
|
|
312
|
+
);
|
|
313
|
+
} else {
|
|
314
|
+
positional.forEach((p, i) => {
|
|
315
|
+
const slot = hint.slots[i];
|
|
316
|
+
if ((p.required === true) === slot.optional) {
|
|
317
|
+
errors.push(
|
|
318
|
+
`${p.name} required must be ${!slot.optional} (argument-hint slot ${slot.raw})`,
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
if ((p.repeat === true) !== slot.repeat) {
|
|
322
|
+
errors.push(`${p.name} repeat must be ${slot.repeat} (argument-hint slot ${slot.raw})`);
|
|
323
|
+
}
|
|
324
|
+
const alts = slot.inner
|
|
325
|
+
.replace(/\.\.\.\s*$/, "")
|
|
326
|
+
.split("|")
|
|
327
|
+
.map((a) => a.trim())
|
|
328
|
+
.filter(Boolean);
|
|
329
|
+
if (alts.length >= 2 && alts.every((a) => BARE_WORD.test(a))) {
|
|
330
|
+
if (p.kind !== "enum" || !sameSet(p.enum ?? [], alts)) {
|
|
331
|
+
errors.push(`${p.name} must be enum [${alts.join(", ")}] as argument-hint lists`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
if (p.kind === "flag" && p.name !== slot.inner) {
|
|
335
|
+
errors.push(
|
|
336
|
+
`${p.name} is a keyword, so its name must equal the slot text "${slot.inner}"`,
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const gui = yamlScalar(fields.gui);
|
|
344
|
+
if (!GUI_SURFACES.includes(gui)) errors.push(`gui must be ${GUI_SURFACES.join("|")}`);
|
|
345
|
+
const destructive = yamlScalar(fields.destructive);
|
|
346
|
+
if (!["true", "false"].includes(destructive)) errors.push("destructive must be true|false");
|
|
347
|
+
const confirm = yamlScalar(fields.confirm);
|
|
348
|
+
if (!CONFIRM_VALUES.includes(confirm)) errors.push(`confirm must be ${CONFIRM_VALUES.join("|")}`);
|
|
349
|
+
if (destructive === "true" && confirm !== "required") {
|
|
350
|
+
errors.push("a destructive command must declare confirm: required");
|
|
351
|
+
}
|
|
352
|
+
if (gui === "button" && valid.some((p) => p.required === true)) {
|
|
353
|
+
errors.push("a button cannot have a required parameter; use gui: form");
|
|
354
|
+
}
|
|
355
|
+
if (gui === "form" && params.length === 0) {
|
|
356
|
+
errors.push("a form needs at least one parameter; use gui: button");
|
|
357
|
+
}
|
|
358
|
+
return errors;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* The catalog a client renders from: one entry per command, defaults filled.
|
|
363
|
+
*
|
|
364
|
+
* @param {string} commandsDir pipeline/commands/multi-agent (or an installed copy)
|
|
365
|
+
*/
|
|
366
|
+
export function loadCatalog(commandsDir) {
|
|
367
|
+
const out = [];
|
|
368
|
+
for (const id of readdirSync(commandsDir).sort()) {
|
|
369
|
+
const file = join(commandsDir, id, "SKILL.md");
|
|
370
|
+
if (!existsSync(file)) continue;
|
|
371
|
+
const fields = frontmatterFields(readFileSync(file, "utf8"));
|
|
372
|
+
if (!fields) continue;
|
|
373
|
+
const parsed = parseParameters(fields.parameters);
|
|
374
|
+
out.push({
|
|
375
|
+
id,
|
|
376
|
+
argumentHint: yamlScalar(fields["argument-hint"]),
|
|
377
|
+
parameters: (parsed.value ?? []).map(normalizeParameter),
|
|
378
|
+
gui: yamlScalar(fields.gui) || null,
|
|
379
|
+
destructive: yamlScalar(fields.destructive) === "true",
|
|
380
|
+
confirm: yamlScalar(fields.confirm) || null,
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
return out;
|
|
384
|
+
}
|
|
@@ -33,3 +33,43 @@ export function costUsd(rate, tokensIn = 0, tokensOut = 0, tokensCached = 0) {
|
|
|
33
33
|
((tokensOut || 0) / 1_000_000) * rout
|
|
34
34
|
);
|
|
35
35
|
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Spend across autopilot attempt-ledger rows (attempted.jsonl).
|
|
39
|
+
*
|
|
40
|
+
* A row's `usd` is the run's cumulative cost when the row was written, priced
|
|
41
|
+
* from the tracker the run keeps. One run can be recorded more than once - parked
|
|
42
|
+
* and later settled, or researched and then resumed - and each later row carries
|
|
43
|
+
* the running total again. Rows are therefore grouped by `taskId`, the id the
|
|
44
|
+
* runner gives one claim, and each run counts once at the largest figure any of
|
|
45
|
+
* its rows recorded. A run whose rows never carry a number (`usd: null`) is
|
|
46
|
+
* unknown, never 0. A row with no `taskId` stands for itself, and a row with no
|
|
47
|
+
* `usd` at all is one where nothing ran.
|
|
48
|
+
*
|
|
49
|
+
* @param {object[]} rows
|
|
50
|
+
* @returns {{usd: number, unknown: number}}
|
|
51
|
+
*/
|
|
52
|
+
export function attemptSpend(rows) {
|
|
53
|
+
let usd = 0;
|
|
54
|
+
let unknown = 0;
|
|
55
|
+
const runs = new Map();
|
|
56
|
+
for (const r of rows || []) {
|
|
57
|
+
if (!r || typeof r !== "object") continue;
|
|
58
|
+
const measured = r.usd !== null && r.usd !== undefined && Number.isFinite(Number(r.usd));
|
|
59
|
+
const key = typeof r.taskId === "string" && r.taskId ? r.taskId : null;
|
|
60
|
+
if (!key) {
|
|
61
|
+
if (r.usd === null) unknown += 1;
|
|
62
|
+
else if (measured) usd += Number(r.usd);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const run = runs.get(key) || { max: null, unmeasured: false };
|
|
66
|
+
if (measured) run.max = run.max === null ? Number(r.usd) : Math.max(run.max, Number(r.usd));
|
|
67
|
+
else if (r.usd === null) run.unmeasured = true;
|
|
68
|
+
runs.set(key, run);
|
|
69
|
+
}
|
|
70
|
+
for (const run of runs.values()) {
|
|
71
|
+
if (run.max !== null) usd += run.max;
|
|
72
|
+
else if (run.unmeasured) unknown += 1;
|
|
73
|
+
}
|
|
74
|
+
return { usd, unknown };
|
|
75
|
+
}
|