@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,255 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* autopilot-awake.mjs - the launchd job that keeps the Mac awake while
|
|
4
|
+
* autopilot is on.
|
|
5
|
+
*
|
|
6
|
+
* The schedule's StartInterval does not wake a sleeping Mac. The in-flight lock
|
|
7
|
+
* (`caffeinate -s -w <runner pid>`, _autopilot-ops.mjs) covers a run while it is
|
|
8
|
+
* going, and nothing covers the gap between ticks: the machine sleeps, the next
|
|
9
|
+
* tick never fires, and the queue stops with nothing to say so. This job closes
|
|
10
|
+
* that gap. It is a second, separate launchd agent that runs
|
|
11
|
+
* `/usr/bin/caffeinate -s -i` (plus `-d` with `awake.display: true`) for as long
|
|
12
|
+
* as it is loaded, and it is loaded exactly while the mode is on.
|
|
13
|
+
*
|
|
14
|
+
* render [--display|--no-display] print the plist
|
|
15
|
+
* install [--display|--no-display] write it into LaunchAgents and load it;
|
|
16
|
+
* without a flag, awake.display from the
|
|
17
|
+
* config decides. awake.enabled: false
|
|
18
|
+
* removes the job instead.
|
|
19
|
+
* remove unload it and delete the plist
|
|
20
|
+
* status [--json] { held, display }
|
|
21
|
+
*
|
|
22
|
+
* Injectable for tests: MA_AP_LAUNCH_AGENTS (the LaunchAgents dir),
|
|
23
|
+
* MA_AP_LAUNCHCTL_BIN, MA_AP_PS_BIN, MA_AP_AWAKE_TEMPLATE, MA_AUTOPILOT_ROOT.
|
|
24
|
+
*
|
|
25
|
+
* Exit: 0 on success, 1 when launchd refused the job, 2 on usage.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import { spawnSync } from "node:child_process";
|
|
29
|
+
import {
|
|
30
|
+
chmodSync,
|
|
31
|
+
existsSync,
|
|
32
|
+
mkdirSync,
|
|
33
|
+
readFileSync,
|
|
34
|
+
renameSync,
|
|
35
|
+
rmSync,
|
|
36
|
+
writeFileSync,
|
|
37
|
+
} from "node:fs";
|
|
38
|
+
import { homedir } from "node:os";
|
|
39
|
+
import { dirname, join } from "node:path";
|
|
40
|
+
import { fileURLToPath } from "node:url";
|
|
41
|
+
import { invokedDirectly } from "../lib/invoked-directly.mjs";
|
|
42
|
+
|
|
43
|
+
export const AWAKE_LABEL = "com.multi-agent.autopilot-awake";
|
|
44
|
+
export const CAFFEINATE = "/usr/bin/caffeinate";
|
|
45
|
+
const TEMPLATE_NAME = "multi-agent-autopilot-awake.plist.template";
|
|
46
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
47
|
+
const LAUNCHCTL_TIMEOUT_MS = 15000;
|
|
48
|
+
|
|
49
|
+
function home(env) {
|
|
50
|
+
return env.HOME || homedir();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function readJson(p) {
|
|
54
|
+
try {
|
|
55
|
+
return JSON.parse(readFileSync(p, "utf-8"));
|
|
56
|
+
} catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** The config's `awake` block with its defaults: on, display allowed to sleep. */
|
|
62
|
+
export function awakeSettings(config) {
|
|
63
|
+
const a = config?.awake;
|
|
64
|
+
return { enabled: a?.enabled !== false, display: a?.display === true };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* `-s` holds system sleep off and macOS honours it on AC only; `-i` holds idle
|
|
69
|
+
* sleep off on battery as well; `-d` keeps the display on and is opt-in,
|
|
70
|
+
* because nothing autopilot runs needs a lit screen.
|
|
71
|
+
*/
|
|
72
|
+
export function caffeinateArgs({ display = false } = {}) {
|
|
73
|
+
return display ? ["-s", "-i", "-d"] : ["-s", "-i"];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** The installed tree keeps templates/ beside scripts/; the repo keeps it in install/. */
|
|
77
|
+
export function templatePath(env = process.env) {
|
|
78
|
+
const candidates = [
|
|
79
|
+
env.MA_AP_AWAKE_TEMPLATE,
|
|
80
|
+
join(HERE, "..", "templates", TEMPLATE_NAME),
|
|
81
|
+
join(HERE, "..", "..", "install", "templates", TEMPLATE_NAME),
|
|
82
|
+
...[".claude", ".copilot", ".codex"].map((d) => join(home(env), d, "templates", TEMPLATE_NAME)),
|
|
83
|
+
].filter(Boolean);
|
|
84
|
+
return candidates.find((p) => existsSync(p)) || null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function xmlEscape(s) {
|
|
88
|
+
return String(s).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function renderAwakePlist({ display = false, label = AWAKE_LABEL, env = process.env } = {}) {
|
|
92
|
+
const tpl = templatePath(env);
|
|
93
|
+
if (!tpl) throw new Error(`${TEMPLATE_NAME} is not installed - re-run the installer`);
|
|
94
|
+
const args = [CAFFEINATE, ...caffeinateArgs({ display })]
|
|
95
|
+
.map((a) => ` <string>${xmlEscape(a)}</string>`)
|
|
96
|
+
.join("\n");
|
|
97
|
+
return readFileSync(tpl, "utf-8")
|
|
98
|
+
.replace(/\{\{LABEL\}\}/g, xmlEscape(label))
|
|
99
|
+
.replace(/\{\{ARGS\}\}/g, args);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function launchAgentsDir(env = process.env) {
|
|
103
|
+
return env.MA_AP_LAUNCH_AGENTS || join(home(env), "Library", "LaunchAgents");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function awakePlistPath(env = process.env) {
|
|
107
|
+
return join(launchAgentsDir(env), `${AWAKE_LABEL}.plist`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function autopilotConfig(env) {
|
|
111
|
+
const root = env.MA_AUTOPILOT_ROOT || join(home(env), ".claude", "autopilot");
|
|
112
|
+
return readJson(join(root, "config.json"));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function launchctl(args, env) {
|
|
116
|
+
const r = spawnSync(env.MA_AP_LAUNCHCTL_BIN || "launchctl", args, {
|
|
117
|
+
encoding: "utf-8",
|
|
118
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
119
|
+
timeout: LAUNCHCTL_TIMEOUT_MS,
|
|
120
|
+
});
|
|
121
|
+
return { ok: !r.error && r.status === 0, stdout: String(r.stdout || "") };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function domain() {
|
|
125
|
+
return `gui/${process.getuid()}`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Unload the job and delete its plist. Absent is success. */
|
|
129
|
+
export function removeAwake({ env = process.env } = {}) {
|
|
130
|
+
const path = awakePlistPath(env);
|
|
131
|
+
if (!launchctl(["bootout", `${domain()}/${AWAKE_LABEL}`], env).ok && existsSync(path)) {
|
|
132
|
+
launchctl(["unload", path], env);
|
|
133
|
+
}
|
|
134
|
+
rmSync(path, { force: true });
|
|
135
|
+
return { path, removed: true };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Write the plist and load it. A job already loaded is booted out first, so a
|
|
140
|
+
* changed display answer takes effect now rather than at the next login.
|
|
141
|
+
*
|
|
142
|
+
* @returns {{path:string|null, loaded:boolean, display:boolean, enabled:boolean}}
|
|
143
|
+
*/
|
|
144
|
+
export function installAwake({ env = process.env, display } = {}) {
|
|
145
|
+
const settings = awakeSettings(autopilotConfig(env));
|
|
146
|
+
if (!settings.enabled) {
|
|
147
|
+
removeAwake({ env });
|
|
148
|
+
return { path: null, loaded: false, display: false, enabled: false };
|
|
149
|
+
}
|
|
150
|
+
const shown = typeof display === "boolean" ? display : settings.display;
|
|
151
|
+
const xml = renderAwakePlist({ display: shown, env });
|
|
152
|
+
const path = awakePlistPath(env);
|
|
153
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
154
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
155
|
+
writeFileSync(tmp, xml, { mode: 0o644 });
|
|
156
|
+
chmodSync(tmp, 0o644);
|
|
157
|
+
launchctl(["bootout", `${domain()}/${AWAKE_LABEL}`], env);
|
|
158
|
+
renameSync(tmp, path);
|
|
159
|
+
const loaded =
|
|
160
|
+
launchctl(["bootstrap", domain(), path], env).ok || launchctl(["load", path], env).ok;
|
|
161
|
+
return { path, loaded, display: shown, enabled: true };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** `caffeinate -s -i [-d]` and nothing after it: the in-flight lock carries `-w <pid>`. */
|
|
165
|
+
const AWAKE_PS = /(^|\/)caffeinate -s -i( -d)?\s*$/;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Held when launchd reports a running PID for the label, or, when launchd
|
|
169
|
+
* cannot say, when a `caffeinate -s -i` process is running. The display answer
|
|
170
|
+
* comes from the installed plist, else from that process's arguments.
|
|
171
|
+
*
|
|
172
|
+
* @returns {{held:boolean, display:boolean}}
|
|
173
|
+
*/
|
|
174
|
+
export function awakeStatus({ env = process.env } = {}) {
|
|
175
|
+
const path = awakePlistPath(env);
|
|
176
|
+
let plistDisplay = null;
|
|
177
|
+
if (existsSync(path)) {
|
|
178
|
+
try {
|
|
179
|
+
plistDisplay = /<string>-d<\/string>/.test(readFileSync(path, "utf-8"));
|
|
180
|
+
} catch {
|
|
181
|
+
plistDisplay = null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const listed = launchctl(["list", AWAKE_LABEL], env);
|
|
185
|
+
if (listed.ok && /"PID"\s*=\s*\d+/.test(listed.stdout)) {
|
|
186
|
+
return { held: true, display: plistDisplay === true };
|
|
187
|
+
}
|
|
188
|
+
const ps = spawnSync(env.MA_AP_PS_BIN || "ps", ["-axo", "command="], {
|
|
189
|
+
encoding: "utf-8",
|
|
190
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
191
|
+
timeout: LAUNCHCTL_TIMEOUT_MS,
|
|
192
|
+
});
|
|
193
|
+
const line = String(ps.stdout || "")
|
|
194
|
+
.split("\n")
|
|
195
|
+
.map((l) => l.trim().replace(/^\d+\s+/, ""))
|
|
196
|
+
.find((l) => AWAKE_PS.test(l));
|
|
197
|
+
if (line) return { held: true, display: plistDisplay ?? / -d\s*$/.test(line) };
|
|
198
|
+
return { held: false, display: plistDisplay === true };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function displayFlag(args) {
|
|
202
|
+
if (args.includes("--display")) return true;
|
|
203
|
+
if (args.includes("--no-display")) return false;
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function main(argv) {
|
|
208
|
+
const [cmd, ...rest] = argv;
|
|
209
|
+
const env = process.env;
|
|
210
|
+
switch (cmd) {
|
|
211
|
+
case "render":
|
|
212
|
+
process.stdout.write(renderAwakePlist({ display: displayFlag(rest) === true, env }));
|
|
213
|
+
return 0;
|
|
214
|
+
case "install": {
|
|
215
|
+
const r = installAwake({ env, display: displayFlag(rest) });
|
|
216
|
+
if (!r.enabled) {
|
|
217
|
+
console.log("awake: disabled in the config (awake.enabled: false) - no job installed");
|
|
218
|
+
return 0;
|
|
219
|
+
}
|
|
220
|
+
if (!r.loaded) {
|
|
221
|
+
console.error(`awake: launchd refused ${r.path}`);
|
|
222
|
+
return 1;
|
|
223
|
+
}
|
|
224
|
+
console.log(`awake: ${r.path} loaded (display ${r.display ? "kept on" : "may sleep"})`);
|
|
225
|
+
return 0;
|
|
226
|
+
}
|
|
227
|
+
case "remove":
|
|
228
|
+
removeAwake({ env });
|
|
229
|
+
console.log(`awake: ${AWAKE_LABEL} removed`);
|
|
230
|
+
return 0;
|
|
231
|
+
case "status": {
|
|
232
|
+
const s = awakeStatus({ env });
|
|
233
|
+
if (rest.includes("--json")) console.log(JSON.stringify(s));
|
|
234
|
+
else
|
|
235
|
+
console.log(
|
|
236
|
+
`awake: ${s.held ? "held" : "not held"}, display ${s.display ? "on" : "may sleep"}`,
|
|
237
|
+
);
|
|
238
|
+
return 0;
|
|
239
|
+
}
|
|
240
|
+
default:
|
|
241
|
+
console.error(
|
|
242
|
+
"usage: autopilot-awake.mjs {render|install|remove|status} [--display|--no-display|--json]",
|
|
243
|
+
);
|
|
244
|
+
return 2;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (invokedDirectly(import.meta.url)) {
|
|
249
|
+
try {
|
|
250
|
+
process.exitCode = main(process.argv.slice(2));
|
|
251
|
+
} catch (e) {
|
|
252
|
+
console.error(`awake: ${e?.message || e}`);
|
|
253
|
+
process.exitCode = 1;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
@@ -32,7 +32,9 @@
|
|
|
32
32
|
*
|
|
33
33
|
* Exit: 0 always when it can read its own state. An empty queue is an answer,
|
|
34
34
|
* not an error - "no item carries the label yet" is the single most common
|
|
35
|
-
* reason nothing is happening and it is not a fault.
|
|
35
|
+
* reason nothing is happening and it is not a fault. 3 when config.json breaks
|
|
36
|
+
* autopilot-config.schema.json: queue.json then holds no queued item and a
|
|
37
|
+
* `blockedReason` naming the field.
|
|
36
38
|
*/
|
|
37
39
|
|
|
38
40
|
import { execFileSync } from "node:child_process";
|
|
@@ -40,6 +42,8 @@ import { existsSync, readFileSync, mkdirSync, writeFileSync, renameSync, chmodSy
|
|
|
40
42
|
import { join, dirname } from "node:path";
|
|
41
43
|
import { homedir } from "node:os";
|
|
42
44
|
import { invokedDirectly } from "../lib/invoked-directly.mjs";
|
|
45
|
+
import { OUTCOME, isParked, isRetryable, isTerminal } from "./_autopilot-outcomes.mjs";
|
|
46
|
+
import { configRefusal } from "./_autopilot-config.mjs";
|
|
43
47
|
|
|
44
48
|
const ROOT = process.env.MA_AUTOPILOT_ROOT || join(homedir(), ".claude", "autopilot");
|
|
45
49
|
|
|
@@ -55,16 +59,13 @@ const PRIORITY = {
|
|
|
55
59
|
lowest: 10,
|
|
56
60
|
};
|
|
57
61
|
|
|
58
|
-
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
+
/*
|
|
63
|
+
* What an outcome means - finished, worth another attempt, or waiting for a
|
|
64
|
+
* person - is _autopilot-outcomes.mjs, the one contract the runner writes and
|
|
65
|
+
* this file reads. A `blocked-*` outcome is none of the three: the token being
|
|
66
|
+
* expired is not the item's fault, and it becomes workable again the moment the
|
|
67
|
+
* token is replaced, so it is queued again without counting an attempt.
|
|
62
68
|
*/
|
|
63
|
-
const TERMINAL = new Set(["pr-opened", "merged", "skipped"]);
|
|
64
|
-
/** Counted against `maxAttempts`. A credential block is NOT one of these - the
|
|
65
|
-
* token being expired is not the item's fault, and it becomes workable again
|
|
66
|
-
* the moment the token is replaced. */
|
|
67
|
-
const RETRYABLE = new Set(["died", "build-failed"]);
|
|
68
69
|
|
|
69
70
|
export function priorityScore(name) {
|
|
70
71
|
if (!name) return 0;
|
|
@@ -137,7 +138,14 @@ export function orderQueue(items, { maxConsecutivePerRepo = 5 } = {}) {
|
|
|
137
138
|
return out;
|
|
138
139
|
}
|
|
139
140
|
|
|
140
|
-
/**
|
|
141
|
+
/**
|
|
142
|
+
* Attempt history, folded into one record per item.
|
|
143
|
+
*
|
|
144
|
+
* Every RETRYABLE outcome counts toward `maxAttempts`, and counts ONCE per run:
|
|
145
|
+
* a run whose supervision timed out is recorded as `timed-out`, and when a
|
|
146
|
+
* later tick retires it the same run is recorded again as `died`. Both carry
|
|
147
|
+
* the runner's `taskId`, which is what makes them one attempt and not two.
|
|
148
|
+
*/
|
|
141
149
|
export function foldAttempts(lines) {
|
|
142
150
|
const byKey = new Map();
|
|
143
151
|
for (const raw of lines) {
|
|
@@ -150,8 +158,14 @@ export function foldAttempts(lines) {
|
|
|
150
158
|
continue; // a truncated last line is normal on an append-only log
|
|
151
159
|
}
|
|
152
160
|
const key = `${rec.source}:${rec.id}`;
|
|
153
|
-
const cur = byKey.get(key) || { attempts: 0, last: null, usd: 0, at: 0 };
|
|
154
|
-
if (
|
|
161
|
+
const cur = byKey.get(key) || { attempts: 0, last: null, usd: 0, at: 0, runs: new Set() };
|
|
162
|
+
if (isRetryable(rec.outcome)) {
|
|
163
|
+
if (!rec.taskId) cur.attempts += 1;
|
|
164
|
+
else if (!cur.runs.has(rec.taskId)) {
|
|
165
|
+
cur.runs.add(rec.taskId);
|
|
166
|
+
cur.attempts += 1;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
155
169
|
cur.usd += Number(rec.usd || 0);
|
|
156
170
|
if ((rec.at || 0) >= cur.at) {
|
|
157
171
|
cur.at = rec.at || 0;
|
|
@@ -164,6 +178,18 @@ export function foldAttempts(lines) {
|
|
|
164
178
|
return byKey;
|
|
165
179
|
}
|
|
166
180
|
|
|
181
|
+
/**
|
|
182
|
+
* The key a GitHub item was recorded under when its id carried only the short
|
|
183
|
+
* repo name (`app#5`). Read as a fallback so an item finished under the old id
|
|
184
|
+
* is not queued again; where two repos share the short name this errs toward
|
|
185
|
+
* leaving the item alone, never toward running it twice.
|
|
186
|
+
*/
|
|
187
|
+
function legacyKey(c) {
|
|
188
|
+
if (c?.source !== "github" || typeof c.id !== "string") return null;
|
|
189
|
+
const m = /^[^/#]+\/([^/#]+)#(\d+)$/.exec(c.id);
|
|
190
|
+
return m ? `github:${m[1]}#${m[2]}` : null;
|
|
191
|
+
}
|
|
192
|
+
|
|
167
193
|
/**
|
|
168
194
|
* Which candidates may enter the queue, and WHY each excluded one was excluded.
|
|
169
195
|
* Every drop carries a reason: a queue that silently shortens is the thing that
|
|
@@ -174,17 +200,24 @@ export function selectable(candidates, history, { maxAttempts = 2 } = {}) {
|
|
|
174
200
|
const awaiting = [];
|
|
175
201
|
const dropped = [];
|
|
176
202
|
for (const c of candidates) {
|
|
177
|
-
const h = history.get(`${c.source}:${c.id}`);
|
|
203
|
+
const h = history.get(`${c.source}:${c.id}`) ?? history.get(legacyKey(c));
|
|
178
204
|
if (!h) {
|
|
179
205
|
queued.push(c);
|
|
180
206
|
continue;
|
|
181
207
|
}
|
|
182
|
-
if (
|
|
208
|
+
if (isTerminal(h.last)) {
|
|
183
209
|
dropped.push({ ...c, reason: `already ${h.last}`, prUrl: h.prUrl });
|
|
184
210
|
continue;
|
|
185
211
|
}
|
|
186
|
-
|
|
187
|
-
|
|
212
|
+
// Parked for a person: never re-run on its own. `awaiting-answer` is the
|
|
213
|
+
// maturity question; the others wait just the same, and say why.
|
|
214
|
+
if (isParked(h.last)) {
|
|
215
|
+
awaiting.push({
|
|
216
|
+
...c,
|
|
217
|
+
askedAt: h.at,
|
|
218
|
+
gapFingerprint: h.gapFingerprint,
|
|
219
|
+
...(h.last === OUTCOME.AWAITING_ANSWER ? {} : { waitingOn: h.last }),
|
|
220
|
+
});
|
|
188
221
|
continue;
|
|
189
222
|
}
|
|
190
223
|
if (h.attempts >= maxAttempts) {
|
|
@@ -234,10 +267,21 @@ function fetchGitHub(repo) {
|
|
|
234
267
|
} catch {
|
|
235
268
|
return [];
|
|
236
269
|
}
|
|
270
|
+
return githubCandidates(repo, rows);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Queue items from `gh issue list` rows. The id carries the full owner/repo:
|
|
275
|
+
* two repos may share a short name, and an id made from the short name alone
|
|
276
|
+
* would let one repo's finished issue drop the other's. `ref` stays short -
|
|
277
|
+
* the run is launched in the repo's own checkout, which names the repo.
|
|
278
|
+
*/
|
|
279
|
+
export function githubCandidates(repo, rows) {
|
|
280
|
+
const label = repo.githubLabel || "agent-queue";
|
|
237
281
|
const short = repo.nameWithOwner.split("/").pop();
|
|
238
|
-
return rows.map((r) => ({
|
|
282
|
+
return (rows || []).map((r) => ({
|
|
239
283
|
source: "github",
|
|
240
|
-
id: `${
|
|
284
|
+
id: `${repo.nameWithOwner}#${r.number}`,
|
|
241
285
|
ref: `${short}#${r.number}`,
|
|
242
286
|
repo: repo.nameWithOwner,
|
|
243
287
|
localPath: repo.localPath,
|
|
@@ -278,7 +322,12 @@ function fetchJira(repo) {
|
|
|
278
322
|
} catch {
|
|
279
323
|
return [];
|
|
280
324
|
}
|
|
281
|
-
return rows
|
|
325
|
+
return jiraCandidates(repo, rows);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/** Queue items from a Jira search's `issues`. The issue key is the id. */
|
|
329
|
+
export function jiraCandidates(repo, issues) {
|
|
330
|
+
return (issues || []).map((i) => ({
|
|
282
331
|
source: "jira",
|
|
283
332
|
id: i.key,
|
|
284
333
|
ref: i.key,
|
|
@@ -292,14 +341,42 @@ function fetchJira(repo) {
|
|
|
292
341
|
}));
|
|
293
342
|
}
|
|
294
343
|
|
|
295
|
-
|
|
344
|
+
/**
|
|
345
|
+
* Every candidate from every configured repo.
|
|
346
|
+
*
|
|
347
|
+
* A Jira issue is one item whichever repo's search returned it. The default
|
|
348
|
+
* JQL (assignee plus label) is the same for every repo, so without this each
|
|
349
|
+
* repo with Jira on would queue - and run, and open a PR for - the same issue.
|
|
350
|
+
* The first repo in config order takes it; each other match is returned in
|
|
351
|
+
* `duplicates` with the reason, so the queue says why it is not listed twice.
|
|
352
|
+
*
|
|
353
|
+
* @returns {{items: object[], duplicates: object[]}}
|
|
354
|
+
*/
|
|
355
|
+
export function gather(
|
|
356
|
+
config,
|
|
357
|
+
{ fetchGitHub: gh = fetchGitHub, fetchJira: jira = fetchJira } = {},
|
|
358
|
+
) {
|
|
296
359
|
const items = [];
|
|
360
|
+
const duplicates = [];
|
|
361
|
+
const jiraOwner = new Map();
|
|
297
362
|
for (const repo of config.repos || []) {
|
|
298
363
|
const sources = repo.sources || ["github"];
|
|
299
|
-
if (sources.includes("github")) items.push(...
|
|
300
|
-
if (sources.includes("jira"))
|
|
364
|
+
if (sources.includes("github")) items.push(...gh(repo));
|
|
365
|
+
if (!sources.includes("jira")) continue;
|
|
366
|
+
for (const it of jira(repo)) {
|
|
367
|
+
const owner = jiraOwner.get(it.id);
|
|
368
|
+
if (owner === undefined) {
|
|
369
|
+
jiraOwner.set(it.id, it.repo);
|
|
370
|
+
items.push(it);
|
|
371
|
+
} else if (owner !== it.repo) {
|
|
372
|
+
duplicates.push({
|
|
373
|
+
...it,
|
|
374
|
+
reason: `also matched for ${owner}, queued there - give each repo a jiraJql that matches only its own issues`,
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
}
|
|
301
378
|
}
|
|
302
|
-
return items;
|
|
379
|
+
return { items, duplicates };
|
|
303
380
|
}
|
|
304
381
|
|
|
305
382
|
// ---------------------------------------------------------------------------
|
|
@@ -313,6 +390,17 @@ function atomicWrite(name, text) {
|
|
|
313
390
|
renameSync(tmp, dst);
|
|
314
391
|
}
|
|
315
392
|
|
|
393
|
+
function readQueue() {
|
|
394
|
+
const qPath = join(ROOT, "queue.json");
|
|
395
|
+
if (!existsSync(qPath)) return { queued: [], running: [] };
|
|
396
|
+
try {
|
|
397
|
+
const q = JSON.parse(readFileSync(qPath, "utf-8"));
|
|
398
|
+
return q && typeof q === "object" && !Array.isArray(q) ? q : { queued: [], running: [] };
|
|
399
|
+
} catch {
|
|
400
|
+
return { queued: [], running: [] };
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
316
404
|
function main(argv) {
|
|
317
405
|
const args = argv.slice(2);
|
|
318
406
|
const has = (f) => args.includes(f);
|
|
@@ -326,10 +414,31 @@ function main(argv) {
|
|
|
326
414
|
}
|
|
327
415
|
|
|
328
416
|
const cfgPath = join(ROOT, "config.json");
|
|
329
|
-
|
|
417
|
+
let config = { repos: [] };
|
|
418
|
+
let refusal = null;
|
|
419
|
+
if (existsSync(cfgPath)) {
|
|
420
|
+
try {
|
|
421
|
+
config = JSON.parse(readFileSync(cfgPath, "utf-8"));
|
|
422
|
+
refusal = configRefusal(config);
|
|
423
|
+
} catch (e) {
|
|
424
|
+
refusal = `autopilot config.json cannot be read: ${e?.message || e}`;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
// A ceiling that is not a number compares false with everything, which would
|
|
428
|
+
// retry an item forever. Nothing is queued until the config is corrected.
|
|
429
|
+
if (refusal) {
|
|
430
|
+
const queue = { ...readQueue(), lastTickAt: Math.floor(Date.now() / 1000) };
|
|
431
|
+
queue.queued = [];
|
|
432
|
+
queue.blockedReason = refusal;
|
|
433
|
+
if (!has("--dry-run")) atomicWrite("queue.json", JSON.stringify(queue, null, 2));
|
|
434
|
+
process.stderr.write(`autopilot-intake: ${refusal}\n`);
|
|
435
|
+
return 3;
|
|
436
|
+
}
|
|
330
437
|
|
|
331
438
|
const fromFile = val("--from");
|
|
332
|
-
const candidates
|
|
439
|
+
const { items: candidates, duplicates } = fromFile
|
|
440
|
+
? { items: JSON.parse(readFileSync(fromFile, "utf-8")), duplicates: [] }
|
|
441
|
+
: gather(config);
|
|
333
442
|
|
|
334
443
|
const attemptPath = join(ROOT, "attempted.jsonl");
|
|
335
444
|
const history = foldAttempts(
|
|
@@ -347,22 +456,14 @@ function main(argv) {
|
|
|
347
456
|
// The existing queue's `running` list is preserved: intake decides what is
|
|
348
457
|
// NEXT and has no opinion about what is already in flight. Overwriting it here
|
|
349
458
|
// would make a scan look like a crash to the status reader.
|
|
350
|
-
|
|
351
|
-
const qPath = join(ROOT, "queue.json");
|
|
352
|
-
if (existsSync(qPath)) {
|
|
353
|
-
try {
|
|
354
|
-
running = JSON.parse(readFileSync(qPath, "utf-8")).running || [];
|
|
355
|
-
} catch {
|
|
356
|
-
running = [];
|
|
357
|
-
}
|
|
358
|
-
}
|
|
459
|
+
const running = readQueue().running || [];
|
|
359
460
|
|
|
360
461
|
const queue = {
|
|
361
462
|
lastTickAt: Math.floor(Date.now() / 1000),
|
|
362
463
|
running,
|
|
363
464
|
queued: ordered,
|
|
364
465
|
awaiting,
|
|
365
|
-
dropped,
|
|
466
|
+
dropped: [...dropped, ...duplicates],
|
|
366
467
|
emptyReason:
|
|
367
468
|
ordered.length === 0 && awaiting.length === 0
|
|
368
469
|
? candidates.length === 0
|