@usine/orchestrator 0.0.1 → 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.
Files changed (58) hide show
  1. package/README.md +123 -2
  2. package/dist/board/projection.d.ts +8 -0
  3. package/dist/board/projection.d.ts.map +1 -0
  4. package/dist/board/projection.js +151 -0
  5. package/dist/board/projection.js.map +1 -0
  6. package/dist/credentials.d.ts +12 -0
  7. package/dist/credentials.d.ts.map +1 -0
  8. package/dist/credentials.js +62 -0
  9. package/dist/credentials.js.map +1 -0
  10. package/dist/exe-dev.d.ts +7 -0
  11. package/dist/exe-dev.d.ts.map +1 -0
  12. package/dist/exe-dev.js +16 -0
  13. package/dist/exe-dev.js.map +1 -0
  14. package/dist/idle-triggers.d.ts +6 -0
  15. package/dist/idle-triggers.d.ts.map +1 -0
  16. package/dist/idle-triggers.js +29 -0
  17. package/dist/idle-triggers.js.map +1 -0
  18. package/dist/index.d.ts +10 -7
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +10 -7
  21. package/dist/index.js.map +1 -1
  22. package/dist/local.d.ts +20 -0
  23. package/dist/local.d.ts.map +1 -0
  24. package/dist/local.js +46 -0
  25. package/dist/local.js.map +1 -0
  26. package/dist/operator/model.d.ts +280 -0
  27. package/dist/operator/model.d.ts.map +1 -0
  28. package/dist/operator/model.js +242 -0
  29. package/dist/operator/model.js.map +1 -0
  30. package/dist/operator/projection.d.ts +17 -0
  31. package/dist/operator/projection.d.ts.map +1 -0
  32. package/dist/operator/projection.js +130 -0
  33. package/dist/operator/projection.js.map +1 -0
  34. package/dist/operator/service.d.ts +36 -0
  35. package/dist/operator/service.d.ts.map +1 -0
  36. package/dist/operator/service.js +248 -0
  37. package/dist/operator/service.js.map +1 -0
  38. package/dist/orchestrator.d.ts +13 -0
  39. package/dist/orchestrator.d.ts.map +1 -0
  40. package/dist/orchestrator.js +14 -0
  41. package/dist/orchestrator.js.map +1 -0
  42. package/dist/polling-triggers.d.ts +40 -0
  43. package/dist/polling-triggers.d.ts.map +1 -0
  44. package/dist/polling-triggers.js +394 -0
  45. package/dist/polling-triggers.js.map +1 -0
  46. package/dist/schedule-triggers.d.ts +65 -0
  47. package/dist/schedule-triggers.d.ts.map +1 -0
  48. package/dist/schedule-triggers.js +391 -0
  49. package/dist/schedule-triggers.js.map +1 -0
  50. package/dist/scheduler.d.ts +15 -0
  51. package/dist/scheduler.d.ts.map +1 -0
  52. package/dist/scheduler.js +122 -0
  53. package/dist/scheduler.js.map +1 -0
  54. package/dist/trigger-submission.d.ts +60 -0
  55. package/dist/trigger-submission.d.ts.map +1 -0
  56. package/dist/trigger-submission.js +105 -0
  57. package/dist/trigger-submission.js.map +1 -0
  58. package/package.json +28 -2
package/README.md CHANGED
@@ -1,5 +1,126 @@
1
1
  # @usine/orchestrator
2
2
 
3
- The embeddable usine composition: the full engine as an Effect layer, startable in-process.
3
+ `@usine/orchestrator` connects loaded loop files to GitHub polling, the durable run engine, and configured workers for [usine](https://github.com/basaltbytes/usine).
4
4
 
5
- Part of [usine](https://github.com/basaltbytes/usine), an agent-agnostic software factory. This block is not implemented yet — its 0.0.x releases reserve the seam while the engine grows. Everything here is 0.x: APIs change without notice.
5
+ Its platform-free root exports the complete embeddable application surface: `PollingTriggers`, `ScheduleTriggers`, `Orchestrator`, and `Operator`. `Orchestrator.run(instance)` runs both trigger streams; `Operator` provides run and Board observation, structured protocol transcript pages, label-backed Board moves, approve/retry/cancel, and database-backed Loop pause/unpause. Transcript payloads, Attempt brains/outcomes, and items needing attention remain typed data; consuming apps own their wording and presentation. `OperatorObservation` exposes the same read-only projection without constructing execution services. The latest polling and schedule failures remain visible through `Operator.overview(instance)` after their sibling work continues. Concurrent overview reads with the same durable revision share one projection computation.
6
+
7
+ `Operator.overview(instance)` groups the latest polled Items into each repository's authored lanes. Repositories without configured lanes receive proposals from the repository label catalog, including unused labels and repositories with no Items. Items that match no source appear in a read-only `Unmapped` lane, and label matches take precedence over state sources. Each card references its newest recorded Run for the same Item. A malformed Item projection is quarantined and reported in the Board and needs-you strip while valid siblings remain visible.
8
+
9
+ `Operator.moveBoardItem(instance, move)` adds the target lane labels and removes only labels owned by the lane map. GitHub labels outside that map remain unchanged even when the Item snapshot is stale or its label connection is truncated. The normal polling cycle evaluates the resulting trigger state.
10
+
11
+ `Operator.detail` accepts distinct cold, live-tail, and earlier-page requests. A cold read keeps the newest 500 rows per Attempt and returns an earlier cursor for every truncated Attempt; clients can page each cursor backward until the entire transcript is reachable without ballooning the first drawer response. A live-tail response returns at most 500 rows across the Run and advances its cursor from the last returned row.
12
+
13
+ ## Polling triggers
14
+
15
+ `PollingTriggers.poll(instance)` performs one cycle; `PollingTriggers.run(instance)` repeats cycles using the instance's factory-wide `poll_interval` and waits longer when GitHub reports rate-limit pressure. Per-repository failures are isolated and reported on the cycle — one failing repository never stops its siblings.
16
+
17
+ Each cycle asks `GitHubPolling` for changed items and the complete label catalog in every managed repository. It stores the catalog, fetches one payload snapshot per changed item, updates the durable Item projection, and evaluates each stream-matching loop's CEL `if:` expression against that snapshot. A match renders every `{{ CEL expression }}` in the loop body, resolves the named agent and effective parent model, then stores that immutable execution context with the Event. The Event identity covers the loop, canonical repository, item number, and timestamp-free content hash. An unmatch revokes pending or approval-waiting work for that loop and item. Repositories without matching loops are still polled for their Board projection.
18
+
19
+ Polling cursors live in the engine's `CursorStore`. When a loop starts watching a repository or its trigger expression changes, the orchestrator discards that repository's efficiency cursor and performs a cold poll, while the permanent Event ledger absorbs repeated state.
20
+
21
+ `PollingTriggers.layer` requires `CursorStore`, `LoopControl`, `RunEngine`, `ConfigParser`, `ExpressionEngine`, and `GitHubPolling`. The engine's local SQLite layer supplies the engine services:
22
+
23
+ ```ts
24
+ import { Layer } from "effect"
25
+ import { PollingTriggers } from "@usine/orchestrator"
26
+
27
+ const dependencies = Layer.mergeAll(
28
+ engineLayer,
29
+ configParserLayer,
30
+ expressionLayer,
31
+ githubPollingLayer,
32
+ )
33
+
34
+ export const triggersLayer = PollingTriggers.layer.pipe(
35
+ Layer.provide(dependencies),
36
+ )
37
+ ```
38
+
39
+ Call `poll` when another scheduler owns timing. Use `run` for the built-in endless polling loop.
40
+
41
+ ## Schedule triggers
42
+
43
+ `ScheduleTriggers.tick(instance)` evaluates the most recent due Tick for every `on: schedule` loop and fans it out to the repositories selected by that loop. Each selected repository receives one Event whose payload is `item.tick = { scheduledAt, scheduledAtLocal, cron, tz }`; `scheduledAt` is the UTC time the Tick was due, `scheduledAtLocal` the same instant in the loop's `tz:`, while the Event's `receivedAt` records when the orchestrator observed it.
44
+
45
+ The Event key covers the loop, canonical repository, and scheduled time. An in-memory fired-tick memory skips already-submitted boundaries, so calling `tick` repeatedly costs nothing, and waking after downtime (or a restart, which clears that memory) emits only the latest missed Tick. A cron whose boundaries cannot be computed at an instant — effect's Cron can fail inside a DST spring-forward gap — fails only that schedule for that cycle and is reported on the returned `ScheduleCycle`. The repository is the schedule stream's Item, so a later Tick follows the same supersede rules as issue and pull-request state. Schedule Runs go through the unchanged `RunEngine`, approval gate, worker scheduler, executor, and agent layer. Because they have no GitHub issue or pull request to comment on, their blocking moments remain UI-only.
46
+
47
+ `ScheduleTriggers.run(instance)` evaluates once at startup for catch-up, then sleeps until the earliest next Tick. Its layer requires `RunEngine`, `ConfigParser`, and `ExpressionEngine`.
48
+
49
+ ## Worker scheduling
50
+
51
+ The platform-free root entry exports `stepExecutorLayer`. At startup it verifies every configured worker, creates one capacity slot per `max_concurrent_attempts`, and assigns slots by Event receipt time. Runs stay pending while every slot is occupied. The layer rejects worker kinds that its supplied executor cannot run.
52
+
53
+ `@usine/orchestrator/local` composes the scheduler with the Node local executor and the engine's local SQLite adapter. It requires a caller-owned `CredentialProvider`; use `gitHubCredentialLayer` with `@usine/github`, or supply another provider that mints one repository credential per Attempt.
54
+
55
+ ```ts
56
+ import { layer as localLayer } from "@usine/orchestrator/local"
57
+
58
+ const EngineLive = localLayer(instanceDirectory, config, {
59
+ repositoryUrl: (repository) => `https://github.com/${repository}.git`,
60
+ })
61
+ ```
62
+
63
+ Provide `CredentialProvider` to `EngineLive`, then request `RunEngine` from the resulting Effect layer. The local composition caches repositories under `<instance>/.usine/workers/<worker>/repos` and removes Attempt worktrees after completion or cancellation.
64
+
65
+ For the whole local application, `runtimeLayer(instanceDirectory, instance, options)` additionally composes GitHub polling, schedule triggers, CEL parsing, `Orchestrator`, and `Operator`. It requires only `GitHubCredentials`; the server or another host owns how those credentials are loaded. `operatorObservationLayer(instanceDirectory)` is the read-only Node composition for setup and maintenance surfaces: it reads durable Runs and Loop runtime state while trigger execution remains idle.
66
+
67
+ For an exe.dev Worker, use the `@usine/orchestrator/exe-dev` composition. It keeps the engine and SQLite runtime local while the unchanged Worker contract runs on the named VM:
68
+
69
+ ```ts
70
+ import { Repository } from "@usine/core"
71
+ import { GitHubIntegration, HarnessLoginCheck, IntegrationName } from "@usine/executor/exe-dev"
72
+ import { layer as exeDevLayer } from "@usine/orchestrator/exe-dev"
73
+
74
+ const EngineLive = exeDevLayer(instanceDirectory, config, {
75
+ githubIntegrations: [
76
+ new GitHubIntegration({
77
+ repository: Repository.Name.make("acme/widget"),
78
+ name: IntegrationName.make("usine-acme-widget"),
79
+ }),
80
+ ],
81
+ harnessLoginChecks: [
82
+ new HarnessLoginCheck({
83
+ harness: "codex",
84
+ command: "codex",
85
+ args: ["login", "status"],
86
+ }),
87
+ ],
88
+ })
89
+ ```
90
+
91
+ The composition sets the GitHub integration grant to five minutes beyond `max_attempt_minutes`. Pass `credentialGrantMinutes` to use another bounded window. The scheduler also bounds every launch at `max_attempt_minutes`: a hung run host or dead link is interrupted through the normal cancel handshake and reported as a typed infrastructure failure before its credential grant lapses.
92
+
93
+ The live exe.dev check requires an existing baked VM and its GitHub integration:
94
+
95
+ ```sh
96
+ export USINE_EXE_DEV_INTEGRATION_WORKER=worker-name
97
+ export USINE_EXE_DEV_INTEGRATION_REPO=owner/repo
98
+ export USINE_EXE_DEV_INTEGRATION_REVISION=main
99
+ export USINE_EXE_DEV_INTEGRATION_GITHUB_INTEGRATION=integration-name
100
+ pnpm --filter @usine/orchestrator test:exe-dev
101
+ ```
102
+
103
+ ## Live GitHub check
104
+
105
+ The opt-in integration test needs a disposable issue in a repository covered by the configured GitHub App. It creates a uniquely named repository label, applies it to the issue, checks the resulting Event and restart deduplication, then deletes the label.
106
+
107
+ ```sh
108
+ export USINE_GITHUB_INTEGRATION_INSTANCE_DIRECTORY=/path/to/instance
109
+ export USINE_GITHUB_INTEGRATION_REPO=owner/repo
110
+ export USINE_GITHUB_INTEGRATION_ISSUE_NUMBER=123
111
+ pnpm --filter @usine/orchestrator test:integration
112
+ ```
113
+
114
+ The agent contract test also starts the local worker and production run host. The Pi parent delegates to Claude Code, which reads the issue with `gh` and posts one signed comment as the App bot. Build the workspace first, provide working Pi and Claude credentials in the worker user's home directory, then run:
115
+
116
+ ```sh
117
+ pnpm build
118
+ export USINE_GITHUB_INTEGRATION_BOT_LOGIN='your-app[bot]'
119
+ export USINE_AGENT_INTEGRATION_PARENT_MODEL=provider/model
120
+ export USINE_AGENT_INTEGRATION_CHILD_MODEL=claude-model-id
121
+ pnpm --filter @usine/orchestrator test:integration:agent
122
+ ```
123
+
124
+ The test removes its kick and result comments during cleanup.
125
+
126
+ Everything here is 0.x, so APIs can change between minor releases. Supply `effect` at the version pinned by the usine workspace.
@@ -0,0 +1,8 @@
1
+ import { type ManagedRepo } from "@usine/config";
2
+ import type { ItemProjection } from "@usine/engine";
3
+ import { ItemLabelMutation } from "@usine/github";
4
+ import { Effect } from "effect";
5
+ import { BoardView, type RunView, WritableBoardLaneView } from "../operator/model.ts";
6
+ export declare const projectBoard: (repository: ManagedRepo, repositoryLabels: readonly string[], storedItems: readonly ItemProjection[], runs: readonly RunView[]) => Effect.Effect<BoardView, never, never>;
7
+ export declare const labelMutationForBoardMove: (board: BoardView, target: WritableBoardLaneView) => ItemLabelMutation;
8
+ //# sourceMappingURL=projection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projection.d.ts","sourceRoot":"","sources":["../../src/board/projection.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,WAAW,EACjB,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAgB,iBAAiB,EAAsB,MAAM,eAAe,CAAC;AACpF,OAAO,EAAE,MAAM,EAAkB,MAAM,QAAQ,CAAC;AAChD,OAAO,EAIL,SAAS,EAET,KAAK,OAAO,EACZ,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAkH9B,eAAO,MAAM,YAAY,4KAgFxB,CAAC;AAEF,eAAO,MAAM,yBAAyB,UAC7B,SAAS,UACR,qBAAqB,KAC5B,iBAaF,CAAC"}
@@ -0,0 +1,151 @@
1
+ import { GitHubLabelName, LabelLaneSource, Lane, LaneName, } from "@usine/config";
2
+ import { Item, RunState } from "@usine/core";
3
+ import { IssuePayload, ItemLabelMutation, PullRequestPayload } from "@usine/github";
4
+ import { Effect, Result, Schema } from "effect";
5
+ import { BoardItemView, BoardLaneId, BoardProjectionError, BoardView, ReadOnlyBoardLaneView, WritableBoardLaneView, } from "../operator/model.js";
6
+ const labelsFrom = Schema.decodeUnknownEffect(Schema.Array(GitHubLabelName));
7
+ const projectionError = (item, message) => new BoardProjectionError({
8
+ repository: item.repository,
9
+ itemKey: item.itemKey,
10
+ message,
11
+ });
12
+ const projectedItem = (item) => Effect.gen(function* () {
13
+ if (item.source === "issue") {
14
+ const payload = yield* Schema.decodeUnknownEffect(IssuePayload)(item.payload).pipe(Effect.mapError((error) => projectionError(item, error.message)));
15
+ return {
16
+ itemKey: item.itemKey,
17
+ kind: "issue",
18
+ number: Item.Number.make(item.number),
19
+ title: payload.title,
20
+ url: payload.url,
21
+ state: payload.state === "OPEN" ? "issue-open" : "issue-closed",
22
+ labels: yield* labelsFrom(payload.labels.nodes.map(({ name }) => name)).pipe(Effect.mapError((error) => projectionError(item, error.message))),
23
+ };
24
+ }
25
+ if (item.source === "pr") {
26
+ const payload = yield* Schema.decodeUnknownEffect(PullRequestPayload)(item.payload).pipe(Effect.mapError((error) => projectionError(item, error.message)));
27
+ const state = payload.merged
28
+ ? "pr-merged"
29
+ : payload.state === "OPEN"
30
+ ? "pr-open"
31
+ : "pr-closed";
32
+ return {
33
+ itemKey: item.itemKey,
34
+ kind: "pr",
35
+ number: Item.Number.make(item.number),
36
+ title: payload.title,
37
+ url: payload.url,
38
+ state,
39
+ labels: yield* labelsFrom(payload.labels.nodes.map(({ name }) => name)).pipe(Effect.mapError((error) => projectionError(item, error.message))),
40
+ };
41
+ }
42
+ return yield* projectionError(item, `Unsupported Item projection source: ${item.source}`);
43
+ });
44
+ const labelSources = (sources) => sources.flatMap((source) => ("label" in source ? [source.label] : []));
45
+ const stateSources = (sources) => sources.flatMap((source) => ("state" in source ? [source.state] : []));
46
+ const proposedLanes = (repositoryLabels) => {
47
+ const labels = [...repositoryLabels]
48
+ .sort((left, right) => left.localeCompare(right))
49
+ .map((label) => GitHubLabelName.make(label));
50
+ return labels.map((label) => ({
51
+ lane: new Lane({
52
+ name: LaneName.make(label),
53
+ sources: [new LabelLaneSource({ label })],
54
+ }),
55
+ origin: "proposed",
56
+ }));
57
+ };
58
+ const effectiveLanes = (repository, repositoryLabels) => repository.lanes.length > 0
59
+ ? repository.lanes.map((lane) => ({ lane, origin: "authored" }))
60
+ : proposedLanes(repositoryLabels);
61
+ const laneId = (definition) => BoardLaneId.make(`${definition.origin}:${definition.lane.name}`);
62
+ const laneFor = (item, lanes) => lanes.find(({ lane }) => labelSources(lane.sources).some((label) => item.labels.includes(label))) ?? lanes.find(({ lane }) => stateSources(lane.sources).includes(item.state));
63
+ const isOpenRun = (run) => RunState.OPEN_STATE_TAGS.some((state) => state === run.state);
64
+ const needsOperator = (run) => run.state === "Waiting" || run.state === "Failed";
65
+ const preferredRun = (runs) => runs.find(needsOperator) ?? runs.find(isOpenRun) ?? runs[0] ?? null;
66
+ export const projectBoard = Effect.fn("Board.project")((repository, repositoryLabels, storedItems, runs) => Effect.gen(function* () {
67
+ yield* Effect.annotateCurrentSpan({ repository: repository.name });
68
+ const results = yield* Effect.forEach(storedItems, (item) => projectedItem(item).pipe(Effect.result));
69
+ const items = [];
70
+ const failures = [];
71
+ for (const result of results) {
72
+ if (Result.isSuccess(result)) {
73
+ items.push(result.success);
74
+ continue;
75
+ }
76
+ failures.push(result.failure);
77
+ yield* Effect.logError("Item projection quarantined from Board; siblings continue", {
78
+ repository: result.failure.repository,
79
+ itemKey: result.failure.itemKey,
80
+ errorTag: result.failure._tag,
81
+ message: result.failure.message,
82
+ });
83
+ }
84
+ const lanes = effectiveLanes(repository, repositoryLabels);
85
+ const runsByItem = new Map();
86
+ for (const run of runs) {
87
+ const itemRuns = runsByItem.get(run.itemKey) ?? [];
88
+ itemRuns.push(run);
89
+ runsByItem.set(run.itemKey, itemRuns);
90
+ }
91
+ const cards = items.map((item) => {
92
+ const itemRuns = runsByItem.get(item.itemKey) ?? [];
93
+ const run = preferredRun(itemRuns);
94
+ return new BoardItemView({
95
+ ...item,
96
+ runs: itemRuns,
97
+ run,
98
+ needsYou: itemRuns.some(needsOperator),
99
+ });
100
+ });
101
+ const grouped = new Map();
102
+ for (const definition of lanes)
103
+ grouped.set(laneId(definition), []);
104
+ const unmatched = [];
105
+ for (const card of cards) {
106
+ const definition = laneFor(card, lanes);
107
+ if (definition === undefined)
108
+ unmatched.push(card);
109
+ else
110
+ grouped.get(laneId(definition))?.push(card);
111
+ }
112
+ const sortItems = (values) => values.sort((left, right) => right.number - left.number);
113
+ return new BoardView({
114
+ failures,
115
+ lanes: [
116
+ ...lanes.map((definition) => {
117
+ const labels = labelSources(definition.lane.sources);
118
+ const fields = {
119
+ id: laneId(definition),
120
+ name: definition.lane.name,
121
+ sources: definition.lane.sources,
122
+ origin: definition.origin,
123
+ items: sortItems(grouped.get(laneId(definition)) ?? []),
124
+ };
125
+ return labels.length > 0
126
+ ? new WritableBoardLaneView({ ...fields, labels })
127
+ : new ReadOnlyBoardLaneView(fields);
128
+ }),
129
+ new ReadOnlyBoardLaneView({
130
+ id: BoardLaneId.make("fallback:unmapped"),
131
+ name: LaneName.make("Unmapped"),
132
+ sources: [],
133
+ origin: "fallback",
134
+ items: sortItems(unmatched),
135
+ }),
136
+ ],
137
+ });
138
+ }));
139
+ export const labelMutationForBoardMove = (board, target) => {
140
+ const laneOwned = new Set(board.lanes
141
+ .filter(({ origin }) => origin === target.origin)
142
+ .flatMap(({ sources }) => labelSources(sources)));
143
+ const targetLabels = new Set(target.labels);
144
+ return new ItemLabelMutation({
145
+ add: [...targetLabels].sort((left, right) => left.localeCompare(right)),
146
+ remove: [...laneOwned]
147
+ .filter((label) => !targetLabels.has(label))
148
+ .sort((left, right) => left.localeCompare(right)),
149
+ });
150
+ };
151
+ //# sourceMappingURL=projection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projection.js","sourceRoot":"","sources":["../../src/board/projection.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,eAAe,EACf,IAAI,EAEJ,QAAQ,GAGT,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EACL,aAAa,EACb,WAAW,EACX,oBAAoB,EACpB,SAAS,EACT,qBAAqB,EAErB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAiB9B,MAAM,UAAU,GAAG,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;AAE7E,MAAM,eAAe,GAAG,CAAC,IAAoB,EAAE,OAAe,EAAE,EAAE,CAChE,IAAI,oBAAoB,CAAC;IACvB,UAAU,EAAE,IAAI,CAAC,UAAU;IAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;IACrB,OAAO;CACR,CAAC,CAAC;AAEL,MAAM,aAAa,GAAG,CAAC,IAAoB,EAAsD,EAAE,CACjG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAChF,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CACjE,CAAC;QACF,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,IAAI,EAAE,OAAO;YACb,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;YACrC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,OAAO,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,cAAc;YAC/D,MAAM,EAAE,KAAK,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAC1E,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CACjE;SACF,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CACtF,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CACjE,CAAC;QACF,MAAM,KAAK,GAAkB,OAAO,CAAC,MAAM;YACzC,CAAC,CAAC,WAAW;YACb,CAAC,CAAC,OAAO,CAAC,KAAK,KAAK,MAAM;gBACxB,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,WAAW,CAAC;QAClB,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,IAAI,EAAE,IAAI;YACV,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;YACrC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK;YACL,MAAM,EAAE,KAAK,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAC1E,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CACjE;SACF,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,uCAAuC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AAC5F,CAAC,CAAC,CAAC;AAEL,MAAM,YAAY,GAAG,CAAC,OAAkC,EAAkC,EAAE,CAC1F,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAEzE,MAAM,YAAY,GAAG,CAAC,OAAkC,EAAgC,EAAE,CACxF,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAEzE,MAAM,aAAa,GAAG,CAAC,gBAAuC,EAAiC,EAAE;IAC/F,MAAM,MAAM,GAAG,CAAC,GAAG,gBAAgB,CAAC;SACjC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;SAChD,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC5B,IAAI,EAAE,IAAI,IAAI,CAAC;YACb,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;YAC1B,OAAO,EAAE,CAAC,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;SAC1C,CAAC;QACF,MAAM,EAAE,UAAU;KACnB,CAAC,CAAC,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CACrB,UAAuB,EACvB,gBAAuC,EACR,EAAE,CACjC,UAAU,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;IACzB,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC;AAEtC,MAAM,MAAM,GAAG,CAAC,UAA0B,EAAe,EAAE,CACzD,WAAW,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,MAAM,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AAEnE,MAAM,OAAO,GAAG,CACd,IAAmB,EACnB,KAAoC,EACR,EAAE,CAC9B,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CACtB,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CACxE,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AAEjF,MAAM,SAAS,GAAG,CAAC,GAAY,EAAW,EAAE,CAC1C,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC;AAEhE,MAAM,aAAa,GAAG,CAAC,GAAY,EAAW,EAAE,CAAC,GAAG,CAAC,KAAK,KAAK,SAAS,IAAI,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC;AAEnG,MAAM,YAAY,GAAG,CAAC,IAA4B,EAAkB,EAAE,CACpE,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAEtE,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,EAAE,CAAC,eAAe,CAAC,CACpD,CACE,UAAuB,EACvB,gBAAuC,EACvC,WAA0C,EAC1C,IAA4B,EACF,EAAE,CAC5B,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,KAAK,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;IACnE,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CAC1D,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CACxC,CAAC;IACF,MAAM,KAAK,GAAyB,EAAE,CAAC;IACvC,MAAM,QAAQ,GAAgC,EAAE,CAAC;IACjD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC3B,SAAS;QACX,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9B,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,2DAA2D,EAAE;YAClF,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU;YACrC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO;YAC/B,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI;YAC7B,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO;SAChC,CAAC,CAAC;IACL,CAAC;IACD,MAAM,KAAK,GAAG,cAAc,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;IAC3D,MAAM,UAAU,GAAG,IAAI,GAAG,EAAgC,CAAC;IAC3D,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACnD,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACxC,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC/B,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACnC,OAAO,IAAI,aAAa,CAAC;YACvB,GAAG,IAAI;YACP,IAAI,EAAE,QAAQ;YACd,GAAG;YACH,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC;SACvC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,IAAI,GAAG,EAAqC,CAAC;IAC7D,KAAK,MAAM,UAAU,IAAI,KAAK;QAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC;IACpE,MAAM,SAAS,GAAyB,EAAE,CAAC;IAC3C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACxC,IAAI,UAAU,KAAK,SAAS;YAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;YAC9C,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACnD,CAAC;IACD,MAAM,SAAS,GAAG,CAAC,MAA4B,EAAE,EAAE,CACjD,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3D,OAAO,IAAI,SAAS,CAAC;QACnB,QAAQ;QACR,KAAK,EAAE;YACL,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;gBAC1B,MAAM,MAAM,GAAG,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrD,MAAM,MAAM,GAAG;oBACb,EAAE,EAAE,MAAM,CAAC,UAAU,CAAC;oBACtB,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI;oBAC1B,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,OAAO;oBAChC,MAAM,EAAE,UAAU,CAAC,MAAM;oBACzB,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;iBAC/C,CAAC;gBACX,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC;oBACtB,CAAC,CAAC,IAAI,qBAAqB,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,CAAC;oBAClD,CAAC,CAAC,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC;YACxC,CAAC,CAAC;YACF,IAAI,qBAAqB,CAAC;gBACxB,EAAE,EAAE,WAAW,CAAC,IAAI,CAAC,mBAAmB,CAAC;gBACzC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC;gBAC/B,OAAO,EAAE,EAAE;gBACX,MAAM,EAAE,UAAU;gBAClB,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC;aAC5B,CAAC;SACH;KACF,CAAC,CAAC;AACL,CAAC,CAAC,CACL,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,KAAgB,EAChB,MAA6B,EACV,EAAE;IACrB,MAAM,SAAS,GAAG,IAAI,GAAG,CACvB,KAAK,CAAC,KAAK;SACR,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC;SAChD,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CACnD,CAAC;IACF,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,OAAO,IAAI,iBAAiB,CAAC;QAC3B,GAAG,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC;aACnB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;aAC3C,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;KACpD,CAAC,CAAC;AACL,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { UsineConfig } from "@usine/config";
2
+ import { CredentialProvider } from "@usine/executor";
3
+ import { GitHubApp } from "@usine/github";
4
+ import { Layer } from "effect";
5
+ /**
6
+ * Mints one fresh, single-repository GitHub App token per Attempt. Project
7
+ * access is discovered lazily on the first mint and cached — a GitHub outage
8
+ * cannot block orchestrator startup, and a repository added to the
9
+ * installation later is picked up by the next refresh after a miss.
10
+ */
11
+ export declare const gitHubCredentialLayer: (config: UsineConfig) => Layer.Layer<CredentialProvider, never, GitHubApp>;
12
+ //# sourceMappingURL=credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,kBAAkB,EAA8B,MAAM,iBAAiB,CAAC;AACjF,OAAO,EAAkB,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAU,KAAK,EAA2B,MAAM,QAAQ,CAAC;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,WACxB,WAAW,KAClB,KAAK,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,EAAE,SAAS,CAoFhD,CAAC"}
@@ -0,0 +1,62 @@
1
+ import { CredentialProvider, CredentialUnavailableError } from "@usine/executor";
2
+ import { CoveredProject, GitHubApp } from "@usine/github";
3
+ import { Effect, Layer, Option, SynchronizedRef } from "effect";
4
+ /**
5
+ * Mints one fresh, single-repository GitHub App token per Attempt. Project
6
+ * access is discovered lazily on the first mint and cached — a GitHub outage
7
+ * cannot block orchestrator startup, and a repository added to the
8
+ * installation later is picked up by the next refresh after a miss.
9
+ */
10
+ export const gitHubCredentialLayer = (config) => Layer.effect(CredentialProvider, Effect.gen(function* () {
11
+ const app = yield* GitHubApp;
12
+ const projectsRef = yield* SynchronizedRef.make(Option.none());
13
+ const discover = (repository) => app.projectAccess(config.repos.map(({ name }) => name)).pipe(Effect.map((access) => new Map(access
14
+ .filter((project) => project._tag === "CoveredProject")
15
+ .map((project) => [project.repository, project]))), Effect.mapError((cause) => new CredentialUnavailableError({
16
+ repository,
17
+ message: "Could not discover GitHub App repository access",
18
+ cause,
19
+ })));
20
+ /** Cached map; on a miss, refresh once before concluding "not covered". */
21
+ const projectFor = Effect.fn("GitHubCredentialProvider.projectFor")(function* (repository) {
22
+ const project = yield* SynchronizedRef.modifyEffect(projectsRef, (current) => Effect.gen(function* () {
23
+ if (Option.isSome(current)) {
24
+ const found = current.value.get(repository);
25
+ if (found !== undefined) {
26
+ const kept = [
27
+ Option.some(found),
28
+ current,
29
+ ];
30
+ return kept;
31
+ }
32
+ }
33
+ const refreshed = yield* discover(repository);
34
+ const refreshedResult = [Option.fromNullishOr(refreshed.get(repository)), Option.some(refreshed)];
35
+ return refreshedResult;
36
+ }));
37
+ if (Option.isNone(project)) {
38
+ return yield* new CredentialUnavailableError({
39
+ repository,
40
+ message: `GitHub App installation does not cover ${repository}`,
41
+ cause: new Error("no project access after refresh"),
42
+ });
43
+ }
44
+ return project.value;
45
+ });
46
+ return CredentialProvider.of({
47
+ issue: Effect.fn("GitHubCredentialProvider.issue")(function* (repository, attemptId) {
48
+ const project = yield* projectFor(repository);
49
+ const token = yield* app.workerToken(project).pipe(Effect.mapError((cause) => new CredentialUnavailableError({
50
+ repository,
51
+ message: `Could not mint a worker token for ${repository}`,
52
+ cause,
53
+ })));
54
+ yield* Effect.logInfo("Minted a single-repository worker token", {
55
+ repository,
56
+ attemptId,
57
+ });
58
+ return token.value;
59
+ }),
60
+ });
61
+ }));
62
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { UsineConfig } from "@usine/config";
2
+ import type { Instance } from "@usine/core";
3
+ import { type ExeDevExecutorOptions } from "@usine/executor/exe-dev";
4
+ import { Layer } from "effect";
5
+ /** Complete local-orchestrator / exe.dev-Worker engine composition. */
6
+ export declare const layer: (instanceDirectory: Instance.Directory, config: UsineConfig, options: ExeDevExecutorOptions) => Layer.Layer<import("@usine/engine").CursorStore | import("@usine/engine").ItemProjectionReader | import("@usine/engine").ItemProjectionWriter | import("@usine/engine").LoopControl | import("@usine/engine").RepositoryLabelProjectionReader | import("@usine/engine").RepositoryLabelProjectionWriter | import("@usine/engine").RunEngine | import("@usine/engine").RunReader, import("@usine/engine").AttemptCancellationError | import("@usine/executor").CredentialUnavailableError | import("@usine/engine").EnginePersistenceError | import("@usine/executor").ExecutorOperationError | import("@usine/engine").RunNotFoundError | import("@usine/engine").RunOperationRejectedError | import("./scheduler.ts").UnsupportedWorkerError | import("@usine/executor").WorkerCapabilityError, never>;
7
+ //# sourceMappingURL=exe-dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exe-dev.d.ts","sourceRoot":"","sources":["../src/exe-dev.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAG/B,uEAAuE;AACvE,eAAO,MAAM,KAAK,sBACG,QAAQ,CAAC,SAAS,UAC7B,WAAW,WACV,qBAAqB,4wBAU/B,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { NodeServices } from "@effect/platform-node";
2
+ import { CredentialGrantMinutes, layer as exeDevExecutorLayer, } from "@usine/executor/exe-dev";
3
+ import { layer as localEngineLayer } from "@usine/engine/local-sqlite";
4
+ import { Layer } from "effect";
5
+ import { stepExecutorLayer } from "./scheduler.js";
6
+ /** Complete local-orchestrator / exe.dev-Worker engine composition. */
7
+ export const layer = (instanceDirectory, config, options) => {
8
+ const executor = exeDevExecutorLayer({
9
+ ...options,
10
+ credentialGrantMinutes: options.credentialGrantMinutes ??
11
+ CredentialGrantMinutes.make(config.settings.maxAttemptMinutes + 5),
12
+ }).pipe(Layer.provide(NodeServices.layer));
13
+ const stepExecutor = stepExecutorLayer(config).pipe(Layer.provide(executor));
14
+ return localEngineLayer(instanceDirectory).pipe(Layer.provide(stepExecutor));
15
+ };
16
+ //# sourceMappingURL=exe-dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exe-dev.js","sourceRoot":"","sources":["../src/exe-dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGrD,OAAO,EACL,sBAAsB,EACtB,KAAK,IAAI,mBAAmB,GAE7B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,KAAK,IAAI,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,uEAAuE;AACvE,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,iBAAqC,EACrC,MAAmB,EACnB,OAA8B,EAC9B,EAAE;IACF,MAAM,QAAQ,GAAG,mBAAmB,CAAC;QACnC,GAAG,OAAO;QACV,sBAAsB,EACpB,OAAO,CAAC,sBAAsB;YAC9B,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,GAAG,CAAC,CAAC;KACrE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC7E,OAAO,gBAAgB,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;AAC/E,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { Layer } from "effect";
2
+ import { PollingTriggers } from "./polling-triggers.ts";
3
+ import { ScheduleTriggers } from "./schedule-triggers.ts";
4
+ /** Trigger services for needs-setup observation; no stream performs work. */
5
+ export declare const idleTriggersLayer: Layer.Layer<PollingTriggers | ScheduleTriggers, never, never>;
6
+ //# sourceMappingURL=idle-triggers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idle-triggers.d.ts","sourceRoot":"","sources":["../src/idle-triggers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,EAAU,MAAM,QAAQ,CAAC;AAC/C,OAAO,EAAa,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAiB,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAEzE,6EAA6E;AAC7E,eAAO,MAAM,iBAAiB,+DAgC7B,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { Effect, Layer, Option } from "effect";
2
+ import { PollCycle, PollingTriggers } from "./polling-triggers.js";
3
+ import { ScheduleCycle, ScheduleTriggers } from "./schedule-triggers.js";
4
+ /** Trigger services for needs-setup observation; no stream performs work. */
5
+ export const idleTriggersLayer = Layer.mergeAll(Layer.succeed(PollingTriggers)({
6
+ latest: Effect.succeed(Option.none()),
7
+ poll: () => Effect.succeed(new PollCycle({
8
+ repositories: 0,
9
+ changedItems: 0,
10
+ submissions: [],
11
+ revokedRuns: 0,
12
+ failures: [],
13
+ nextPollAt: Option.none(),
14
+ })),
15
+ run: () => Effect.never,
16
+ }), Layer.succeed(ScheduleTriggers)({
17
+ latest: Effect.succeed(Option.none()),
18
+ tick: () => Effect.succeed(new ScheduleCycle({
19
+ loops: 0,
20
+ fanout: 0,
21
+ submissions: [],
22
+ skipped: 0,
23
+ alreadyFired: 0,
24
+ failures: [],
25
+ nextTickAt: Option.none(),
26
+ })),
27
+ run: () => Effect.never,
28
+ }));
29
+ //# sourceMappingURL=idle-triggers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idle-triggers.js","sourceRoot":"","sources":["../src/idle-triggers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAEzE,6EAA6E;AAC7E,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC,QAAQ,CAC7C,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACrC,IAAI,EAAE,GAAG,EAAE,CACT,MAAM,CAAC,OAAO,CACZ,IAAI,SAAS,CAAC;QACZ,YAAY,EAAE,CAAC;QACf,YAAY,EAAE,CAAC;QACf,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,CAAC;QACd,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE;KAC1B,CAAC,CACH;IACH,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK;CACxB,CAAC,EACF,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACrC,IAAI,EAAE,GAAG,EAAE,CACT,MAAM,CAAC,OAAO,CACZ,IAAI,aAAa,CAAC;QAChB,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC;QACT,WAAW,EAAE,EAAE;QACf,OAAO,EAAE,CAAC;QACV,YAAY,EAAE,CAAC;QACf,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE;KAC1B,CAAC,CACH;IACH,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK;CACxB,CAAC,CACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,11 @@
1
- /**
2
- * @usine/orchestrator — The embeddable usine composition: the full engine as an Effect layer, startable in-process.
3
- *
4
- * Not implemented yet: this 0.0.x release reserves the block's seam while the
5
- * engine grows.
6
- */
7
- export {};
1
+ /** @usine/orchestrator — embeddable trigger-to-run and worker composition. */
2
+ export * from "./operator/model.ts";
3
+ export * from "./operator/service.ts";
4
+ export { labelMutationForBoardMove, projectBoard } from "./board/projection.ts";
5
+ export * from "./orchestrator.ts";
6
+ export { idleTriggersLayer } from "./idle-triggers.ts";
7
+ export { PollCycle, PollingTriggers, RepositoryPollFailure } from "./polling-triggers.ts";
8
+ export { ScheduleAgentFailure, ScheduleCronFailure, ScheduleCycle, ScheduleFailure, ScheduleTickFailure, ScheduleTriggers, } from "./schedule-triggers.ts";
9
+ export { stepExecutorLayer, UnsupportedWorkerError } from "./scheduler.ts";
10
+ export { gitHubCredentialLayer } from "./credentials.ts";
8
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,yBAAyB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChF,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -1,8 +1,11 @@
1
- /**
2
- * @usine/orchestrator — The embeddable usine composition: the full engine as an Effect layer, startable in-process.
3
- *
4
- * Not implemented yet: this 0.0.x release reserves the block's seam while the
5
- * engine grows.
6
- */
7
- export {};
1
+ /** @usine/orchestrator — embeddable trigger-to-run and worker composition. */
2
+ export * from "./operator/model.js";
3
+ export * from "./operator/service.js";
4
+ export { labelMutationForBoardMove, projectBoard } from "./board/projection.js";
5
+ export * from "./orchestrator.js";
6
+ export { idleTriggersLayer } from "./idle-triggers.js";
7
+ export { PollCycle, PollingTriggers, RepositoryPollFailure } from "./polling-triggers.js";
8
+ export { ScheduleAgentFailure, ScheduleCronFailure, ScheduleCycle, ScheduleFailure, ScheduleTickFailure, ScheduleTriggers, } from "./schedule-triggers.js";
9
+ export { stepExecutorLayer, UnsupportedWorkerError } from "./scheduler.js";
10
+ export { gitHubCredentialLayer } from "./credentials.js";
8
11
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,yBAAyB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChF,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { ConfigParser, type LoadedInstance, type UsineConfig } from "@usine/config";
2
+ import type { Instance } from "@usine/core";
3
+ import { type LocalExecutorOptions } from "@usine/executor/local";
4
+ import { GitHubItemWriter, GitHubPolling } from "@usine/github";
5
+ import { Layer } from "effect";
6
+ import { Operator, OperatorObservation } from "./operator/service.ts";
7
+ import { Orchestrator } from "./orchestrator.ts";
8
+ import { PollingTriggers } from "./polling-triggers.ts";
9
+ import { ScheduleTriggers } from "./schedule-triggers.ts";
10
+ /** Complete local-worker engine composition. Credential sourcing stays caller-owned. */
11
+ export declare const layer: (instanceDirectory: Instance.Directory, config: UsineConfig, options: Omit<LocalExecutorOptions, "instanceDirectory" | "runHost"> & Partial<Pick<LocalExecutorOptions, "runHost">>) => Layer.Layer<import("@usine/engine").CursorStore | import("@usine/engine").ItemProjectionReader | import("@usine/engine").ItemProjectionWriter | import("@usine/engine").LoopControl | import("@usine/engine").RepositoryLabelProjectionReader | import("@usine/engine").RepositoryLabelProjectionWriter | import("@usine/engine").RunEngine | import("@usine/engine").RunReader, import("@usine/engine").AttemptCancellationError | import("@usine/executor").CredentialUnavailableError | import("@usine/engine").EnginePersistenceError | import("@usine/executor").ExecutorOperationError | import("@usine/engine").RunNotFoundError | import("@usine/engine").RunOperationRejectedError | import("./scheduler.ts").UnsupportedWorkerError | import("@usine/executor").WorkerCapabilityError, import("@usine/executor").CredentialProvider>;
12
+ /** Read-only local operator composition used while trigger credentials are unavailable. */
13
+ export declare const operatorObservationLayer: (instanceDirectory: Instance.Directory) => Layer.Layer<OperatorObservation, import("@usine/engine").AttemptCancellationError | import("@usine/engine").EnginePersistenceError | import("@usine/engine").RunNotFoundError | import("@usine/engine").RunOperationRejectedError, never>;
14
+ /**
15
+ * Complete Node composition for one loaded local factory. The caller still
16
+ * owns GitHub credential sourcing; everything else — both trigger streams,
17
+ * durable engine, worker execution, and operator surface — is included.
18
+ */
19
+ export declare const runtimeLayer: (instanceDirectory: Instance.Directory, instance: LoadedInstance, options: Omit<LocalExecutorOptions, "instanceDirectory" | "runHost"> & Partial<Pick<LocalExecutorOptions, "runHost">>) => Layer.Layer<ConfigParser | import("@usine/engine").CursorStore | import("@usine/expression").ExpressionEngine | GitHubItemWriter | GitHubPolling | import("@usine/engine").ItemProjectionReader | import("@usine/engine").ItemProjectionWriter | import("@usine/engine").LoopControl | Operator | Orchestrator | PollingTriggers | import("@usine/engine").RepositoryLabelProjectionReader | import("@usine/engine").RepositoryLabelProjectionWriter | import("@usine/engine").RunEngine | import("@usine/engine").RunReader | ScheduleTriggers, import("@usine/github").AppAuthenticationError | import("@usine/engine").AttemptCancellationError | import("@usine/executor").CredentialUnavailableError | import("@usine/engine").EnginePersistenceError | import("@usine/executor").ExecutorOperationError | import("@usine/engine").RunNotFoundError | import("@usine/engine").RunOperationRejectedError | import("./scheduler.ts").UnsupportedWorkerError | import("@usine/executor").WorkerCapabilityError, import("@usine/github").GitHubCredentials>;
20
+ //# sourceMappingURL=local.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../src/local.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAA+B,KAAK,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAM/F,OAAO,EAAa,gBAAgB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE3E,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAI/B,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D,wFAAwF;AACxF,eAAO,MAAM,KAAK,sBACG,QAAQ,CAAC,SAAS,UAC7B,WAAW,WACV,IAAI,CAAC,oBAAoB,EAAE,mBAAmB,GAAG,SAAS,CAAC,GAClE,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAC,mzBASjD,CAAC;AAEF,2FAA2F;AAC3F,eAAO,MAAM,wBAAwB,sBAAuB,QAAQ,CAAC,SAAS,8OAG3E,CAAC;AAEJ;;;;GAIG;AACH,eAAO,MAAM,YAAY,sBACJ,QAAQ,CAAC,SAAS,YAC3B,cAAc,WACf,IAAI,CAAC,oBAAoB,EAAE,mBAAmB,GAAG,SAAS,CAAC,GAClE,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAC,igCA4BjD,CAAC"}
package/dist/local.js ADDED
@@ -0,0 +1,46 @@
1
+ import { NodeServices } from "@effect/platform-node";
2
+ import { ConfigParser } from "@usine/config";
3
+ import { layer as localExecutorLayer } from "@usine/executor/local";
4
+ import { layer as localEngineLayer, observationLayer as localObservationLayer, } from "@usine/engine/local-sqlite";
5
+ import { MarcbachmannCelLayer } from "@usine/expression";
6
+ import { GitHubApp, GitHubItemWriter, GitHubPolling } from "@usine/github";
7
+ import { executableCommand } from "@usine/run-host/executable";
8
+ import { Layer } from "effect";
9
+ import { FetchHttpClient } from "effect/unstable/http";
10
+ import { gitHubCredentialLayer } from "./credentials.js";
11
+ import { idleTriggersLayer } from "./idle-triggers.js";
12
+ import { Operator, OperatorObservation } from "./operator/service.js";
13
+ import { Orchestrator } from "./orchestrator.js";
14
+ import { PollingTriggers } from "./polling-triggers.js";
15
+ import { ScheduleTriggers } from "./schedule-triggers.js";
16
+ import { stepExecutorLayer } from "./scheduler.js";
17
+ /** Complete local-worker engine composition. Credential sourcing stays caller-owned. */
18
+ export const layer = (instanceDirectory, config, options) => {
19
+ const executor = localExecutorLayer({
20
+ runHost: options.runHost ?? executableCommand(),
21
+ ...options,
22
+ instanceDirectory,
23
+ }).pipe(Layer.provide(NodeServices.layer));
24
+ const stepExecutor = stepExecutorLayer(config).pipe(Layer.provide(executor));
25
+ return localEngineLayer(instanceDirectory).pipe(Layer.provide(stepExecutor));
26
+ };
27
+ /** Read-only local operator composition used while trigger credentials are unavailable. */
28
+ export const operatorObservationLayer = (instanceDirectory) => OperatorObservation.layer.pipe(Layer.provide(Layer.mergeAll(localObservationLayer(instanceDirectory), idleTriggersLayer)));
29
+ /**
30
+ * Complete Node composition for one loaded local factory. The caller still
31
+ * owns GitHub credential sourcing; everything else — both trigger streams,
32
+ * durable engine, worker execution, and operator surface — is included.
33
+ */
34
+ export const runtimeLayer = (instanceDirectory, instance, options) => {
35
+ const app = GitHubApp.layer.pipe(Layer.provide(FetchHttpClient.layer), Layer.provide(NodeServices.layer));
36
+ const credentials = gitHubCredentialLayer(instance.config).pipe(Layer.provide(app));
37
+ const engine = layer(instanceDirectory, instance.config, options).pipe(Layer.provide(credentials));
38
+ const polling = GitHubPolling.layer.pipe(Layer.provide(app), Layer.provide(FetchHttpClient.layer), Layer.provide(NodeServices.layer));
39
+ const itemWriter = GitHubItemWriter.layer.pipe(Layer.provide(app), Layer.provide(FetchHttpClient.layer));
40
+ const parser = ConfigParser.layer.pipe(Layer.provide(MarcbachmannCelLayer));
41
+ const dependencies = Layer.mergeAll(engine, itemWriter, MarcbachmannCelLayer, parser, polling);
42
+ const triggers = Layer.mergeAll(PollingTriggers.layer, ScheduleTriggers.layer).pipe(Layer.provide(dependencies));
43
+ const services = Layer.mergeAll(Operator.layer, Orchestrator.layer).pipe(Layer.provide(Layer.mergeAll(dependencies, triggers)));
44
+ return Layer.mergeAll(dependencies, triggers, services);
45
+ };
46
+ //# sourceMappingURL=local.js.map