@mmerterden/multi-agent-pipeline 20.33.0 → 20.35.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 +98 -1
- package/README.md +3 -1
- package/README.tr.md +2 -1
- package/docs/adr/0018-cross-repo-links-not-a-global-graph.md +43 -0
- package/docs/adr/README.md +2 -1
- package/docs/facts.json +5 -4
- package/docs/features.md +1 -1
- package/install/_dev-only-files.mjs +1 -0
- package/install/catalog-history.json +1 -1
- package/install/claude.mjs +24 -2
- package/install/templates/claude-hooks.json +34 -1
- package/manifest.json +393 -339
- package/package.json +3 -1
- package/pipeline/agents/bulk-reader.md +3 -0
- package/pipeline/agents/code-reviewer.md +9 -0
- package/pipeline/agents/explorer.md +4 -0
- package/pipeline/agents/plan-critic.md +4 -2
- package/pipeline/commands/multi-agent/SKILL.md +17 -136
- package/pipeline/commands/multi-agent/channels/SKILL.md +16 -298
- package/pipeline/commands/multi-agent/graph/SKILL.md +5 -2
- package/pipeline/commands/multi-agent/language/SKILL.md +3 -3
- package/pipeline/commands/multi-agent/office-on/SKILL.md +7 -3
- package/pipeline/commands/multi-agent/office-status/SKILL.md +3 -2
- package/pipeline/commands/multi-agent/resume/SKILL.md +8 -22
- package/pipeline/commands/multi-agent/review/SKILL.md +7 -131
- package/pipeline/commands/multi-agent/setup/SKILL.md +19 -224
- package/pipeline/contract/CHANGELOG.md +9 -0
- package/pipeline/contract/README.md +6 -2
- package/pipeline/contract/fixtures/error-invalid-request.json +1 -1
- package/pipeline/contract/fixtures/error-unauthorized.json +1 -1
- package/pipeline/contract/fixtures/error-unsigned.json +1 -1
- package/pipeline/contract/manifest.json +14 -1
- package/pipeline/contract/types/index.d.ts +24 -2
- package/pipeline/lib/json-file-lock.mjs +61 -15
- package/pipeline/lib/office-remote.mjs +228 -0
- package/pipeline/lib/qr-code.mjs +360 -0
- package/pipeline/lib/repo-hygiene.sh +1 -0
- package/pipeline/lib/run-completion.mjs +17 -0
- package/pipeline/multi-agent-refs/channels/generator.md +146 -0
- package/pipeline/multi-agent-refs/channels/issue-comment.md +1 -1
- package/pipeline/multi-agent-refs/channels/menu.md +55 -0
- package/pipeline/multi-agent-refs/channels/multi-repo.md +6 -0
- package/pipeline/multi-agent-refs/channels/preview.md +25 -0
- package/pipeline/multi-agent-refs/channels/reference.md +98 -0
- package/pipeline/multi-agent-refs/features/autopilot-circuit-breaker.md +1 -1
- package/pipeline/multi-agent-refs/features/code-graph.md +27 -0
- package/pipeline/multi-agent-refs/features/office-remote-protocol.md +166 -0
- package/pipeline/multi-agent-refs/features/office-threat-model.md +2 -2
- package/pipeline/multi-agent-refs/features/plan-critic.md +5 -2
- package/pipeline/multi-agent-refs/features/review-delta.md +4 -1
- package/pipeline/multi-agent-refs/features/scope-check.md +25 -1
- package/pipeline/multi-agent-refs/features/verify-by-test.md +10 -0
- package/pipeline/multi-agent-refs/keychain.md +7 -0
- package/pipeline/multi-agent-refs/knowledge.md +9 -0
- package/pipeline/multi-agent-refs/orchestrator/dispatcher.md +163 -0
- package/pipeline/multi-agent-refs/phases/phase-0-init.md +6 -2
- package/pipeline/multi-agent-refs/phases/phase-1-plan.md +8 -10
- package/pipeline/multi-agent-refs/phases/phase-2-dev.md +18 -20
- package/pipeline/multi-agent-refs/phases/phase-3-review.md +20 -14
- package/pipeline/multi-agent-refs/phases/phase-4-commit.md +8 -7
- package/pipeline/multi-agent-refs/phases/phase-5-report.md +6 -3
- package/pipeline/multi-agent-refs/picker-contract.md +1 -1
- package/pipeline/multi-agent-refs/resume/details.md +35 -0
- package/pipeline/multi-agent-refs/review/inputs.md +87 -0
- package/pipeline/multi-agent-refs/review/module-guides.md +25 -0
- package/pipeline/multi-agent-refs/review/valven.md +42 -0
- package/pipeline/multi-agent-refs/rules.md +3 -2
- package/pipeline/multi-agent-refs/setup/accounts.md +27 -0
- package/pipeline/multi-agent-refs/setup/app-store-connect.md +5 -0
- package/pipeline/multi-agent-refs/setup/firebase.md +5 -0
- package/pipeline/multi-agent-refs/setup/google-play.md +4 -0
- package/pipeline/multi-agent-refs/setup/hooks-and-plugins.md +21 -0
- package/pipeline/multi-agent-refs/setup/language.md +46 -0
- package/pipeline/multi-agent-refs/setup/multi-repo-group.md +51 -0
- package/pipeline/multi-agent-refs/setup/summaries.md +63 -0
- package/pipeline/multi-agent-refs/setup/token-save-flow.md +51 -0
- package/pipeline/multi-agent-refs/tracker-contract.md +1 -1
- package/pipeline/office/NOTICE.md +4 -1
- package/pipeline/office/assets/char_12.png +0 -0
- package/pipeline/office/assets/char_13.png +0 -0
- package/pipeline/office/assets/char_14.png +0 -0
- package/pipeline/office/assets/char_15.png +0 -0
- package/pipeline/office/assets/char_16.png +0 -0
- package/pipeline/office/assets/char_17.png +0 -0
- package/pipeline/office/assets/char_18.png +0 -0
- package/pipeline/office/assets/char_19.png +0 -0
- package/pipeline/office/assets/char_20.png +0 -0
- package/pipeline/office/assets/char_21.png +0 -0
- package/pipeline/office/assets/char_22.png +0 -0
- package/pipeline/office/assets/char_23.png +0 -0
- package/pipeline/office/assets/char_24.png +0 -0
- package/pipeline/office/assets/char_25.png +0 -0
- package/pipeline/office/assets/char_26.png +0 -0
- package/pipeline/office/assets/char_27.png +0 -0
- package/pipeline/office/assets/char_28.png +0 -0
- package/pipeline/office/assets/char_29.png +0 -0
- package/pipeline/office/assets/char_30.png +0 -0
- package/pipeline/office/index.html +304 -55
- package/pipeline/office/toolkit.json +1 -1
- package/pipeline/rules/response-shape.md +6 -7
- package/pipeline/schemas/agent-state.schema.json +36 -0
- package/pipeline/schemas/phases.json +4 -4
- package/pipeline/schemas/plan-critique.schema.json +9 -2
- package/pipeline/schemas/planning-output.schema.json +43 -2
- package/pipeline/schemas/pr-reach.schema.json +55 -0
- package/pipeline/schemas/prefs.schema.json +37 -8
- package/pipeline/schemas/reviewer-output.schema.json +20 -2
- package/pipeline/schemas/token-budget.json +4 -4
- package/pipeline/schemas/triage-output.schema.json +32 -3
- package/pipeline/schemas/unattended-policy.json +2 -1
- package/pipeline/scripts/_graph-analysis.mjs +270 -0
- package/pipeline/scripts/_guard_rules.py +449 -1
- package/pipeline/scripts/_memory-policy.mjs +165 -0
- package/pipeline/scripts/_secret-scan.mjs +105 -0
- package/pipeline/scripts/_test-gaming.mjs +36 -0
- package/pipeline/scripts/_unified-diff.mjs +2 -2
- package/pipeline/scripts/agent-guard.py +79 -19
- package/pipeline/scripts/anonymize-findings.mjs +99 -0
- package/pipeline/scripts/answer-check.mjs +113 -0
- package/pipeline/scripts/answer-check.sh +20 -0
- package/pipeline/scripts/autopilot-publish.mjs +9 -2
- package/pipeline/scripts/capture-flush.sh +12 -2
- package/pipeline/scripts/check-read-size.sh +9 -0
- package/pipeline/scripts/code-graph-rules/android.json +8 -3
- package/pipeline/scripts/contract-server.mjs +71 -16
- package/pipeline/scripts/debt-ledger.mjs +323 -0
- package/pipeline/scripts/file-context.mjs +261 -0
- package/pipeline/scripts/file-context.sh +20 -0
- package/pipeline/scripts/gate-ledger.mjs +144 -21
- package/pipeline/scripts/graph-links.mjs +230 -0
- package/pipeline/scripts/graph-query.mjs +133 -1
- package/pipeline/scripts/graph-report.mjs +65 -0
- package/pipeline/scripts/learn-from-transcripts.mjs +12 -48
- package/pipeline/scripts/learnings-ledger.mjs +143 -24
- package/pipeline/scripts/office-build.mjs +276 -5
- package/pipeline/scripts/office-control.mjs +70 -10
- package/pipeline/scripts/office-pair.mjs +407 -0
- package/pipeline/scripts/office-remote-client.mjs +463 -0
- package/pipeline/scripts/phase-tracker.sh +8 -0
- package/pipeline/scripts/phase0-exit-gate.mjs +40 -37
- package/pipeline/scripts/phone-devices.mjs +9 -1
- package/pipeline/scripts/plan-critique-gate.mjs +11 -2
- package/pipeline/scripts/pre-commit-check.sh +28 -2
- package/pipeline/scripts/pre-push-check.sh +6 -12
- package/pipeline/scripts/rework-base.mjs +87 -0
- package/pipeline/scripts/rework-rulings.mjs +106 -0
- package/pipeline/scripts/run-commit-check.mjs +104 -0
- package/pipeline/scripts/run-scope-guard.mjs +58 -3
- package/pipeline/scripts/run-scope-guard.sh +13 -1
- package/pipeline/scripts/scope-check-gate.mjs +213 -2
- package/pipeline/scripts/task-mirror.mjs +106 -15
- package/pipeline/scripts/task-mirror.sh +3 -2
- package/pipeline/scripts/test-stability-gate.mjs +112 -0
- package/pipeline/scripts/triage-memory.mjs +64 -37
- package/pipeline/scripts/update-check.sh +7 -1
- package/pipeline/scripts/update-issue-progress.sh +73 -8
- package/pipeline/scripts/validate-planning.mjs +172 -4
- package/pipeline/scripts/validate-reviewer.mjs +20 -0
- package/pipeline/scripts/validate-triage.mjs +149 -4
- package/pipeline/scripts/work-items.mjs +119 -1
- package/pipeline/scripts/worktree-prepare-all.mjs +200 -0
- package/pipeline/scripts/worktree-prepare.sh +40 -4
- package/pipeline/scripts/write-state.mjs +67 -24
- package/pipeline/skills/.skill-manifest.json +9 -9
- package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +5 -5
- package/pipeline/skills/shared/core/google-play-compliance/references/rules.yml +1 -1
- package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-graph/SKILL.md +5 -2
- package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +4 -4
- package/pipeline/skills/shared/core/multi-agent-office-status/SKILL.md +2 -2
- package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +2 -0
- package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +4 -4
- package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +14 -0
- package/pipeline/skills/shared/external/android-architecture/references/patterns.md +6 -0
- package/pipeline/skills/shared/external/android-build-quality-gates/references/patterns.md +10 -0
- package/pipeline/skills/shared/external/android-datastore/references/patterns.md +11 -0
- package/pipeline/skills/shared/external/android-design-tokens-codegen/references/patterns.md +8 -0
- package/pipeline/skills/shared/external/android-jetpack-compose-expert/references/patterns.md +6 -0
- package/pipeline/skills/shared/external/android-mvi-viewmodel/references/patterns.md +10 -0
- package/pipeline/skills/shared/external/android-performance/references/patterns.md +13 -0
- package/pipeline/skills/shared/external/android-security/references/patterns.md +16 -0
- package/pipeline/skills/shared/external/api-patterns/references/contract-details.md +9 -0
- package/pipeline/skills/shared/external/api-security-best-practices/references/abuse-controls.md +12 -0
- package/pipeline/skills/shared/external/api-security-best-practices/references/identity-and-access.md +13 -0
- package/pipeline/skills/shared/external/api-security-best-practices/references/request-handling.md +12 -0
- package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +9 -0
- package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +8 -0
- package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +10 -0
- package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +21 -0
- package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +9 -0
- package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +7 -0
- package/pipeline/skills/shared/external/app-store-review/SKILL.md +2 -2
- package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +10 -0
- package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +10 -1
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +22 -0
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +17 -0
- package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +22 -0
- package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +17 -0
- package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +9 -0
- package/pipeline/skills/shared/external/authentication/references/passkeys.md +11 -0
- package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +13 -0
- package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +9 -0
- package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +10 -0
- package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +15 -0
- package/pipeline/skills/shared/external/compose-components/references/patterns.md +7 -0
- package/pipeline/skills/shared/external/compose-navigation/references/patterns.md +7 -0
- package/pipeline/skills/shared/external/compose-testing/references/patterns.md +15 -0
- package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +9 -0
- package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +11 -0
- package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +10 -0
- package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +13 -0
- package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +20 -0
- package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +16 -0
- package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +16 -0
- package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +14 -0
- package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +13 -0
- package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +10 -0
- package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +10 -0
- package/pipeline/skills/shared/external/fastapi-pro/references/app-structure.md +10 -0
- package/pipeline/skills/shared/external/gradle-kotlin-dsl/references/patterns.md +17 -0
- package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +12 -0
- package/pipeline/skills/shared/external/hig-app-icons/references/icon-workflow.md +10 -0
- package/pipeline/skills/shared/external/hig-components-content/references/content-views.md +10 -0
- package/pipeline/skills/shared/external/hig-components-layout/references/bars-and-tabs.md +11 -0
- package/pipeline/skills/shared/external/hig-foundations/references/foundations-detail.md +13 -0
- package/pipeline/skills/shared/external/hig-foundations/references/type-color-spacing.md +13 -0
- package/pipeline/skills/shared/external/hig-patterns/references/onboarding-and-states.md +11 -0
- package/pipeline/skills/shared/external/hig-platforms/references/ipad-layout.md +12 -0
- package/pipeline/skills/shared/external/hig-technologies/references/technologies.md +16 -0
- package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +9 -0
- package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +18 -0
- package/pipeline/skills/shared/external/ios-accessibility/references/large-content-and-appearance.md +9 -0
- package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +9 -0
- package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +7 -0
- package/pipeline/skills/shared/external/ios-coding-standard/references/STANDARD.md +13 -0
- package/pipeline/skills/shared/external/ios-design-review/references/appearance-matrix.md +9 -0
- package/pipeline/skills/shared/external/ios-design-review/references/checklist.md +15 -0
- package/pipeline/skills/shared/external/ios-haptics/references/core-haptics.md +11 -0
- package/pipeline/skills/shared/external/ios-iphone-duo/references/api-map.md +11 -0
- package/pipeline/skills/shared/external/ios-iphone-duo/references/fixed-assumptions.md +15 -0
- package/pipeline/skills/shared/external/ios-iphone-duo/references/poses-and-panes.md +11 -0
- package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +18 -0
- package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +19 -0
- package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +15 -0
- package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +7 -0
- package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +8 -0
- package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +12 -0
- package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +17 -0
- package/pipeline/skills/shared/external/ios-security/references/app-review-guidelines.md +8 -0
- package/pipeline/skills/shared/external/ios-security/references/cryptokit-advanced.md +14 -0
- package/pipeline/skills/shared/external/ios-security/references/file-storage-patterns.md +8 -0
- package/pipeline/skills/shared/external/ios-security/references/privacy-manifest.md +9 -0
- package/pipeline/skills/shared/external/ios-sf-symbols/references/effects-and-custom-symbols.md +9 -0
- package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +13 -0
- package/pipeline/skills/shared/external/kotlin-coroutines-expert/references/patterns.md +8 -0
- package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +21 -0
- package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +9 -0
- package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +12 -0
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +16 -0
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +21 -0
- package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +10 -0
- package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +9 -0
- package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +12 -0
- package/pipeline/skills/shared/external/nodejs-backend-patterns/references/runtime-patterns.md +11 -0
- package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +11 -0
- package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +18 -0
- package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +11 -0
- package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +11 -0
- package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +15 -0
- package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +14 -0
- package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +14 -0
- package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +14 -0
- package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +14 -0
- package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +10 -0
- package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +12 -0
- package/pipeline/skills/shared/external/retrofit-networking/references/patterns.md +14 -0
- package/pipeline/skills/shared/external/room-database/references/patterns.md +16 -0
- package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +10 -0
- package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +10 -0
- package/pipeline/skills/shared/external/spm-build-analysis/references/build-optimization-sources.md +14 -0
- package/pipeline/skills/shared/external/spm-build-analysis/references/spm-analysis-checks.md +19 -0
- package/pipeline/skills/shared/external/storekit/references/core-patterns.md +13 -0
- package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +31 -0
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +8 -0
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +9 -0
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +10 -0
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +8 -0
- package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +24 -0
- package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +8 -0
- package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +14 -0
- package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +12 -0
- package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +10 -0
- package/pipeline/skills/shared/external/swift-concurrency-expert/references/swift-6-2-concurrency.md +8 -0
- package/pipeline/skills/shared/external/swift-concurrency-pro/references/actors.md +10 -0
- package/pipeline/skills/shared/external/swift-concurrency-pro/references/cancellation.md +7 -0
- package/pipeline/skills/shared/external/swift-concurrency-pro/references/interop.md +10 -0
- package/pipeline/skills/shared/external/swift-concurrency-pro/references/new-features.md +11 -0
- package/pipeline/skills/shared/external/swift-concurrency-pro/references/structured.md +9 -0
- package/pipeline/skills/shared/external/swift-concurrency-pro/references/testing.md +13 -0
- package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +7 -0
- package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +14 -0
- package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +16 -0
- package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +17 -0
- package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +19 -0
- package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +16 -0
- package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +19 -0
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +18 -0
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +16 -0
- package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +17 -0
- package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +17 -0
- package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +17 -0
- package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +18 -0
- package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +21 -0
- package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +16 -0
- package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +16 -0
- package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +9 -0
- package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +24 -0
- package/pipeline/skills/shared/external/swift-testing-pro/references/async-tests.md +9 -0
- package/pipeline/skills/shared/external/swift-testing-pro/references/new-features.md +11 -0
- package/pipeline/skills/shared/external/swift-testing-pro/references/writing-better-tests.md +13 -0
- package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +8 -0
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +17 -0
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +12 -0
- package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +11 -0
- package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +7 -0
- package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +13 -0
- package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +24 -0
- package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +12 -0
- package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +15 -0
- package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +15 -0
- package/pipeline/skills/shared/external/swiftui-animation/references/scroll-effects.md +12 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/accessibility-patterns.md +11 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-advanced.md +7 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-basics.md +13 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-transitions.md +9 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/charts-accessibility.md +9 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/charts.md +17 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/image-optimization.md +9 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/latest-apis.md +10 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/layout-best-practices.md +12 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/list-patterns.md +12 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/macos-scenes.md +13 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/macos-views.md +12 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/macos-window-styling.md +12 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/performance-patterns.md +7 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/scroll-patterns.md +9 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/sheet-navigation-patterns.md +10 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/state-management.md +18 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/view-structure.md +16 -0
- package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +11 -0
- package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +8 -0
- package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +14 -0
- package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +9 -0
- package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +22 -0
- package/pipeline/skills/shared/external/swiftui-liquid-glass/references/uikit-glass.md +14 -0
- package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +10 -0
- package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +10 -0
- package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +13 -0
- package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +10 -0
- package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +14 -0
- package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +30 -0
- package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +16 -0
- package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +11 -0
- package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +11 -0
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +10 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/code-smells.md +8 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/app-wiring.md +12 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/menu-bar.md +10 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/navigationstack.md +11 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/scroll-reveal.md +12 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/sheets.md +14 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/tabview.md +10 -0
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +10 -0
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +13 -0
- package/pipeline/skills/shared/external/swiftui-view-refactor/references/mv-patterns.md +12 -0
- package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +8 -0
- package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +8 -0
- package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +14 -0
- package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +17 -0
- package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +11 -0
- package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +11 -0
- package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +27 -0
- package/pipeline/skills/shared/external/xcode-build-fixer/references/build-settings-best-practices.md +9 -0
- package/pipeline/skills/shared/external/xcode-build-fixer/references/fix-patterns.md +7 -0
- package/pipeline/skills/shared/external/xcode-build-orchestrator/references/build-settings-best-practices.md +9 -0
- package/pipeline/skills/shared/external/xcode-compilation-analyzer/references/build-optimization-sources.md +14 -0
- package/pipeline/skills/shared/external/xcode-compilation-analyzer/references/code-compilation-checks.md +8 -0
- package/pipeline/skills/shared/external/xcode-project-analyzer/references/build-optimization-sources.md +14 -0
- package/pipeline/skills/shared/external/xcode-project-analyzer/references/build-settings-best-practices.md +9 -0
- package/pipeline/skills/shared/external/xcode-project-analyzer/references/project-audit-checks.md +13 -0
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
* Storage: append-only JSONL, one file per repo:
|
|
11
11
|
* $HOME/.claude/memory/multi-agent/<repo-slug>/triage-corpus.jsonl
|
|
12
12
|
*
|
|
13
|
-
* Each line conforms to pipeline/schemas/triage-corpus.schema.json.
|
|
13
|
+
* Each line conforms to pipeline/schemas/triage-corpus.schema.json. Every row
|
|
14
|
+
* passes the secret scan in _secret-scan.mjs before it is written; one that
|
|
15
|
+
* fails is counted in `droppedBySecretScan` and left out.
|
|
14
16
|
*
|
|
15
17
|
* Why JSONL not SQLite: zero deps, Node 18+ compatible, easy to grep/diff,
|
|
16
18
|
* easy to delete a single row by line. The cost of a full corpus scan is
|
|
@@ -55,6 +57,8 @@ import { readFileSync, existsSync, mkdirSync, appendFileSync, statSync } from "n
|
|
|
55
57
|
import { homedir } from "node:os";
|
|
56
58
|
import { execFileSync } from "node:child_process";
|
|
57
59
|
import { join, basename, dirname, posix } from "node:path";
|
|
60
|
+
import { checkedSlug, memoryExcluded } from "./_memory-policy.mjs";
|
|
61
|
+
import { openScanner, stripPrivate } from "./_secret-scan.mjs";
|
|
58
62
|
import {
|
|
59
63
|
bm25,
|
|
60
64
|
recencyRank,
|
|
@@ -91,6 +95,10 @@ function die(msg, code = 1) {
|
|
|
91
95
|
// prior-art recall always miss. `--git-common-dir` points at the main
|
|
92
96
|
// repository's .git for every linked worktree.
|
|
93
97
|
function repoSlug() {
|
|
98
|
+
return checkedSlug(rawRepoSlug());
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function rawRepoSlug() {
|
|
94
102
|
if (flags["repo-slug"]) return String(flags["repo-slug"]);
|
|
95
103
|
if (process.env.MULTI_AGENT_REPO_SLUG) return process.env.MULTI_AGENT_REPO_SLUG;
|
|
96
104
|
try {
|
|
@@ -249,9 +257,14 @@ function ingest() {
|
|
|
249
257
|
const fromState = stateDefaults();
|
|
250
258
|
const taskId = flags["task-id"] || fromState.taskId;
|
|
251
259
|
if (!taskId) die("ingest needs --task-id <id> (or --state with a taskId)", 1);
|
|
252
|
-
const taskTitle = flags["task-title"] || fromState.taskTitle || null;
|
|
260
|
+
const taskTitle = stripPrivate(flags["task-title"] || fromState.taskTitle || "").trim() || null;
|
|
253
261
|
const stack = flags.stack || fromState.stack || null;
|
|
254
262
|
const slug = repoSlug();
|
|
263
|
+
if (memoryExcluded(slug)) {
|
|
264
|
+
process.stdout.write(JSON.stringify({ ok: true, slug, ingested: 0, excluded: true }) + "\n");
|
|
265
|
+
process.exitCode = 2;
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
255
268
|
|
|
256
269
|
let triage;
|
|
257
270
|
try {
|
|
@@ -274,35 +287,51 @@ function ingest() {
|
|
|
274
287
|
];
|
|
275
288
|
|
|
276
289
|
let written = 0;
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
290
|
+
let droppedBySecretScan = 0;
|
|
291
|
+
const scan = openScanner();
|
|
292
|
+
try {
|
|
293
|
+
for (const [classification, rows] of buckets) {
|
|
294
|
+
for (const f of rows) {
|
|
295
|
+
const issue = stripPrivate(f.issue || "").trim();
|
|
296
|
+
if (!issue) continue;
|
|
297
|
+
const file = f.file || "";
|
|
298
|
+
const key = `${taskId}::${classification}::${file}::${issue}`;
|
|
299
|
+
if (seen.has(key)) continue;
|
|
300
|
+
const fix = f.fix ? stripPrivate(f.fix).trim() || null : null;
|
|
301
|
+
const reason = f._reason ? stripPrivate(f._reason).trim() || null : null;
|
|
302
|
+
const reviewer = f.reviewer || null;
|
|
303
|
+
const stored = [issue, fix, reason, file, taskTitle, taskId, stack, reviewer, f.severity];
|
|
304
|
+
if (!scan.isClean(stored.filter(Boolean).join("\n"))) {
|
|
305
|
+
droppedBySecretScan++;
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
const row = {
|
|
309
|
+
v: "1.0.0",
|
|
310
|
+
ts,
|
|
311
|
+
task_id: taskId,
|
|
312
|
+
task_title: taskTitle,
|
|
313
|
+
stack,
|
|
314
|
+
classification,
|
|
315
|
+
severity: f.severity || "suggestion",
|
|
316
|
+
file,
|
|
317
|
+
line: typeof f.line === "number" ? f.line : null,
|
|
318
|
+
issue,
|
|
319
|
+
fix,
|
|
320
|
+
reason,
|
|
321
|
+
reviewer,
|
|
322
|
+
file_sha: fileSha(file, top),
|
|
323
|
+
};
|
|
324
|
+
writeRow(slug, row);
|
|
325
|
+
seen.add(key);
|
|
326
|
+
written++;
|
|
327
|
+
}
|
|
303
328
|
}
|
|
329
|
+
} finally {
|
|
330
|
+
scan.close();
|
|
304
331
|
}
|
|
305
|
-
process.stdout.write(
|
|
332
|
+
process.stdout.write(
|
|
333
|
+
JSON.stringify({ ok: true, slug, ingested: written, droppedBySecretScan }) + "\n",
|
|
334
|
+
);
|
|
306
335
|
// exitCode, not exit(): even this one-line write is on the same rule, and a
|
|
307
336
|
// rule with an exception is the one that gets copied into the next branch.
|
|
308
337
|
// 2 = nothing new, which callers treat as an idempotent success.
|
|
@@ -313,7 +342,7 @@ function ingest() {
|
|
|
313
342
|
function query() {
|
|
314
343
|
const cfg = recallConfig();
|
|
315
344
|
const topN = flags.top ? Math.max(1, Number(flags.top)) : cfg.maxResults;
|
|
316
|
-
const slug =
|
|
345
|
+
const slug = repoSlug();
|
|
317
346
|
const corpus = readCorpus(slug);
|
|
318
347
|
if (corpus.length === 0) {
|
|
319
348
|
process.stdout.write(JSON.stringify({ ok: true, slug, hits: [], total: 0 }) + "\n");
|
|
@@ -347,7 +376,7 @@ function priorArt() {
|
|
|
347
376
|
: [];
|
|
348
377
|
const cfg = recallConfig();
|
|
349
378
|
const topN = flags.top ? Math.max(1, Number(flags.top)) : cfg.maxResults;
|
|
350
|
-
const slug =
|
|
379
|
+
const slug = repoSlug();
|
|
351
380
|
const corpus = readCorpus(slug);
|
|
352
381
|
const out = list.map((f) => {
|
|
353
382
|
if (corpus.length === 0) return [];
|
|
@@ -436,7 +465,7 @@ function rank(corpus, issueText, fileGlob, topN, cfg) {
|
|
|
436
465
|
function showCmd() {
|
|
437
466
|
const id = flags.id && flags.id !== true ? String(flags.id) : null;
|
|
438
467
|
if (!id) die("show needs --id <id>", 1);
|
|
439
|
-
const slug =
|
|
468
|
+
const slug = repoSlug();
|
|
440
469
|
const want = id.startsWith("T:") ? id : `T:${id}`;
|
|
441
470
|
const row = readCorpus(slug).find((r) => rowId(r) === want);
|
|
442
471
|
if (!row) {
|
|
@@ -465,7 +494,7 @@ function showCmd() {
|
|
|
465
494
|
function timelineCmd() {
|
|
466
495
|
const id = flags.anchor && flags.anchor !== true ? String(flags.anchor) : null;
|
|
467
496
|
if (!id) die("timeline needs --anchor <id>", 1);
|
|
468
|
-
const slug =
|
|
497
|
+
const slug = repoSlug();
|
|
469
498
|
const before = flags.before && flags.before !== true ? Math.max(0, Number(flags.before)) : 3;
|
|
470
499
|
const after = flags.after && flags.after !== true ? Math.max(0, Number(flags.after)) : 3;
|
|
471
500
|
const want = id.startsWith("T:") ? id : `T:${id}`;
|
|
@@ -495,15 +524,13 @@ function timelineCmd() {
|
|
|
495
524
|
}
|
|
496
525
|
|
|
497
526
|
function pathCmd() {
|
|
498
|
-
process.stdout.write(
|
|
499
|
-
corpusPath(flags["repo-slug"] ? String(flags["repo-slug"]) : repoSlug()) + "\n",
|
|
500
|
-
);
|
|
527
|
+
process.stdout.write(corpusPath(repoSlug()) + "\n");
|
|
501
528
|
process.exitCode = 0;
|
|
502
529
|
return;
|
|
503
530
|
}
|
|
504
531
|
|
|
505
532
|
function statsCmd() {
|
|
506
|
-
const slug =
|
|
533
|
+
const slug = repoSlug();
|
|
507
534
|
const corpus = readCorpus(slug);
|
|
508
535
|
const counts = { accepted: 0, deferred: 0, rejected: 0 };
|
|
509
536
|
for (const r of corpus) if (counts[r.classification] !== undefined) counts[r.classification]++;
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
# # updateCheck.ttlHours, else 24)
|
|
31
31
|
# bash pipeline/scripts/update-check.sh --force # ignore cache
|
|
32
32
|
# bash pipeline/scripts/update-check.sh --print-required # emit the floor only
|
|
33
|
+
# bash pipeline/scripts/update-check.sh --cache-only # cached answer at any age, never the registry
|
|
33
34
|
#
|
|
34
35
|
# Cache file: ~/.claude/logs/multi-agent/.update-check ("epoch|latest|required").
|
|
35
36
|
# A legacy two-field cache ("epoch|latest") still reads - the missing third
|
|
@@ -47,6 +48,7 @@ FAIL_TTL_SECONDS=3600
|
|
|
47
48
|
LOCAL_VERSION=""
|
|
48
49
|
FORCE=0
|
|
49
50
|
PRINT_REQUIRED=0
|
|
51
|
+
CACHE_ONLY=0
|
|
50
52
|
|
|
51
53
|
while [ $# -gt 0 ]; do
|
|
52
54
|
case "$1" in
|
|
@@ -54,6 +56,7 @@ while [ $# -gt 0 ]; do
|
|
|
54
56
|
--ttl-hours) TTL_HOURS="${2:-}"; shift; [ $# -gt 0 ] && shift ;;
|
|
55
57
|
--force) FORCE=1; shift ;;
|
|
56
58
|
--print-required) PRINT_REQUIRED=1; shift ;;
|
|
59
|
+
--cache-only) CACHE_ONLY=1; shift ;;
|
|
57
60
|
*) shift ;;
|
|
58
61
|
esac
|
|
59
62
|
done
|
|
@@ -124,12 +127,15 @@ if [ "$FORCE" -eq 0 ] && [ -f "$CACHE_FILE" ]; then
|
|
|
124
127
|
case "$cached_epoch" in (*[!0-9]*|"") cached_epoch=0 ;; esac
|
|
125
128
|
# A stamp in the future is a clock or copy mistake, not a fresh answer.
|
|
126
129
|
[ "$cached_epoch" -gt "$now" ] && cached_epoch=0
|
|
127
|
-
if [ $((now - cached_epoch)) -lt $((TTL_HOURS * 3600)) ] && [ -n "$cached_latest" ]; then
|
|
130
|
+
if { [ "$CACHE_ONLY" -eq 1 ] || [ $((now - cached_epoch)) -lt $((TTL_HOURS * 3600)) ]; } && [ -n "$cached_latest" ]; then
|
|
128
131
|
latest="$cached_latest"
|
|
129
132
|
required="$cached_required"
|
|
130
133
|
fi
|
|
131
134
|
fi
|
|
132
135
|
|
|
136
|
+
# A cache-only caller gets no answer rather than a network wait.
|
|
137
|
+
[ -z "$latest" ] && [ "$CACHE_ONLY" -eq 1 ] && exit 0
|
|
138
|
+
|
|
133
139
|
# Stale or missing cache -> one bounded registry call (silent on any failure).
|
|
134
140
|
# The abbreviated packument carries dist-tags at a quarter of the full document.
|
|
135
141
|
# A failed read is remembered for FAIL_TTL_SECONDS in "<cache>.fail", so an
|
|
@@ -11,7 +11,13 @@
|
|
|
11
11
|
# never hand-edited.
|
|
12
12
|
#
|
|
13
13
|
# Usage:
|
|
14
|
-
# update-issue-progress.sh <task-id>
|
|
14
|
+
# update-issue-progress.sh <task-id> [--comment-file <path>]
|
|
15
|
+
#
|
|
16
|
+
# --comment-file posts that comment on the issue first (through the outbound
|
|
17
|
+
# gate, with the `Ref: #N` footer appended when missing), then the flags, so
|
|
18
|
+
# a caller with no separate comment step (the unattended runner) still writes
|
|
19
|
+
# both. `--body-file` is the same flag under the name the runner's script
|
|
20
|
+
# runner passes. Without it the flags wait for a comment already on the issue.
|
|
15
21
|
#
|
|
16
22
|
# Inputs:
|
|
17
23
|
# $HOME/.claude/logs/multi-agent/{project}/{taskId}/agent-state.json
|
|
@@ -26,6 +32,9 @@
|
|
|
26
32
|
# 2 missing agent-state.json
|
|
27
33
|
# 3 missing required flags
|
|
28
34
|
# 4 GitHub edit failed
|
|
35
|
+
# 5 no issue comment from this run yet: the comment is posted first and the
|
|
36
|
+
# flags follow it, both or neither (channels/issue-comment.md)
|
|
37
|
+
# 6 issue coordinates in the state that are not an owner/repo and a number
|
|
29
38
|
|
|
30
39
|
set -euo pipefail
|
|
31
40
|
|
|
@@ -118,9 +127,17 @@ EOF
|
|
|
118
127
|
|
|
119
128
|
TASK_ID="${1:-}"
|
|
120
129
|
if [ -z "$TASK_ID" ]; then
|
|
121
|
-
echo "usage: update-issue-progress.sh <task-id>" >&2
|
|
130
|
+
echo "usage: update-issue-progress.sh <task-id> [--comment-file <path>]" >&2
|
|
122
131
|
exit 64
|
|
123
132
|
fi
|
|
133
|
+
COMMENT_FILE=""
|
|
134
|
+
if [ "$TASK_ID" != "--rewrite" ] && [ "$#" -gt 1 ]; then
|
|
135
|
+
if [ "$#" -ne 3 ] || { [ "$2" != "--comment-file" ] && [ "$2" != "--body-file" ]; } || [ ! -f "$3" ]; then
|
|
136
|
+
echo "usage: update-issue-progress.sh <task-id> [--comment-file <path>]" >&2
|
|
137
|
+
exit 64
|
|
138
|
+
fi
|
|
139
|
+
COMMENT_FILE="$3"
|
|
140
|
+
fi
|
|
124
141
|
|
|
125
142
|
# Internal test seam: `--rewrite <body-file>` runs only the Progress-block
|
|
126
143
|
# rewrite (placeholder glyphs) and prints the result. No state, no gh.
|
|
@@ -155,6 +172,11 @@ if [ -z "$ORG_REPO" ] || [ -z "$ISSUE_NUM" ]; then
|
|
|
155
172
|
echo "update-issue-progress: no githubIssue in state for task=$TASK_ID (Jira-originated task, or issue not yet linked)" >&2
|
|
156
173
|
exit 3
|
|
157
174
|
fi
|
|
175
|
+
if ! printf '%s' "$ISSUE_NUM" | grep -Eq '^[0-9]{1,9}$' ||
|
|
176
|
+
! printf '%s' "$ORG_REPO" | grep -Eq '^[A-Za-z0-9][A-Za-z0-9-]{0,38}/[A-Za-z0-9._-]{1,100}$'; then
|
|
177
|
+
echo "update-issue-progress: githubIssue in state is not an owner/repo and a number; nothing written" >&2
|
|
178
|
+
exit 6
|
|
179
|
+
fi
|
|
158
180
|
|
|
159
181
|
# Read the four flags (default false).
|
|
160
182
|
F_IMPL=$(jq -r '.flags.implementation // false' "$AGENT_STATE")
|
|
@@ -190,17 +212,60 @@ NEW_BLOCK=$(build_progress_block "$G_IMPL" "$G_TEST" "$G_CC" "$G_WIKI")
|
|
|
190
212
|
# comment, next heading, or EOF) - see rewrite_progress_body above.
|
|
191
213
|
rewrite_progress_body "$NEW_BLOCK" "$TMP_BODY" > "$TMP_NEW"
|
|
192
214
|
|
|
193
|
-
#
|
|
194
|
-
|
|
215
|
+
# Whether the body changes (an unchanged body is an idempotent no-op for the
|
|
216
|
+
# flags), and the new body's outbound check before anything is posted, so a
|
|
217
|
+
# refused body never leaves a comment behind without its flags.
|
|
218
|
+
CHANGED=true
|
|
219
|
+
cmp -s "$TMP_BODY" "$TMP_NEW" && CHANGED=false
|
|
220
|
+
if [ "$CHANGED" = true ] && ! ma_outbound_gate "$TMP_NEW"; then
|
|
221
|
+
echo "update-issue-progress: outbound gate refused the new body; #$ISSUE_NUM left unchanged" >&2
|
|
222
|
+
exit 7
|
|
223
|
+
fi
|
|
224
|
+
|
|
225
|
+
# Both or neither: the flags follow this run's issue comment, never stand in
|
|
226
|
+
# for it. With --comment-file the comment is posted here, first, whether or
|
|
227
|
+
# not the flags change. Otherwise it
|
|
228
|
+
# is the one the authenticated account posted on the issue since the run
|
|
229
|
+
# started, carrying the template's `Ref: #N` footer.
|
|
230
|
+
if [ -n "$COMMENT_FILE" ]; then
|
|
231
|
+
TMP_COMMENT=$(mktemp "/tmp/issue-comment-${TASK_ID}.XXXXXX")
|
|
232
|
+
trap 'rm -f "$TMP_BODY" "$TMP_NEW" "$TMP_COMMENT"' EXIT
|
|
233
|
+
cat "$COMMENT_FILE" > "$TMP_COMMENT"
|
|
234
|
+
grep -qF "Ref: #$ISSUE_NUM" "$TMP_COMMENT" || printf '\n\nRef: #%s\n' "$ISSUE_NUM" >> "$TMP_COMMENT"
|
|
235
|
+
if ! ma_outbound_gate "$TMP_COMMENT"; then
|
|
236
|
+
echo "update-issue-progress: outbound gate refused the comment; #$ISSUE_NUM left unchanged" >&2
|
|
237
|
+
exit 7
|
|
238
|
+
fi
|
|
239
|
+
if ! gh issue comment "$ISSUE_NUM" --repo "$ORG_REPO" --body-file "$TMP_COMMENT" >/dev/null; then
|
|
240
|
+
echo "update-issue-progress: gh issue comment failed for #$ISSUE_NUM; flags left unchanged" >&2
|
|
241
|
+
exit 4
|
|
242
|
+
fi
|
|
243
|
+
elif [ "$CHANGED" = true ]; then
|
|
244
|
+
# The comments API reads `since` as an ISO 8601 instant; an offset's `+`
|
|
245
|
+
# would arrive as a space, so the start time goes out in UTC.
|
|
246
|
+
STARTED=$(jq -r '.startedAt // empty' "$AGENT_STATE")
|
|
247
|
+
STARTED=$(node -e 'const d = new Date(process.argv[1]); if (process.argv[1] && !isNaN(d)) process.stdout.write(d.toISOString().replace(/\.\d{3}Z$/, "Z"));' "$STARTED" 2>/dev/null || true)
|
|
248
|
+
ME=$(gh api user --jq .login 2>/dev/null || true)
|
|
249
|
+
if ! printf '%s' "$ME" | grep -Eq '^[A-Za-z0-9][A-Za-z0-9-]{0,38}(\[bot\])?$'; then
|
|
250
|
+
echo "update-issue-progress: could not read the GitHub account; #$ISSUE_NUM left unchanged" >&2
|
|
251
|
+
exit 5
|
|
252
|
+
fi
|
|
253
|
+
COMMENTS_PATH="repos/$ORG_REPO/issues/$ISSUE_NUM/comments"
|
|
254
|
+
[ -n "$STARTED" ] && COMMENTS_PATH="$COMMENTS_PATH?since=$STARTED"
|
|
255
|
+
if ! gh api --paginate "$COMMENTS_PATH" \
|
|
256
|
+
--jq ".[] | select(.user.login == \"$ME\") | select(.body | contains(\"Ref: #$ISSUE_NUM\")) | .id" 2>/dev/null |
|
|
257
|
+
grep -q .; then
|
|
258
|
+
echo "update-issue-progress: no issue comment from this run on #$ISSUE_NUM; post it first (comment and flags go together)" >&2
|
|
259
|
+
exit 5
|
|
260
|
+
fi
|
|
261
|
+
fi
|
|
262
|
+
|
|
263
|
+
if [ "$CHANGED" = false ]; then
|
|
195
264
|
echo "update-issue-progress: no change for #$ISSUE_NUM (idempotent no-op)" >&2
|
|
196
265
|
exit 0
|
|
197
266
|
fi
|
|
198
267
|
|
|
199
268
|
# Apply.
|
|
200
|
-
if ! ma_outbound_gate "$TMP_NEW"; then
|
|
201
|
-
echo "update-issue-progress: outbound gate refused the new body; #$ISSUE_NUM left unchanged" >&2
|
|
202
|
-
exit 7
|
|
203
|
-
fi
|
|
204
269
|
if ! gh issue edit "$ISSUE_NUM" --repo "$ORG_REPO" --body-file "$TMP_NEW" >/dev/null; then
|
|
205
270
|
echo "update-issue-progress: gh issue edit failed for #$ISSUE_NUM" >&2
|
|
206
271
|
exit 4
|
|
@@ -8,8 +8,12 @@
|
|
|
8
8
|
// Zero deps. Reads JSON from path arg or STDIN.
|
|
9
9
|
//
|
|
10
10
|
// Usage:
|
|
11
|
-
// node validate-planning.mjs path/to/plan.json
|
|
12
|
-
// cat plan.json | node validate-planning.mjs -
|
|
11
|
+
// node validate-planning.mjs path/to/plan.json [--spec <path>]
|
|
12
|
+
// cat plan.json | node validate-planning.mjs - [--spec <path>]
|
|
13
|
+
//
|
|
14
|
+
// --spec names the analysis document or task text the plan was written from.
|
|
15
|
+
// A plan more than SPEC_RATIO times its length gets a warning: a plan should
|
|
16
|
+
// record decisions, and one far longer than its spec is usually a transcript.
|
|
13
17
|
//
|
|
14
18
|
// Exit codes:
|
|
15
19
|
// 0 - valid
|
|
@@ -23,15 +27,113 @@
|
|
|
23
27
|
|
|
24
28
|
import { readFileSync } from "node:fs";
|
|
25
29
|
import { planOverlaps } from "./_plan-overlap.mjs";
|
|
30
|
+
import { sectionBody, tableDataRows } from "../lib/analysis-sections.mjs";
|
|
26
31
|
|
|
27
32
|
const ALLOWED_TYPES = new Set(["test", "code", "refactor", "docs", "chore"]);
|
|
28
33
|
const TASK_ID_RE = /^T\d+$/;
|
|
29
34
|
const NAME_LISTS = ["creates", "removes", "produces", "consumes"];
|
|
35
|
+
const REVIEW_FOCUS_MAX = 5;
|
|
36
|
+
const SPEC_RATIO = 4;
|
|
37
|
+
const SPEC_MIN_CHARS = 400;
|
|
38
|
+
|
|
39
|
+
const FIGMA_LINK = /\bfigma\.com\/(?:design|file|proto)\//i;
|
|
40
|
+
const DESIGN_VALUE = /\b\d+(?:\.\d+)?\s?(?:px|pt)\b/i;
|
|
41
|
+
const INVENTORY_KEYWORDS = ["Bileşen Envanteri", "Component Inventory"];
|
|
42
|
+
const UI_FILE = /(?:View|Screen|Scene|Content|Cell|Sheet)\.(?:swift|kt)$|\.figma\.(?:swift|kt)$/;
|
|
43
|
+
const MAPPINGS = new Set(["code-connect", "new", "best-fit"]);
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The analysis Section 6 rows: the component name (first cell) and whether it
|
|
47
|
+
* exists already (second cell, yes / no; anything else is unknown).
|
|
48
|
+
*/
|
|
49
|
+
function inventoryComponents(specText) {
|
|
50
|
+
const body = sectionBody(String(specText).split("\n"), INVENTORY_KEYWORDS, 2);
|
|
51
|
+
if (!body) return [];
|
|
52
|
+
return tableDataRows(body)
|
|
53
|
+
.map((row) => {
|
|
54
|
+
const cells = row.split("|").map((c) => c.replace(/[`*]/g, "").trim());
|
|
55
|
+
const existing = (cells[2] || "").toLowerCase();
|
|
56
|
+
return {
|
|
57
|
+
name: cells[1] ?? "",
|
|
58
|
+
existing: /^(yes|evet)\b/.test(existing)
|
|
59
|
+
? true
|
|
60
|
+
: /^(no|hayır|hayir)\b/.test(existing)
|
|
61
|
+
? false
|
|
62
|
+
: null,
|
|
63
|
+
};
|
|
64
|
+
})
|
|
65
|
+
.filter((r) => r.name && !/^<.*>$/.test(r.name));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Errors and warnings for the plan's UI tasks against Section 6: a task that
|
|
70
|
+
* touches a view file names its component, and the name is a Section 6 row.
|
|
71
|
+
*/
|
|
72
|
+
function designCitations(tasks, components) {
|
|
73
|
+
const errors = [];
|
|
74
|
+
const warnings = [];
|
|
75
|
+
if (!components.length || !Array.isArray(tasks)) return { errors, warnings };
|
|
76
|
+
const known = new Map(components.map((c) => [c.name, c.existing]));
|
|
77
|
+
for (const t of tasks) {
|
|
78
|
+
if (!t || typeof t !== "object") continue;
|
|
79
|
+
const d = t.design;
|
|
80
|
+
if (d !== undefined) {
|
|
81
|
+
if (!d || typeof d.component !== "string" || !MAPPINGS.has(d.mapping)) {
|
|
82
|
+
errors.push(`tasks ${t.id}.design: needs {component, mapping: code-connect|new|best-fit}`);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const name = d.component.trim();
|
|
86
|
+
if (!known.has(name)) {
|
|
87
|
+
errors.push(
|
|
88
|
+
`tasks ${t.id}.design.component: "${d.component}" is not a Section 6 row; use the inventory's name verbatim, never a sound-alike`,
|
|
89
|
+
);
|
|
90
|
+
} else if (d.mapping === "new" && known.get(name) === true) {
|
|
91
|
+
errors.push(
|
|
92
|
+
`tasks ${t.id}.design: "${name}" exists already per Section 6; reuse it, do not build it new`,
|
|
93
|
+
);
|
|
94
|
+
} else if (d.mapping === "code-connect" && known.get(name) === false) {
|
|
95
|
+
errors.push(
|
|
96
|
+
`tasks ${t.id}.design: "${name}" does not exist yet per Section 6, so it has no Code Connect mapping`,
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
if (d.mapping === "best-fit") {
|
|
100
|
+
warnings.push(
|
|
101
|
+
`tasks ${t.id}: best-fit component needs a Risk row; Phase 3 gates it review_blocking`,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const ui = (Array.isArray(t.files) ? t.files : []).some(
|
|
107
|
+
(f) => typeof f === "string" && UI_FILE.test(f),
|
|
108
|
+
);
|
|
109
|
+
if (ui && (t.type === "code" || t.type === "refactor")) {
|
|
110
|
+
errors.push(
|
|
111
|
+
`tasks ${t.id}: touches a UI file but cites no Section 6 component (design.component)`,
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return { errors, warnings };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function specPath() {
|
|
119
|
+
const i = process.argv.indexOf("--spec");
|
|
120
|
+
return i > 0 ? process.argv[i + 1] : null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** The plan path: the first argument that is neither a flag nor a flag's value. */
|
|
124
|
+
function inputArg() {
|
|
125
|
+
const args = process.argv.slice(2);
|
|
126
|
+
for (let i = 0; i < args.length; i++) {
|
|
127
|
+
if (args[i] === "--spec") i++;
|
|
128
|
+
else if (!args[i].startsWith("--")) return args[i];
|
|
129
|
+
}
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
30
132
|
|
|
31
133
|
function readInput() {
|
|
32
|
-
const arg =
|
|
134
|
+
const arg = inputArg();
|
|
33
135
|
if (!arg) {
|
|
34
|
-
console.error("usage: validate-planning.mjs <path|->");
|
|
136
|
+
console.error("usage: validate-planning.mjs <path|-> [--spec <path>]");
|
|
35
137
|
process.exit(64);
|
|
36
138
|
}
|
|
37
139
|
if (arg === "-") {
|
|
@@ -173,6 +275,33 @@ async function main() {
|
|
|
173
275
|
}
|
|
174
276
|
}
|
|
175
277
|
|
|
278
|
+
if (parsed.reviewFocus !== undefined) {
|
|
279
|
+
if (!Array.isArray(parsed.reviewFocus)) {
|
|
280
|
+
errors.push("reviewFocus: must be array if present");
|
|
281
|
+
} else {
|
|
282
|
+
if (parsed.reviewFocus.length > REVIEW_FOCUS_MAX) {
|
|
283
|
+
errors.push(`reviewFocus: at most ${REVIEW_FOCUS_MAX} entries`);
|
|
284
|
+
}
|
|
285
|
+
parsed.reviewFocus.forEach((r, i) => {
|
|
286
|
+
if (typeof r?.input !== "string" || r.input.trim().length < 4) {
|
|
287
|
+
errors.push(`reviewFocus[${i}].input: must name the input`);
|
|
288
|
+
}
|
|
289
|
+
if (!ids.has(r?.ownerTaskId)) {
|
|
290
|
+
errors.push(`reviewFocus[${i}].ownerTaskId: unknown task "${r?.ownerTaskId}"`);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (
|
|
296
|
+
parsed.globalConstraints !== undefined &&
|
|
297
|
+
!(
|
|
298
|
+
Array.isArray(parsed.globalConstraints) &&
|
|
299
|
+
parsed.globalConstraints.every((c) => typeof c === "string" && c.length > 0)
|
|
300
|
+
)
|
|
301
|
+
) {
|
|
302
|
+
errors.push("globalConstraints: must be an array of non-empty strings if present");
|
|
303
|
+
}
|
|
304
|
+
|
|
176
305
|
// approved=false requires userFeedback
|
|
177
306
|
if (errors.length === 0 && parsed.approved === false) {
|
|
178
307
|
if (typeof parsed.userFeedback !== "string" || parsed.userFeedback.length === 0) {
|
|
@@ -189,6 +318,45 @@ async function main() {
|
|
|
189
318
|
errors.push(...found.contradictions);
|
|
190
319
|
}
|
|
191
320
|
|
|
321
|
+
const spec = specPath();
|
|
322
|
+
if (spec) {
|
|
323
|
+
let specChars = 0;
|
|
324
|
+
let specText = "";
|
|
325
|
+
try {
|
|
326
|
+
specText = readFileSync(spec, "utf-8");
|
|
327
|
+
specChars = specText.length;
|
|
328
|
+
} catch {
|
|
329
|
+
warnings.push(`spec not readable: ${spec}`);
|
|
330
|
+
}
|
|
331
|
+
// With a design behind the plan, values come from its tokens, never from a
|
|
332
|
+
// number someone read off a screenshot.
|
|
333
|
+
if (FIGMA_LINK.test(specText) && Array.isArray(parsed.tasks)) {
|
|
334
|
+
for (const t of parsed.tasks) {
|
|
335
|
+
const text = [
|
|
336
|
+
t?.title,
|
|
337
|
+
t?.description,
|
|
338
|
+
...(Array.isArray(t?.acceptanceCriteria) ? t.acceptanceCriteria : []),
|
|
339
|
+
]
|
|
340
|
+
.filter((v) => typeof v === "string")
|
|
341
|
+
.join("\n");
|
|
342
|
+
const m = text.match(DESIGN_VALUE);
|
|
343
|
+
if (m) {
|
|
344
|
+
errors.push(
|
|
345
|
+
`tasks ${t.id}: "${m[0]}" is a raw design value; name the design token (Spacing.*, Radius.*, a type style) the analysis mapped instead`,
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
const cited = designCitations(parsed.tasks, inventoryComponents(specText));
|
|
351
|
+
errors.push(...cited.errors);
|
|
352
|
+
warnings.push(...cited.warnings);
|
|
353
|
+
if (specChars >= SPEC_MIN_CHARS && raw.length > specChars * SPEC_RATIO) {
|
|
354
|
+
warnings.push(
|
|
355
|
+
`plan is ${Math.round(raw.length / specChars)}x the length of its spec; record decisions, not a transcript`,
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
192
360
|
if (errors.length > 0) {
|
|
193
361
|
emit({ ok: false, code: 1, errors, warnings, overlaps });
|
|
194
362
|
process.exitCode = 1;
|
|
@@ -264,6 +264,26 @@ async function main() {
|
|
|
264
264
|
errors.push("approved must be boolean");
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
+
// Requirements the diff cannot show: they live in code the change did not touch.
|
|
268
|
+
if (parsed.cannotVerify !== undefined) {
|
|
269
|
+
if (!Array.isArray(parsed.cannotVerify)) {
|
|
270
|
+
errors.push("cannotVerify must be an array when present");
|
|
271
|
+
} else {
|
|
272
|
+
parsed.cannotVerify.forEach((row, i) => {
|
|
273
|
+
const label = `cannotVerify[${i}]`;
|
|
274
|
+
if (typeof row?.requirement !== "string" || row.requirement.trim().length < 4) {
|
|
275
|
+
errors.push(`${label}: requirement must name what could not be verified`);
|
|
276
|
+
}
|
|
277
|
+
if (typeof row?.where !== "string" || !row.where.trim()) {
|
|
278
|
+
errors.push(`${label}: where must name the unchanged file or symbol`);
|
|
279
|
+
}
|
|
280
|
+
if (typeof row?.why !== "string" || row.why.trim().length < 4) {
|
|
281
|
+
errors.push(`${label}: why must say what the diff does not show`);
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
267
287
|
// Conformance checklist, only when the orchestrator supplied criteria.
|
|
268
288
|
const critIdx = process.argv.indexOf("--criteria");
|
|
269
289
|
if (critIdx !== -1) {
|