oh-my-super-agent 0.1.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/.agents/agents/advisor.md +15 -0
- package/.agents/agents/conductor.md +32 -0
- package/.agents/agents/dreamer.md +13 -0
- package/.agents/agents/executor.md +17 -0
- package/.agents/agents/grader.md +15 -0
- package/.agents/config/endurance-policy.json +8 -0
- package/.agents/config/oms-config.json +119 -0
- package/.agents/config/release-policy.json +12 -0
- package/.agents/config/secret-scan-policy.json +7 -0
- package/.agents/config/verification-plan.json +33 -0
- package/.agents/registry.json +11 -0
- package/.agents/rules/constitution.md +7 -0
- package/.agents/skills/conductor/SKILL.md +23 -0
- package/.agents/skills/dream/SKILL.md +14 -0
- package/.agents/skills/executor/SKILL.md +13 -0
- package/.agents/skills/oms/SKILL.md +52 -0
- package/.agents/skills/quota-aware/SKILL.md +12 -0
- package/.agents/skills/schedule/SKILL.md +13 -0
- package/.agents/skills/team-protocol/SKILL.md +20 -0
- package/LICENSE +21 -0
- package/README.md +146 -0
- package/dist/src/audit/run-ledger.d.ts +183 -0
- package/dist/src/audit/run-ledger.js +1655 -0
- package/dist/src/audit/run-ledger.js.map +1 -0
- package/dist/src/cli.d.ts +61 -0
- package/dist/src/cli.js +2096 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/commands/github-queue-probe.d.ts +26 -0
- package/dist/src/commands/github-queue-probe.js +51 -0
- package/dist/src/commands/github-queue-probe.js.map +1 -0
- package/dist/src/commands/trace-fixture.d.ts +20 -0
- package/dist/src/commands/trace-fixture.js +72 -0
- package/dist/src/commands/trace-fixture.js.map +1 -0
- package/dist/src/conductor/activity.d.ts +46 -0
- package/dist/src/conductor/activity.js +224 -0
- package/dist/src/conductor/activity.js.map +1 -0
- package/dist/src/conductor/bridge.d.ts +53 -0
- package/dist/src/conductor/bridge.js +652 -0
- package/dist/src/conductor/bridge.js.map +1 -0
- package/dist/src/conductor/notifications.d.ts +59 -0
- package/dist/src/conductor/notifications.js +381 -0
- package/dist/src/conductor/notifications.js.map +1 -0
- package/dist/src/conductor/recovery.d.ts +29 -0
- package/dist/src/conductor/recovery.js +198 -0
- package/dist/src/conductor/recovery.js.map +1 -0
- package/dist/src/conductor/start.d.ts +73 -0
- package/dist/src/conductor/start.js +519 -0
- package/dist/src/conductor/start.js.map +1 -0
- package/dist/src/conductor/waiter.d.ts +88 -0
- package/dist/src/conductor/waiter.js +427 -0
- package/dist/src/conductor/waiter.js.map +1 -0
- package/dist/src/config.d.ts +9 -0
- package/dist/src/config.js +40 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/dispatch/advice-source.d.ts +61 -0
- package/dist/src/dispatch/advice-source.js +198 -0
- package/dist/src/dispatch/advice-source.js.map +1 -0
- package/dist/src/dispatch/advice-store.d.ts +41 -0
- package/dist/src/dispatch/advice-store.js +201 -0
- package/dist/src/dispatch/advice-store.js.map +1 -0
- package/dist/src/dispatch/advice.d.ts +34 -0
- package/dist/src/dispatch/advice.js +371 -0
- package/dist/src/dispatch/advice.js.map +1 -0
- package/dist/src/dispatch/authority.d.ts +124 -0
- package/dist/src/dispatch/authority.js +1202 -0
- package/dist/src/dispatch/authority.js.map +1 -0
- package/dist/src/dispatch/intent.d.ts +66 -0
- package/dist/src/dispatch/intent.js +71 -0
- package/dist/src/dispatch/intent.js.map +1 -0
- package/dist/src/dispatch/runtime-authority.d.ts +42 -0
- package/dist/src/dispatch/runtime-authority.js +52 -0
- package/dist/src/dispatch/runtime-authority.js.map +1 -0
- package/dist/src/doctor.d.ts +20 -0
- package/dist/src/doctor.js +85 -0
- package/dist/src/doctor.js.map +1 -0
- package/dist/src/domain/records.d.ts +44 -0
- package/dist/src/domain/records.js +138 -0
- package/dist/src/domain/records.js.map +1 -0
- package/dist/src/domain/role-policy.d.ts +67 -0
- package/dist/src/domain/role-policy.js +547 -0
- package/dist/src/domain/role-policy.js.map +1 -0
- package/dist/src/events/bus.d.ts +32 -0
- package/dist/src/events/bus.js +115 -0
- package/dist/src/events/bus.js.map +1 -0
- package/dist/src/events/kinds.d.ts +126 -0
- package/dist/src/events/kinds.js +14 -0
- package/dist/src/events/kinds.js.map +1 -0
- package/dist/src/evidence/immutable-file.d.ts +12 -0
- package/dist/src/evidence/immutable-file.js +141 -0
- package/dist/src/evidence/immutable-file.js.map +1 -0
- package/dist/src/evidence/store.d.ts +125 -0
- package/dist/src/evidence/store.js +1189 -0
- package/dist/src/evidence/store.js.map +1 -0
- package/dist/src/evidence/verdict.d.ts +17 -0
- package/dist/src/evidence/verdict.js +23 -0
- package/dist/src/evidence/verdict.js.map +1 -0
- package/dist/src/generation/agent.d.ts +5 -0
- package/dist/src/generation/agent.js +34 -0
- package/dist/src/generation/agent.js.map +1 -0
- package/dist/src/generation/frontmatter.d.ts +7 -0
- package/dist/src/generation/frontmatter.js +33 -0
- package/dist/src/generation/frontmatter.js.map +1 -0
- package/dist/src/github/adapter.d.ts +44 -0
- package/dist/src/github/adapter.js +592 -0
- package/dist/src/github/adapter.js.map +1 -0
- package/dist/src/github/dispatch-eligibility.d.ts +9 -0
- package/dist/src/github/dispatch-eligibility.js +94 -0
- package/dist/src/github/dispatch-eligibility.js.map +1 -0
- package/dist/src/github/projector.d.ts +23 -0
- package/dist/src/github/projector.js +181 -0
- package/dist/src/github/projector.js.map +1 -0
- package/dist/src/github/review.d.ts +39 -0
- package/dist/src/github/review.js +1450 -0
- package/dist/src/github/review.js.map +1 -0
- package/dist/src/github/sync.d.ts +21 -0
- package/dist/src/github/sync.js +518 -0
- package/dist/src/github/sync.js.map +1 -0
- package/dist/src/github/types.d.ts +134 -0
- package/dist/src/github/types.js +11 -0
- package/dist/src/github/types.js.map +1 -0
- package/dist/src/goals/artifact-store.d.ts +31 -0
- package/dist/src/goals/artifact-store.js +241 -0
- package/dist/src/goals/artifact-store.js.map +1 -0
- package/dist/src/goals/authority.d.ts +112 -0
- package/dist/src/goals/authority.js +621 -0
- package/dist/src/goals/authority.js.map +1 -0
- package/dist/src/goals/native-snapshot.d.ts +12 -0
- package/dist/src/goals/native-snapshot.js +53 -0
- package/dist/src/goals/native-snapshot.js.map +1 -0
- package/dist/src/goals/runtime-authority.d.ts +7 -0
- package/dist/src/goals/runtime-authority.js +20 -0
- package/dist/src/goals/runtime-authority.js.map +1 -0
- package/dist/src/health/release-assessment.d.ts +11 -0
- package/dist/src/health/release-assessment.js +83 -0
- package/dist/src/health/release-assessment.js.map +1 -0
- package/dist/src/health/release-policy.d.ts +16 -0
- package/dist/src/health/release-policy.js +40 -0
- package/dist/src/health/release-policy.js.map +1 -0
- package/dist/src/hooks/native.d.ts +30 -0
- package/dist/src/hooks/native.js +495 -0
- package/dist/src/hooks/native.js.map +1 -0
- package/dist/src/hooks/provider-runtime.d.ts +55 -0
- package/dist/src/hooks/provider-runtime.js +479 -0
- package/dist/src/hooks/provider-runtime.js.map +1 -0
- package/dist/src/hooks/provider.d.ts +102 -0
- package/dist/src/hooks/provider.js +358 -0
- package/dist/src/hooks/provider.js.map +1 -0
- package/dist/src/live/contact-journal.d.ts +73 -0
- package/dist/src/live/contact-journal.js +439 -0
- package/dist/src/live/contact-journal.js.map +1 -0
- package/dist/src/live-probes/gh-adapter.d.ts +28 -0
- package/dist/src/live-probes/gh-adapter.js +188 -0
- package/dist/src/live-probes/gh-adapter.js.map +1 -0
- package/dist/src/live-probes/github-queue.d.ts +1 -0
- package/dist/src/live-probes/github-queue.js +2 -0
- package/dist/src/live-probes/github-queue.js.map +1 -0
- package/dist/src/notifications/slack-request.d.ts +13 -0
- package/dist/src/notifications/slack-request.js +40 -0
- package/dist/src/notifications/slack-request.js.map +1 -0
- package/dist/src/outbox/processor.d.ts +27 -0
- package/dist/src/outbox/processor.js +63 -0
- package/dist/src/outbox/processor.js.map +1 -0
- package/dist/src/outbox/store.d.ts +158 -0
- package/dist/src/outbox/store.js +834 -0
- package/dist/src/outbox/store.js.map +1 -0
- package/dist/src/package-root.d.ts +1 -0
- package/dist/src/package-root.js +26 -0
- package/dist/src/package-root.js.map +1 -0
- package/dist/src/project.d.ts +12 -0
- package/dist/src/project.js +60 -0
- package/dist/src/project.js.map +1 -0
- package/dist/src/projection/generated-file.d.ts +15 -0
- package/dist/src/projection/generated-file.js +72 -0
- package/dist/src/projection/generated-file.js.map +1 -0
- package/dist/src/projection/project-workspace.d.ts +11 -0
- package/dist/src/projection/project-workspace.js +94 -0
- package/dist/src/projection/project-workspace.js.map +1 -0
- package/dist/src/projection/registry.d.ts +15 -0
- package/dist/src/projection/registry.js +59 -0
- package/dist/src/projection/registry.js.map +1 -0
- package/dist/src/projection/safe-path.d.ts +4 -0
- package/dist/src/projection/safe-path.js +106 -0
- package/dist/src/projection/safe-path.js.map +1 -0
- package/dist/src/providers/claude-interactive.d.ts +38 -0
- package/dist/src/providers/claude-interactive.js +287 -0
- package/dist/src/providers/claude-interactive.js.map +1 -0
- package/dist/src/providers/claude-structured-bridge.d.ts +32 -0
- package/dist/src/providers/claude-structured-bridge.js +215 -0
- package/dist/src/providers/claude-structured-bridge.js.map +1 -0
- package/dist/src/providers/claude-structured-completion.d.ts +23 -0
- package/dist/src/providers/claude-structured-completion.js +229 -0
- package/dist/src/providers/claude-structured-completion.js.map +1 -0
- package/dist/src/providers/claude-structured-pane.d.ts +23 -0
- package/dist/src/providers/claude-structured-pane.js +156 -0
- package/dist/src/providers/claude-structured-pane.js.map +1 -0
- package/dist/src/providers/claude-structured-store.d.ts +48 -0
- package/dist/src/providers/claude-structured-store.js +212 -0
- package/dist/src/providers/claude-structured-store.js.map +1 -0
- package/dist/src/providers/claude-structured.d.ts +56 -0
- package/dist/src/providers/claude-structured.js +250 -0
- package/dist/src/providers/claude-structured.js.map +1 -0
- package/dist/src/providers/codex-exec.d.ts +29 -0
- package/dist/src/providers/codex-exec.js +127 -0
- package/dist/src/providers/codex-exec.js.map +1 -0
- package/dist/src/providers/grading.d.ts +2 -0
- package/dist/src/providers/grading.js +20 -0
- package/dist/src/providers/grading.js.map +1 -0
- package/dist/src/providers/native-dispatch.d.ts +24 -0
- package/dist/src/providers/native-dispatch.js +34 -0
- package/dist/src/providers/native-dispatch.js.map +1 -0
- package/dist/src/providers/preflight.d.ts +65 -0
- package/dist/src/providers/preflight.js +256 -0
- package/dist/src/providers/preflight.js.map +1 -0
- package/dist/src/providers/process.d.ts +18 -0
- package/dist/src/providers/process.js +21 -0
- package/dist/src/providers/process.js.map +1 -0
- package/dist/src/queue/model.d.ts +37 -0
- package/dist/src/queue/model.js +51 -0
- package/dist/src/queue/model.js.map +1 -0
- package/dist/src/queue/service.d.ts +1 -0
- package/dist/src/queue/service.js +2 -0
- package/dist/src/queue/service.js.map +1 -0
- package/dist/src/reflections/store.d.ts +21 -0
- package/dist/src/reflections/store.js +60 -0
- package/dist/src/reflections/store.js.map +1 -0
- package/dist/src/reports/daily-trust.d.ts +11 -0
- package/dist/src/reports/daily-trust.js +98 -0
- package/dist/src/reports/daily-trust.js.map +1 -0
- package/dist/src/runs/controller.d.ts +187 -0
- package/dist/src/runs/controller.js +1182 -0
- package/dist/src/runs/controller.js.map +1 -0
- package/dist/src/runtime/composition.d.ts +9 -0
- package/dist/src/runtime/composition.js +35 -0
- package/dist/src/runtime/composition.js.map +1 -0
- package/dist/src/runtime/endurance-authorities.d.ts +44 -0
- package/dist/src/runtime/endurance-authorities.js +101 -0
- package/dist/src/runtime/endurance-authorities.js.map +1 -0
- package/dist/src/runtime/endurance-policy.d.ts +12 -0
- package/dist/src/runtime/endurance-policy.js +13 -0
- package/dist/src/runtime/endurance-policy.js.map +1 -0
- package/dist/src/runtime/lock.d.ts +63 -0
- package/dist/src/runtime/lock.js +577 -0
- package/dist/src/runtime/lock.js.map +1 -0
- package/dist/src/runtime/process-identity.d.ts +10 -0
- package/dist/src/runtime/process-identity.js +43 -0
- package/dist/src/runtime/process-identity.js.map +1 -0
- package/dist/src/runtime/quota.d.ts +130 -0
- package/dist/src/runtime/quota.js +590 -0
- package/dist/src/runtime/quota.js.map +1 -0
- package/dist/src/runtime/record-store.d.ts +45 -0
- package/dist/src/runtime/record-store.js +272 -0
- package/dist/src/runtime/record-store.js.map +1 -0
- package/dist/src/runtime/schema.d.ts +28 -0
- package/dist/src/runtime/schema.js +194 -0
- package/dist/src/runtime/schema.js.map +1 -0
- package/dist/src/runtime/stable-id.d.ts +3 -0
- package/dist/src/runtime/stable-id.js +27 -0
- package/dist/src/runtime/stable-id.js.map +1 -0
- package/dist/src/runtime/system-clock.d.ts +8 -0
- package/dist/src/runtime/system-clock.js +35 -0
- package/dist/src/runtime/system-clock.js.map +1 -0
- package/dist/src/schedule/service-plan.d.ts +58 -0
- package/dist/src/schedule/service-plan.js +327 -0
- package/dist/src/schedule/service-plan.js.map +1 -0
- package/dist/src/schedule/user-installation.d.ts +62 -0
- package/dist/src/schedule/user-installation.js +701 -0
- package/dist/src/schedule/user-installation.js.map +1 -0
- package/dist/src/schedule/user-plan.d.ts +47 -0
- package/dist/src/schedule/user-plan.js +286 -0
- package/dist/src/schedule/user-plan.js.map +1 -0
- package/dist/src/scheduler/minute.d.ts +31 -0
- package/dist/src/scheduler/minute.js +441 -0
- package/dist/src/scheduler/minute.js.map +1 -0
- package/dist/src/schemas/registry.d.ts +10 -0
- package/dist/src/schemas/registry.js +36 -0
- package/dist/src/schemas/registry.js.map +1 -0
- package/dist/src/security/secret-scan.d.ts +50 -0
- package/dist/src/security/secret-scan.js +384 -0
- package/dist/src/security/secret-scan.js.map +1 -0
- package/dist/src/sessions/registry.d.ts +89 -0
- package/dist/src/sessions/registry.js +443 -0
- package/dist/src/sessions/registry.js.map +1 -0
- package/dist/src/state.d.ts +27 -0
- package/dist/src/state.js +235 -0
- package/dist/src/state.js.map +1 -0
- package/dist/src/status/hud.d.ts +37 -0
- package/dist/src/status/hud.js +88 -0
- package/dist/src/status/hud.js.map +1 -0
- package/dist/src/team/plan.d.ts +31 -0
- package/dist/src/team/plan.js +184 -0
- package/dist/src/team/plan.js.map +1 -0
- package/dist/src/team/projection.d.ts +24 -0
- package/dist/src/team/projection.js +79 -0
- package/dist/src/team/projection.js.map +1 -0
- package/dist/src/tickets/admission.d.ts +34 -0
- package/dist/src/tickets/admission.js +169 -0
- package/dist/src/tickets/admission.js.map +1 -0
- package/dist/src/tickets/materializer.d.ts +1 -0
- package/dist/src/tickets/materializer.js +2 -0
- package/dist/src/tickets/materializer.js.map +1 -0
- package/dist/src/tickets/runtime-authority.d.ts +32 -0
- package/dist/src/tickets/runtime-authority.js +46 -0
- package/dist/src/tickets/runtime-authority.js.map +1 -0
- package/dist/src/tickets/store.d.ts +221 -0
- package/dist/src/tickets/store.js +2025 -0
- package/dist/src/tickets/store.js.map +1 -0
- package/dist/src/tracer/one-ticket.d.ts +58 -0
- package/dist/src/tracer/one-ticket.js +578 -0
- package/dist/src/tracer/one-ticket.js.map +1 -0
- package/dist/src/trust/assessment.d.ts +24 -0
- package/dist/src/trust/assessment.js +124 -0
- package/dist/src/trust/assessment.js.map +1 -0
- package/dist/src/trust/runs.d.ts +13 -0
- package/dist/src/trust/runs.js +46 -0
- package/dist/src/trust/runs.js.map +1 -0
- package/dist/src/types.d.ts +6 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/utils/fs.d.ts +13 -0
- package/dist/src/utils/fs.js +188 -0
- package/dist/src/utils/fs.js.map +1 -0
- package/dist/src/verification/authority.d.ts +28 -0
- package/dist/src/verification/authority.js +153 -0
- package/dist/src/verification/authority.js.map +1 -0
- package/dist/src/verification/grade-source.d.ts +17 -0
- package/dist/src/verification/grade-source.js +30 -0
- package/dist/src/verification/grade-source.js.map +1 -0
- package/dist/src/verification/plan.d.ts +20 -0
- package/dist/src/verification/plan.js +128 -0
- package/dist/src/verification/plan.js.map +1 -0
- package/dist/src/verification/protected-runner.d.ts +50 -0
- package/dist/src/verification/protected-runner.js +171 -0
- package/dist/src/verification/protected-runner.js.map +1 -0
- package/dist/src/verification/result-gate-store.d.ts +72 -0
- package/dist/src/verification/result-gate-store.js +193 -0
- package/dist/src/verification/result-gate-store.js.map +1 -0
- package/dist/src/verification/result-gate.d.ts +41 -0
- package/dist/src/verification/result-gate.js +731 -0
- package/dist/src/verification/result-gate.js.map +1 -0
- package/dist/src/verification/runner.d.ts +38 -0
- package/dist/src/verification/runner.js +143 -0
- package/dist/src/verification/runner.js.map +1 -0
- package/dist/src/verification/sandbox.d.ts +16 -0
- package/dist/src/verification/sandbox.js +199 -0
- package/dist/src/verification/sandbox.js.map +1 -0
- package/dist/src/verify.d.ts +8 -0
- package/dist/src/verify.js +35 -0
- package/dist/src/verify.js.map +1 -0
- package/dist/src/watchdog/reconcile.d.ts +42 -0
- package/dist/src/watchdog/reconcile.js +440 -0
- package/dist/src/watchdog/reconcile.js.map +1 -0
- package/dist/src/workers/bridge.d.ts +35 -0
- package/dist/src/workers/bridge.js +426 -0
- package/dist/src/workers/bridge.js.map +1 -0
- package/dist/src/workers/delivery.d.ts +31 -0
- package/dist/src/workers/delivery.js +876 -0
- package/dist/src/workers/delivery.js.map +1 -0
- package/dist/src/workers/panes.d.ts +32 -0
- package/dist/src/workers/panes.js +212 -0
- package/dist/src/workers/panes.js.map +1 -0
- package/dist/src/workers/registry.d.ts +80 -0
- package/dist/src/workers/registry.js +351 -0
- package/dist/src/workers/registry.js.map +1 -0
- package/dist/src/workers/runtime.d.ts +44 -0
- package/dist/src/workers/runtime.js +21 -0
- package/dist/src/workers/runtime.js.map +1 -0
- package/dist/src/worktrees/manager.d.ts +35 -0
- package/dist/src/worktrees/manager.js +315 -0
- package/dist/src/worktrees/manager.js.map +1 -0
- package/docs/ARCHITECTURE.md +323 -0
- package/docs/PLAN.md +216 -0
- package/docs/REFERENCES.md +42 -0
- package/docs/ROADMAP.md +327 -0
- package/docs/SECURITY.md +242 -0
- package/docs/adr/0001-tracer-first-file-backed-certification.md +41 -0
- package/docs/adr/0002-conductor-first-typed-dispatch.md +102 -0
- package/docs/adr/0003-mandatory-pre-dispatch-advice.md +59 -0
- package/docs/compatibility/claude-code-2.1.207.md +25 -0
- package/loop/contract.md +102 -0
- package/package.json +54 -0
- package/schemas/advisor-evidence.schema.json +54 -0
- package/schemas/advisor-output.schema.json +31 -0
- package/schemas/conductor-activity-payload.schema.json +38 -0
- package/schemas/conductor-decision.schema.json +29 -0
- package/schemas/conductor-dispatch-intent.schema.json +71 -0
- package/schemas/conductor-dispatch-preparation.schema.json +46 -0
- package/schemas/conductor-dispatch-proposal.schema.json +82 -0
- package/schemas/conductor-goal-proposal.schema.json +30 -0
- package/schemas/conductor-manage-worker.schema.json +17 -0
- package/schemas/conductor-notification-payload.schema.json +39 -0
- package/schemas/conductor-process-result.schema.json +14 -0
- package/schemas/conductor-route.schema.json +51 -0
- package/schemas/conductor-start-team.schema.json +16 -0
- package/schemas/conductor-waiter-payload.schema.json +68 -0
- package/schemas/deterministic-check.schema.json +107 -0
- package/schemas/dispatch-acknowledgement.schema.json +15 -0
- package/schemas/dispatch-advice-payload.schema.json +64 -0
- package/schemas/dispatch-payload.schema.json +131 -0
- package/schemas/dispatch-result.schema.json +28 -0
- package/schemas/endurance-policy.schema.json +16 -0
- package/schemas/events/dispatch-delivery-requested.schema.json +17 -0
- package/schemas/events/github-observed.schema.json +28 -0
- package/schemas/events/native-hook-observed.schema.json +35 -0
- package/schemas/events/provider-observed.schema.json +64 -0
- package/schemas/events/run-heartbeat-due.schema.json +10 -0
- package/schemas/events/slack-notification-requested.schema.json +14 -0
- package/schemas/events/structured-role-completed.schema.json +54 -0
- package/schemas/events/ticket-resume-due.schema.json +28 -0
- package/schemas/events/watchdog-lease-expired.schema.json +14 -0
- package/schemas/events/watchdog-outbox-stalled.schema.json +12 -0
- package/schemas/events/watchdog-session-stalled.schema.json +11 -0
- package/schemas/evidence-record.schema.json +37 -0
- package/schemas/executor-result.schema.json +17 -0
- package/schemas/github-observation.schema.json +33 -0
- package/schemas/github-watermark.schema.json +66 -0
- package/schemas/goal-artifact.schema.json +19 -0
- package/schemas/goal-create-input.schema.json +14 -0
- package/schemas/goal-executor-result.schema.json +18 -0
- package/schemas/goal-payload.schema.json +95 -0
- package/schemas/grader-output.schema.json +33 -0
- package/schemas/lease-expiry.schema.json +19 -0
- package/schemas/live-disclosure.schema.json +16 -0
- package/schemas/live-outcome.schema.json +52 -0
- package/schemas/native-goal-snapshot.schema.json +27 -0
- package/schemas/provider-observed.schema.json +64 -0
- package/schemas/quota-observation.schema.json +72 -0
- package/schemas/reflection-evidence.schema.json +61 -0
- package/schemas/reflection.schema.json +13 -0
- package/schemas/regression-request.schema.json +54 -0
- package/schemas/release-assessment.schema.json +34 -0
- package/schemas/release-policy.schema.json +30 -0
- package/schemas/result-gate-payload.schema.json +244 -0
- package/schemas/review-delivery-payload.schema.json +42 -0
- package/schemas/role-policy.schema.json +111 -0
- package/schemas/run-abort-input.schema.json +11 -0
- package/schemas/run-completion-proof.schema.json +62 -0
- package/schemas/run-ledger-entry.schema.json +78 -0
- package/schemas/run-manifest.schema.json +74 -0
- package/schemas/run-start-intent.schema.json +74 -0
- package/schemas/runtime-record.schema.json +111 -0
- package/schemas/service-plan.schema.json +35 -0
- package/schemas/session-payload.schema.json +80 -0
- package/schemas/structured-role-read-request.schema.json +14 -0
- package/schemas/structured-role-request.schema.json +44 -0
- package/schemas/structured-role-result.schema.json +38 -0
- package/schemas/structured-role-submit-result.schema.json +15 -0
- package/schemas/team-checkpoint.schema.json +42 -0
- package/schemas/team-plan.schema.json +30 -0
- package/schemas/ticket-content.schema.json +38 -0
- package/schemas/ticket-queue-payload.schema.json +191 -0
- package/schemas/trust-report.schema.json +68 -0
- package/schemas/trust-run.schema.json +47 -0
- package/schemas/ultragoal-checkpoint.schema.json +49 -0
- package/schemas/user-schedule-installation-v1.schema.json +32 -0
- package/schemas/user-schedule-installation.schema.json +38 -0
- package/schemas/user-schedule-plan.schema.json +39 -0
- package/schemas/verification-plan-evidence.schema.json +37 -0
- package/schemas/worker-acknowledge-dispatch.schema.json +12 -0
- package/schemas/worker-payload.schema.json +47 -0
- package/schemas/worker-read-dispatch.schema.json +11 -0
- package/schemas/worker-record-dispatch-result.schema.json +14 -0
|
@@ -0,0 +1,652 @@
|
|
|
1
|
+
import { once } from "node:events";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { isDeepStrictEqual } from "node:util";
|
|
6
|
+
import { readOmsConfig } from "../config.js";
|
|
7
|
+
import { assertConductorBridgeSession } from "./start.js";
|
|
8
|
+
import { captureStoredDispatchIntent } from "../dispatch/authority.js";
|
|
9
|
+
import { createRuntimeDispatchAuthorities } from "../dispatch/runtime-authority.js";
|
|
10
|
+
import { assertActorId, assertOpaqueId } from "../domain/records.js";
|
|
11
|
+
import { createGoalWithReplay, readGoal } from "../goals/authority.js";
|
|
12
|
+
import { assertCurrentGithubDispatchEligibility } from "../github/dispatch-eligibility.js";
|
|
13
|
+
import { assertShippedSubscriptionRole, resolveConfiguredRole } from "../providers/preflight.js";
|
|
14
|
+
import { acquireDirectoryLock } from "../runtime/lock.js";
|
|
15
|
+
import { assertSchema, loadJsonSchema, SchemaValidationError } from "../runtime/schema.js";
|
|
16
|
+
import { createStableId } from "../runtime/stable-id.js";
|
|
17
|
+
import { admitReadyGithubTickets } from "../tickets/admission.js";
|
|
18
|
+
import { isRecord, readJsonFileNoFollow, validateExistingDirectory, writeJsonAtomicNoReplace } from "../utils/fs.js";
|
|
19
|
+
export const CONDUCTOR_BRIDGE_TOOLS = Object.freeze([
|
|
20
|
+
"propose_goal",
|
|
21
|
+
"prepare_dispatch",
|
|
22
|
+
"advise_dispatch",
|
|
23
|
+
"propose_dispatch",
|
|
24
|
+
"manage_worker",
|
|
25
|
+
"start_team",
|
|
26
|
+
"process_result",
|
|
27
|
+
]);
|
|
28
|
+
export const MAX_CONDUCTOR_BRIDGE_FRAME_BYTES = 128 * 1024;
|
|
29
|
+
export const CONDUCTOR_BRIDGE_TOOL_SCHEMA_FILES = Object.freeze({
|
|
30
|
+
propose_goal: "conductor-goal-proposal.schema.json",
|
|
31
|
+
prepare_dispatch: "conductor-dispatch-preparation.schema.json",
|
|
32
|
+
advise_dispatch: "conductor-dispatch-intent.schema.json",
|
|
33
|
+
propose_dispatch: "conductor-dispatch-proposal.schema.json",
|
|
34
|
+
manage_worker: "conductor-manage-worker.schema.json",
|
|
35
|
+
start_team: "conductor-start-team.schema.json",
|
|
36
|
+
process_result: "conductor-process-result.schema.json",
|
|
37
|
+
});
|
|
38
|
+
export function createConductorBridge(options) {
|
|
39
|
+
const packageRoot = validateExistingDirectory(options.packageRoot, "package root");
|
|
40
|
+
const configRoot = validateExistingDirectory(options.configRoot ?? packageRoot, "configuration root");
|
|
41
|
+
const workspaceRoot = validateExistingDirectory(options.workspaceRoot, "conductor workspace root");
|
|
42
|
+
const stateRoot = validateExistingDirectory(options.stateRoot, "conductor state root");
|
|
43
|
+
const preparationsRoot = validateExistingDirectory(join(stateRoot, "dispatch-preparations"), "dispatch preparations root");
|
|
44
|
+
const locksRoot = validateExistingDirectory(join(stateRoot, "locks"), "conductor locks root");
|
|
45
|
+
assertOpaqueId(options.sessionId, "conductor session id");
|
|
46
|
+
const binding = assertConductorBridgeSession({ workspaceRoot, stateRoot, sessionId: options.sessionId });
|
|
47
|
+
const actorId = assertActorId(options.actorId, "conductor actor id");
|
|
48
|
+
if (actorId !== binding.actor_id)
|
|
49
|
+
throw new Error("conductor bridge actor does not match its launch binding");
|
|
50
|
+
const clock = options.clock ?? (() => new Date().toISOString());
|
|
51
|
+
const tools = loadToolDefinitions(packageRoot);
|
|
52
|
+
const schemas = Object.freeze({
|
|
53
|
+
propose_goal: tools[0].inputSchema,
|
|
54
|
+
prepare_dispatch: tools[1].inputSchema,
|
|
55
|
+
advise_dispatch: tools[2].inputSchema,
|
|
56
|
+
propose_dispatch: tools[3].inputSchema,
|
|
57
|
+
manage_worker: tools[4].inputSchema,
|
|
58
|
+
start_team: tools[5].inputSchema,
|
|
59
|
+
process_result: tools[6].inputSchema,
|
|
60
|
+
});
|
|
61
|
+
const runtime = createRuntimeDispatchAuthorities({
|
|
62
|
+
packageRoot,
|
|
63
|
+
configRoot,
|
|
64
|
+
workspaceRoot,
|
|
65
|
+
stateRoot,
|
|
66
|
+
actorId,
|
|
67
|
+
clock,
|
|
68
|
+
});
|
|
69
|
+
function prepareDispatch(request) {
|
|
70
|
+
const preparationId = createStableId("disp-prep", request.ticket_id, String(request.attempt), request.operation_nonce);
|
|
71
|
+
const requestPath = join(preparationsRoot, `${preparationId}.request.json`);
|
|
72
|
+
const resultPath = join(preparationsRoot, `${preparationId}.result.json`);
|
|
73
|
+
const lock = acquireDirectoryLock({
|
|
74
|
+
locksRoot,
|
|
75
|
+
lockId: createStableId("disp-prep-lock", request.ticket_id, String(request.attempt)),
|
|
76
|
+
ownerId: actorId,
|
|
77
|
+
note: preparationId,
|
|
78
|
+
});
|
|
79
|
+
try {
|
|
80
|
+
const goal = readGoal(runtime.goals.authority, request.goal_id);
|
|
81
|
+
if (goal.state !== "active"
|
|
82
|
+
|| goal.version !== request.goal_version
|
|
83
|
+
|| goal.payload.repository_scope !== workspaceRoot)
|
|
84
|
+
throw new Error("dispatch preparation goal authority is stale");
|
|
85
|
+
const before = runtime.tickets.lifecycle.read(request.ticket_id);
|
|
86
|
+
if (before.payload.source !== "github"
|
|
87
|
+
|| before.payload.content_sha256 !== request.ticket_content_sha256
|
|
88
|
+
|| (before.state !== "pending" && before.state !== "retryable" && before.state !== "leased"))
|
|
89
|
+
throw new Error("dispatch preparation ticket authority is stale");
|
|
90
|
+
const targetAttempt = before.state === "retryable" ? before.attempt + 1 : before.attempt;
|
|
91
|
+
if (targetAttempt !== request.attempt || targetAttempt > before.max_attempts) {
|
|
92
|
+
throw new Error("dispatch preparation attempt authority is stale");
|
|
93
|
+
}
|
|
94
|
+
const content = readTicketWithinGoalScope(runtime, before, goal.payload.queue_scope);
|
|
95
|
+
const resolved = resolveConfiguredRole(readOmsConfig(configRoot), request.role_id);
|
|
96
|
+
assertShippedSubscriptionRole(resolved.role);
|
|
97
|
+
if (resolved.role.sandbox !== "ticket-worktree-write"
|
|
98
|
+
|| (resolved.role.transport !== "claude_interactive" && resolved.role.transport !== "codex_goal"))
|
|
99
|
+
throw new Error("dispatch preparation role is not a writable executor");
|
|
100
|
+
const storedRequest = readPreparationRequest(requestPath, preparationId, schemas.prepare_dispatch);
|
|
101
|
+
if (storedRequest) {
|
|
102
|
+
if (!isDeepStrictEqual(storedRequest.request, request)) {
|
|
103
|
+
throw new Error("dispatch preparation nonce was reused with different authority");
|
|
104
|
+
}
|
|
105
|
+
assertPreparationRecoveryState(storedRequest, before);
|
|
106
|
+
}
|
|
107
|
+
const storedResult = readPreparationResult(resultPath, preparationId, schemas.advise_dispatch);
|
|
108
|
+
if (storedResult) {
|
|
109
|
+
if (!storedRequest)
|
|
110
|
+
throw new Error("stored dispatch preparation result has no request authority");
|
|
111
|
+
const captured = runtime.dispatch.captureIntent(storedResult.intent);
|
|
112
|
+
if (captured.dispatch_intent_sha256 !== storedResult.dispatch_intent_sha256) {
|
|
113
|
+
throw new Error("stored dispatch preparation intent digest changed");
|
|
114
|
+
}
|
|
115
|
+
assertNoConflictingDispatch(runtime, captured);
|
|
116
|
+
return Object.freeze({ status: "replayed", intent: deepFreeze(structuredClone(storedResult.intent)) });
|
|
117
|
+
}
|
|
118
|
+
assertCurrentGithubDispatchEligibility({
|
|
119
|
+
stateRoot,
|
|
120
|
+
outbox: runtime.outbox,
|
|
121
|
+
content,
|
|
122
|
+
queueScope: goal.payload.queue_scope,
|
|
123
|
+
conductorSessionId: options.sessionId,
|
|
124
|
+
});
|
|
125
|
+
if (!storedRequest) {
|
|
126
|
+
if (before.version !== request.expected_ticket_version) {
|
|
127
|
+
throw new Error("dispatch preparation selected a stale ticket version");
|
|
128
|
+
}
|
|
129
|
+
const createdAt = clock();
|
|
130
|
+
writeJsonAtomicNoReplace(requestPath, {
|
|
131
|
+
schema_version: 1,
|
|
132
|
+
preparation_id: preparationId,
|
|
133
|
+
request_sha256: preparationRequestSha256(request, before.state, isPreparedTicket(before)),
|
|
134
|
+
request: structuredClone(request),
|
|
135
|
+
selected_ticket_state: before.state,
|
|
136
|
+
selected_ticket_prepared: isPreparedTicket(before),
|
|
137
|
+
created_at: createdAt,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
const [admission] = admitReadyGithubTickets({
|
|
141
|
+
packageRoot,
|
|
142
|
+
configRoot,
|
|
143
|
+
workspaceRoot,
|
|
144
|
+
stateRoot,
|
|
145
|
+
tickets: runtime.tickets,
|
|
146
|
+
ticketIds: [before.record_id],
|
|
147
|
+
at: clock(),
|
|
148
|
+
});
|
|
149
|
+
if (!admission)
|
|
150
|
+
throw new Error("dispatch preparation did not admit exactly one ticket");
|
|
151
|
+
const ticket = runtime.tickets.lifecycle.read(admission.ticket_id);
|
|
152
|
+
if (ticket.state !== "leased"
|
|
153
|
+
|| ticket.version !== admission.ticket_version
|
|
154
|
+
|| ticket.attempt !== request.attempt
|
|
155
|
+
|| ticket.payload.content_sha256 !== request.ticket_content_sha256)
|
|
156
|
+
throw new Error("dispatch preparation lease binding changed");
|
|
157
|
+
const intent = Object.freeze({
|
|
158
|
+
goal_id: goal.record_id,
|
|
159
|
+
goal_version: goal.version,
|
|
160
|
+
ticket_id: admission.ticket_id,
|
|
161
|
+
ticket_version: admission.ticket_version,
|
|
162
|
+
lease_token: admission.lease_token,
|
|
163
|
+
attempt: admission.attempt,
|
|
164
|
+
worker_id: admission.worker_id,
|
|
165
|
+
role_id: request.role_id,
|
|
166
|
+
model_id: resolved.modelId,
|
|
167
|
+
provider_mode: resolved.role.transport,
|
|
168
|
+
worktree_id: admission.worktree_id,
|
|
169
|
+
worktree_path: admission.worktree_path,
|
|
170
|
+
capabilities: ["repository-read", "ticket-worktree-write"],
|
|
171
|
+
budget_snapshot: {
|
|
172
|
+
profile: "subscription-only",
|
|
173
|
+
remaining_attempts: ticket.max_attempts - ticket.attempt + 1,
|
|
174
|
+
policy_digest: ticket.payload.policy_digest,
|
|
175
|
+
},
|
|
176
|
+
acceptance_criteria: [...request.acceptance_criteria],
|
|
177
|
+
evidence_requirements: [...request.evidence_requirements],
|
|
178
|
+
task_body: request.task_body,
|
|
179
|
+
operation_nonce: request.operation_nonce,
|
|
180
|
+
});
|
|
181
|
+
const captured = runtime.dispatch.captureIntent(intent);
|
|
182
|
+
assertNoConflictingDispatch(runtime, captured);
|
|
183
|
+
writeJsonAtomicNoReplace(resultPath, {
|
|
184
|
+
schema_version: 1,
|
|
185
|
+
preparation_id: preparationId,
|
|
186
|
+
dispatch_intent_sha256: captured.dispatch_intent_sha256,
|
|
187
|
+
intent: structuredClone(intent),
|
|
188
|
+
prepared_at: clock(),
|
|
189
|
+
});
|
|
190
|
+
return Object.freeze({ status: storedRequest ? "replayed" : "prepared", intent });
|
|
191
|
+
}
|
|
192
|
+
finally {
|
|
193
|
+
lock.release();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function handleMessage(message) {
|
|
197
|
+
const request = parseRequest(message);
|
|
198
|
+
if (!request)
|
|
199
|
+
return invalidRequest(null);
|
|
200
|
+
if (request.method === "notifications/initialized")
|
|
201
|
+
return undefined;
|
|
202
|
+
if (request.method === "initialize") {
|
|
203
|
+
if (request.id === undefined)
|
|
204
|
+
return undefined;
|
|
205
|
+
return success(request.id, {
|
|
206
|
+
protocolVersion: "2025-06-18",
|
|
207
|
+
capabilities: { tools: { listChanged: false } },
|
|
208
|
+
serverInfo: { name: "oms-conductor-bridge", version: "0.1.0" },
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
if (request.method === "ping") {
|
|
212
|
+
if (request.id === undefined)
|
|
213
|
+
return undefined;
|
|
214
|
+
return success(request.id, {});
|
|
215
|
+
}
|
|
216
|
+
if (request.method === "tools/list") {
|
|
217
|
+
if (request.id === undefined)
|
|
218
|
+
return undefined;
|
|
219
|
+
return success(request.id, { tools: structuredClone(tools) });
|
|
220
|
+
}
|
|
221
|
+
if (request.method === "tools/call") {
|
|
222
|
+
if (request.id === undefined)
|
|
223
|
+
return undefined;
|
|
224
|
+
const call = parseToolCall(request.params);
|
|
225
|
+
if (!call)
|
|
226
|
+
return failure(request.id, -32602, "invalid tool call");
|
|
227
|
+
const schema = schemas[call.name];
|
|
228
|
+
try {
|
|
229
|
+
assertSchema(call.arguments, schema, `${call.name} input`);
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
if (error instanceof SchemaValidationError)
|
|
233
|
+
return failure(request.id, -32602, "invalid tool input");
|
|
234
|
+
return failure(request.id, -32603, "tool validation failed");
|
|
235
|
+
}
|
|
236
|
+
if (call.name === "prepare_dispatch") {
|
|
237
|
+
try {
|
|
238
|
+
return success(request.id, toolResult(prepareDispatch(call.arguments)));
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
return success(request.id, toolResult({ status: "preparation-conflict" }, true));
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (call.name === "advise_dispatch") {
|
|
245
|
+
try {
|
|
246
|
+
if (!options.adviseDispatch)
|
|
247
|
+
throw new Error("dispatch advice is unavailable");
|
|
248
|
+
const progress = options.adviseDispatch(call.arguments);
|
|
249
|
+
return success(request.id, toolResult({
|
|
250
|
+
...progress,
|
|
251
|
+
}, progress.status === "blocked"));
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
return success(request.id, toolResult({ status: "blocked", reason: "dispatch advice is unavailable" }, true));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (call.name === "propose_dispatch") {
|
|
258
|
+
try {
|
|
259
|
+
const proposed = runtime.dispatch.propose(call.arguments);
|
|
260
|
+
const deliveryEventId = proposed.record.payload.delivery_event_id;
|
|
261
|
+
let delivery;
|
|
262
|
+
if (deliveryEventId && options.deliverAcceptedDispatch) {
|
|
263
|
+
try {
|
|
264
|
+
delivery = options.deliverAcceptedDispatch(deliveryEventId);
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
delivery = { status: "delivery-blocked" };
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return success(request.id, toolResult({
|
|
271
|
+
status: proposed.status,
|
|
272
|
+
dispatch_id: proposed.record.record_id,
|
|
273
|
+
version: proposed.record.version,
|
|
274
|
+
...(delivery === undefined ? {} : { delivery }),
|
|
275
|
+
}));
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
return success(request.id, toolResult({ status: "dispatch-conflict" }, true));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (call.name === "manage_worker") {
|
|
282
|
+
const control = call.arguments;
|
|
283
|
+
if (!isValidWorkerControl(control))
|
|
284
|
+
return failure(request.id, -32602, "invalid tool input");
|
|
285
|
+
try {
|
|
286
|
+
if (!options.manageWorker)
|
|
287
|
+
throw new Error("worker control is unavailable");
|
|
288
|
+
return success(request.id, toolResult({ status: "worker-control-complete", result: options.manageWorker(control) }));
|
|
289
|
+
}
|
|
290
|
+
catch {
|
|
291
|
+
return success(request.id, toolResult({ status: "worker-control-blocked" }, true));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
if (call.name === "start_team") {
|
|
295
|
+
const dispatchIds = call.arguments.dispatch_ids;
|
|
296
|
+
if (new Set(dispatchIds).size !== dispatchIds.length)
|
|
297
|
+
return failure(request.id, -32602, "invalid tool input");
|
|
298
|
+
try {
|
|
299
|
+
if (!options.startTeam)
|
|
300
|
+
throw new Error("Team start is unavailable");
|
|
301
|
+
return success(request.id, toolResult({ status: "team-start-complete", result: options.startTeam(dispatchIds) }));
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
return success(request.id, toolResult({ status: "team-start-blocked" }, true));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (call.name === "process_result") {
|
|
308
|
+
try {
|
|
309
|
+
if (!options.processResult)
|
|
310
|
+
throw new Error("protected result processing is unavailable");
|
|
311
|
+
const dispatchId = String(call.arguments.dispatch_id);
|
|
312
|
+
return success(request.id, toolResult({
|
|
313
|
+
status: "result-processing-complete",
|
|
314
|
+
result: options.processResult(dispatchId),
|
|
315
|
+
}));
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
return success(request.id, toolResult({ status: "result-processing-blocked" }, true));
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
const proposal = call.arguments;
|
|
322
|
+
if (proposal.repository_scope !== workspaceRoot) {
|
|
323
|
+
return success(request.id, toolResult({ status: "repository-scope-mismatch" }, true));
|
|
324
|
+
}
|
|
325
|
+
try {
|
|
326
|
+
const created = createGoalWithReplay(runtime.goals.authority, {
|
|
327
|
+
objective: proposal.objective,
|
|
328
|
+
repositoryScope: proposal.repository_scope,
|
|
329
|
+
queueScope: proposal.queue_scope,
|
|
330
|
+
stoppingCondition: proposal.stopping_condition,
|
|
331
|
+
runtimeHorizon: proposal.runtime_horizon,
|
|
332
|
+
budgetProfile: proposal.budget_profile,
|
|
333
|
+
policyProfile: proposal.policy_profile,
|
|
334
|
+
creationNonce: proposal.creation_nonce,
|
|
335
|
+
leaderId: actorId,
|
|
336
|
+
createdAt: clock(),
|
|
337
|
+
});
|
|
338
|
+
return success(request.id, toolResult({
|
|
339
|
+
status: created.status,
|
|
340
|
+
goal_id: created.goal.record_id,
|
|
341
|
+
version: created.goal.version,
|
|
342
|
+
}));
|
|
343
|
+
}
|
|
344
|
+
catch {
|
|
345
|
+
return success(request.id, toolResult({ status: "goal-conflict" }, true));
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (request.id === undefined)
|
|
349
|
+
return undefined;
|
|
350
|
+
return failure(request.id, -32601, "method not found");
|
|
351
|
+
}
|
|
352
|
+
return Object.freeze({
|
|
353
|
+
handleMessage,
|
|
354
|
+
handleLine(line) {
|
|
355
|
+
const bytes = Buffer.isBuffer(line) ? line : Buffer.from(line, "utf8");
|
|
356
|
+
if (bytes.byteLength > MAX_CONDUCTOR_BRIDGE_FRAME_BYTES) {
|
|
357
|
+
return serializeResponse(failure(null, -32700, "frame too large"));
|
|
358
|
+
}
|
|
359
|
+
let message;
|
|
360
|
+
try {
|
|
361
|
+
message = JSON.parse(bytes.toString("utf8"));
|
|
362
|
+
}
|
|
363
|
+
catch {
|
|
364
|
+
return serializeResponse(failure(null, -32700, "parse error"));
|
|
365
|
+
}
|
|
366
|
+
const response = handleMessage(message);
|
|
367
|
+
return response ? serializeResponse(response) : undefined;
|
|
368
|
+
},
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
export async function runConductorBridge(options) {
|
|
372
|
+
const bridge = createConductorBridge(options);
|
|
373
|
+
let fragments = [];
|
|
374
|
+
let frameBytes = 0;
|
|
375
|
+
let discardingOversizedFrame = false;
|
|
376
|
+
for await (const rawChunk of options.input) {
|
|
377
|
+
const chunk = Buffer.isBuffer(rawChunk) ? rawChunk : Buffer.from(String(rawChunk), "utf8");
|
|
378
|
+
let offset = 0;
|
|
379
|
+
while (offset < chunk.byteLength) {
|
|
380
|
+
const newline = chunk.indexOf(0x0a, offset);
|
|
381
|
+
const end = newline === -1 ? chunk.byteLength : newline;
|
|
382
|
+
const fragment = chunk.subarray(offset, end);
|
|
383
|
+
if (!discardingOversizedFrame) {
|
|
384
|
+
if (frameBytes + fragment.byteLength > MAX_CONDUCTOR_BRIDGE_FRAME_BYTES) {
|
|
385
|
+
fragments = [];
|
|
386
|
+
frameBytes = 0;
|
|
387
|
+
discardingOversizedFrame = true;
|
|
388
|
+
await writeResponse(options.output, serializeResponse(failure(null, -32700, "frame too large")));
|
|
389
|
+
}
|
|
390
|
+
else if (fragment.byteLength > 0) {
|
|
391
|
+
fragments.push(fragment);
|
|
392
|
+
frameBytes += fragment.byteLength;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (newline === -1)
|
|
396
|
+
break;
|
|
397
|
+
if (discardingOversizedFrame) {
|
|
398
|
+
discardingOversizedFrame = false;
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
const response = bridge.handleLine(joinFrame(fragments, frameBytes));
|
|
402
|
+
if (response)
|
|
403
|
+
await writeResponse(options.output, response);
|
|
404
|
+
}
|
|
405
|
+
fragments = [];
|
|
406
|
+
frameBytes = 0;
|
|
407
|
+
offset = newline + 1;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
if (!discardingOversizedFrame && frameBytes > 0) {
|
|
411
|
+
const response = bridge.handleLine(joinFrame(fragments, frameBytes));
|
|
412
|
+
if (response)
|
|
413
|
+
await writeResponse(options.output, response);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
function joinFrame(fragments, byteLength) {
|
|
417
|
+
const frame = Buffer.concat(fragments, byteLength);
|
|
418
|
+
return frame.at(-1) === 0x0d ? frame.subarray(0, -1) : frame;
|
|
419
|
+
}
|
|
420
|
+
async function writeResponse(output, serialized) {
|
|
421
|
+
if (!output.write(`${serialized}\n`, "utf8"))
|
|
422
|
+
await once(output, "drain");
|
|
423
|
+
}
|
|
424
|
+
function serializeResponse(response) {
|
|
425
|
+
return JSON.stringify(response);
|
|
426
|
+
}
|
|
427
|
+
function readPreparationRequest(path, preparationId, requestSchema) {
|
|
428
|
+
if (!existsSync(path))
|
|
429
|
+
return undefined;
|
|
430
|
+
const value = readJsonFileNoFollow(path, 128 * 1024);
|
|
431
|
+
if (!isRecord(value)
|
|
432
|
+
|| Object.keys(value).sort().join("\0") !== [
|
|
433
|
+
"created_at",
|
|
434
|
+
"preparation_id",
|
|
435
|
+
"request",
|
|
436
|
+
"request_sha256",
|
|
437
|
+
"schema_version",
|
|
438
|
+
"selected_ticket_prepared",
|
|
439
|
+
"selected_ticket_state",
|
|
440
|
+
].join("\0")
|
|
441
|
+
|| value.schema_version !== 1
|
|
442
|
+
|| value.preparation_id !== preparationId
|
|
443
|
+
|| typeof value.request_sha256 !== "string"
|
|
444
|
+
|| typeof value.created_at !== "string"
|
|
445
|
+
|| !["pending", "retryable", "leased"].includes(String(value.selected_ticket_state))
|
|
446
|
+
|| typeof value.selected_ticket_prepared !== "boolean"
|
|
447
|
+
|| !isRecord(value.request))
|
|
448
|
+
throw new Error("stored dispatch preparation request is invalid");
|
|
449
|
+
if (value.selected_ticket_state !== "pending" && value.selected_ticket_prepared !== true) {
|
|
450
|
+
throw new Error("stored dispatch preparation selected an unprepared active ticket");
|
|
451
|
+
}
|
|
452
|
+
assertSchema(value.request, requestSchema, "stored dispatch preparation request");
|
|
453
|
+
if (preparationRequestSha256(value.request, value.selected_ticket_state, value.selected_ticket_prepared) !== value.request_sha256) {
|
|
454
|
+
throw new Error("stored dispatch preparation request digest changed");
|
|
455
|
+
}
|
|
456
|
+
return value;
|
|
457
|
+
}
|
|
458
|
+
function readPreparationResult(path, preparationId, intentSchema) {
|
|
459
|
+
if (!existsSync(path))
|
|
460
|
+
return undefined;
|
|
461
|
+
const value = readJsonFileNoFollow(path, 256 * 1024);
|
|
462
|
+
if (!isRecord(value)
|
|
463
|
+
|| Object.keys(value).sort().join("\0") !== ["dispatch_intent_sha256", "intent", "preparation_id", "prepared_at", "schema_version"].join("\0")
|
|
464
|
+
|| value.schema_version !== 1
|
|
465
|
+
|| value.preparation_id !== preparationId
|
|
466
|
+
|| typeof value.dispatch_intent_sha256 !== "string"
|
|
467
|
+
|| typeof value.prepared_at !== "string"
|
|
468
|
+
|| !isRecord(value.intent))
|
|
469
|
+
throw new Error("stored dispatch preparation result is invalid");
|
|
470
|
+
assertSchema(value.intent, intentSchema, "stored dispatch preparation intent");
|
|
471
|
+
return value;
|
|
472
|
+
}
|
|
473
|
+
function readTicketWithinGoalScope(runtime, ticket, queueScope) {
|
|
474
|
+
const prefix = "github:label=";
|
|
475
|
+
if (!queueScope.startsWith(prefix) || queueScope.length === prefix.length) {
|
|
476
|
+
throw new Error("dispatch preparation goal queue scope is not a GitHub label scope");
|
|
477
|
+
}
|
|
478
|
+
const label = queueScope.slice(prefix.length);
|
|
479
|
+
const content = runtime.tickets.materializer.readContent({
|
|
480
|
+
ticket_id: ticket.record_id,
|
|
481
|
+
sha256: ticket.payload.content_sha256,
|
|
482
|
+
file_name: ticket.payload.content_file,
|
|
483
|
+
});
|
|
484
|
+
if (content.source !== "github"
|
|
485
|
+
|| content.repository === null
|
|
486
|
+
|| !content.labels.includes(label))
|
|
487
|
+
throw new Error("dispatch preparation ticket is outside the goal queue scope");
|
|
488
|
+
return content;
|
|
489
|
+
}
|
|
490
|
+
function assertPreparationRecoveryState(stored, current) {
|
|
491
|
+
const selectedVersion = stored.request.expected_ticket_version;
|
|
492
|
+
const selectedAttempt = stored.selected_ticket_state === "retryable"
|
|
493
|
+
? stored.request.attempt - 1
|
|
494
|
+
: stored.request.attempt;
|
|
495
|
+
const currentPrepared = isPreparedTicket(current);
|
|
496
|
+
const exactSelected = current.version === selectedVersion
|
|
497
|
+
&& current.state === stored.selected_ticket_state
|
|
498
|
+
&& current.attempt === selectedAttempt
|
|
499
|
+
&& currentPrepared === stored.selected_ticket_prepared;
|
|
500
|
+
const preparedPending = stored.selected_ticket_state === "pending"
|
|
501
|
+
&& !stored.selected_ticket_prepared
|
|
502
|
+
&& current.version === selectedVersion + 1
|
|
503
|
+
&& current.state === "pending"
|
|
504
|
+
&& current.attempt === selectedAttempt
|
|
505
|
+
&& currentPrepared;
|
|
506
|
+
const leasedVersion = selectedVersion + (stored.selected_ticket_state === "pending" && !stored.selected_ticket_prepared ? 2 : 1);
|
|
507
|
+
const admittedLease = stored.selected_ticket_state !== "leased"
|
|
508
|
+
&& current.version === leasedVersion
|
|
509
|
+
&& current.state === "leased"
|
|
510
|
+
&& current.attempt === stored.request.attempt
|
|
511
|
+
&& currentPrepared;
|
|
512
|
+
if (!exactSelected && !preparedPending && !admittedLease) {
|
|
513
|
+
throw new Error("dispatch preparation request-only recovery found ticket version drift");
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
function isPreparedTicket(ticket) {
|
|
517
|
+
const prepared = ticket.payload.verification_plan_ref !== null;
|
|
518
|
+
if (prepared !== (ticket.payload.worktree !== null)
|
|
519
|
+
|| prepared !== (ticket.payload.gate_digest !== null))
|
|
520
|
+
throw new Error("dispatch preparation ticket has partial preparation authority");
|
|
521
|
+
return prepared;
|
|
522
|
+
}
|
|
523
|
+
function assertNoConflictingDispatch(runtime, captured) {
|
|
524
|
+
const existing = runtime.dispatch.readIfExists(captured.canonical.dispatch_id);
|
|
525
|
+
if (!existing)
|
|
526
|
+
return;
|
|
527
|
+
if (captureStoredDispatchIntent(existing.payload).dispatch_intent_sha256 !== captured.dispatch_intent_sha256) {
|
|
528
|
+
throw new Error("dispatch preparation conflicts with an existing dispatch");
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
function preparationRequestSha256(request, selectedTicketState, selectedTicketPrepared) {
|
|
532
|
+
return sha256Canonical({
|
|
533
|
+
request,
|
|
534
|
+
selected_ticket_state: selectedTicketState,
|
|
535
|
+
selected_ticket_prepared: selectedTicketPrepared,
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
function sha256Canonical(value) {
|
|
539
|
+
return createHash("sha256").update(canonicalJson(value), "utf8").digest("hex");
|
|
540
|
+
}
|
|
541
|
+
function canonicalJson(value) {
|
|
542
|
+
if (value === null || typeof value === "boolean" || typeof value === "number" || typeof value === "string") {
|
|
543
|
+
return JSON.stringify(value);
|
|
544
|
+
}
|
|
545
|
+
if (Array.isArray(value))
|
|
546
|
+
return `[${value.map(canonicalJson).join(",")}]`;
|
|
547
|
+
if (!isRecord(value))
|
|
548
|
+
throw new Error("dispatch preparation contains a non-JSON value");
|
|
549
|
+
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(",")}}`;
|
|
550
|
+
}
|
|
551
|
+
function deepFreeze(value) {
|
|
552
|
+
if (typeof value !== "object" || value === null || Object.isFrozen(value))
|
|
553
|
+
return value;
|
|
554
|
+
for (const child of Object.values(value))
|
|
555
|
+
deepFreeze(child);
|
|
556
|
+
return Object.freeze(value);
|
|
557
|
+
}
|
|
558
|
+
function parseToolCall(value) {
|
|
559
|
+
if (!isRecord(value) || Object.keys(value).some((key) => key !== "name" && key !== "arguments" && key !== "_meta")) {
|
|
560
|
+
return undefined;
|
|
561
|
+
}
|
|
562
|
+
if (value._meta !== undefined && !isRecord(value._meta))
|
|
563
|
+
return undefined;
|
|
564
|
+
if (value.name !== "propose_goal"
|
|
565
|
+
&& value.name !== "prepare_dispatch"
|
|
566
|
+
&& value.name !== "advise_dispatch"
|
|
567
|
+
&& value.name !== "propose_dispatch"
|
|
568
|
+
&& value.name !== "manage_worker"
|
|
569
|
+
&& value.name !== "start_team"
|
|
570
|
+
&& value.name !== "process_result")
|
|
571
|
+
return undefined;
|
|
572
|
+
if (!isRecord(value.arguments))
|
|
573
|
+
return undefined;
|
|
574
|
+
return { name: value.name, arguments: value.arguments };
|
|
575
|
+
}
|
|
576
|
+
function toolResult(payload, isError = false) {
|
|
577
|
+
const result = {
|
|
578
|
+
content: [{ type: "text", text: JSON.stringify(payload) }],
|
|
579
|
+
};
|
|
580
|
+
if (isError)
|
|
581
|
+
result.isError = true;
|
|
582
|
+
return result;
|
|
583
|
+
}
|
|
584
|
+
function loadToolDefinitions(packageRoot) {
|
|
585
|
+
return Object.freeze([
|
|
586
|
+
Object.freeze({
|
|
587
|
+
name: "propose_goal",
|
|
588
|
+
description: "Propose one canonical OMS goal bound to this conductor session.",
|
|
589
|
+
inputSchema: loadJsonSchema(join(packageRoot, "schemas", CONDUCTOR_BRIDGE_TOOL_SCHEMA_FILES.propose_goal)),
|
|
590
|
+
}),
|
|
591
|
+
Object.freeze({
|
|
592
|
+
name: "prepare_dispatch",
|
|
593
|
+
description: "Prepare and lease one exact goal-selected ticket, returning the server-derived dispatch intent.",
|
|
594
|
+
inputSchema: loadJsonSchema(join(packageRoot, "schemas", CONDUCTOR_BRIDGE_TOOL_SCHEMA_FILES.prepare_dispatch)),
|
|
595
|
+
}),
|
|
596
|
+
Object.freeze({
|
|
597
|
+
name: "advise_dispatch",
|
|
598
|
+
description: "Request one fresh, read-only OMS advisor decision for an exact dispatch intent before proposing it.",
|
|
599
|
+
inputSchema: loadJsonSchema(join(packageRoot, "schemas", CONDUCTOR_BRIDGE_TOOL_SCHEMA_FILES.advise_dispatch)),
|
|
600
|
+
}),
|
|
601
|
+
Object.freeze({
|
|
602
|
+
name: "propose_dispatch",
|
|
603
|
+
description: "Propose one OMS dispatch bound to existing authority and its approved advisor evidence.",
|
|
604
|
+
inputSchema: loadJsonSchema(join(packageRoot, "schemas", CONDUCTOR_BRIDGE_TOOL_SCHEMA_FILES.propose_dispatch)),
|
|
605
|
+
}),
|
|
606
|
+
Object.freeze({
|
|
607
|
+
name: "manage_worker",
|
|
608
|
+
description: "Observe, park, resume, or stop one accepted OMS worker dispatch through typed lifecycle authority.",
|
|
609
|
+
inputSchema: loadJsonSchema(join(packageRoot, "schemas", CONDUCTOR_BRIDGE_TOOL_SCHEMA_FILES.manage_worker)),
|
|
610
|
+
}),
|
|
611
|
+
Object.freeze({
|
|
612
|
+
name: "start_team",
|
|
613
|
+
description: "Persist and start one executor-only OMS group from accepted dispatch IDs.",
|
|
614
|
+
inputSchema: loadJsonSchema(join(packageRoot, "schemas", CONDUCTOR_BRIDGE_TOOL_SCHEMA_FILES.start_team)),
|
|
615
|
+
}),
|
|
616
|
+
Object.freeze({
|
|
617
|
+
name: "process_result",
|
|
618
|
+
description: "Advance one resolved OMS worker result through protected verification, one cross-engine grade, bounded retry authority, and the fixed draft-review handoff.",
|
|
619
|
+
inputSchema: loadJsonSchema(join(packageRoot, "schemas", CONDUCTOR_BRIDGE_TOOL_SCHEMA_FILES.process_result)),
|
|
620
|
+
}),
|
|
621
|
+
]);
|
|
622
|
+
}
|
|
623
|
+
function isValidWorkerControl(request) {
|
|
624
|
+
if (request.action === "park") {
|
|
625
|
+
return request.reason !== null && request.reason.trim().length > 0 && request.parked_until !== null;
|
|
626
|
+
}
|
|
627
|
+
if (request.action === "stop") {
|
|
628
|
+
return request.reason !== null && request.reason.trim().length > 0 && request.parked_until === null;
|
|
629
|
+
}
|
|
630
|
+
return request.reason === null && request.parked_until === null;
|
|
631
|
+
}
|
|
632
|
+
function parseRequest(value) {
|
|
633
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
634
|
+
return undefined;
|
|
635
|
+
const candidate = value;
|
|
636
|
+
if (candidate.jsonrpc !== "2.0" || typeof candidate.method !== "string")
|
|
637
|
+
return undefined;
|
|
638
|
+
if (candidate.id !== undefined && candidate.id !== null
|
|
639
|
+
&& typeof candidate.id !== "string" && typeof candidate.id !== "number")
|
|
640
|
+
return undefined;
|
|
641
|
+
return candidate;
|
|
642
|
+
}
|
|
643
|
+
function success(id, result) {
|
|
644
|
+
return { jsonrpc: "2.0", id, result };
|
|
645
|
+
}
|
|
646
|
+
function invalidRequest(id) {
|
|
647
|
+
return failure(id, -32600, "invalid request");
|
|
648
|
+
}
|
|
649
|
+
function failure(id, code, message) {
|
|
650
|
+
return { jsonrpc: "2.0", id, error: { code, message } };
|
|
651
|
+
}
|
|
652
|
+
//# sourceMappingURL=bridge.js.map
|