factoryhub 0.1.0 → 0.1.1
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/README.md +9 -3
- package/factories/index.json +231 -0
- package/factories/newsletter-note/README.md +11 -0
- package/factories/newsletter-note/agents/reviewer/agent.md +10 -0
- package/factories/newsletter-note/agents/writer/agent.md +11 -0
- package/factories/newsletter-note/factory.yaml +12 -0
- package/factories/newsletter-note/flow.yaml +45 -0
- package/factories/newsletter-note/mindburn.tests.yaml +80 -0
- package/factories/release-desk/README.md +13 -0
- package/factories/release-desk/agents/editor/agent.md +10 -0
- package/factories/release-desk/agents/reviewer/agent.md +10 -0
- package/factories/release-desk/factory.yaml +13 -0
- package/factories/release-desk/flow.yaml +67 -0
- package/factories/release-desk/mindburn.tests.yaml +163 -0
- package/factories/short-video-cut/README.md +11 -0
- package/factories/short-video-cut/agents/reviewer/agent.md +10 -0
- package/factories/short-video-cut/agents/writer/agent.md +11 -0
- package/factories/short-video-cut/factory.yaml +13 -0
- package/factories/short-video-cut/flow.yaml +46 -0
- package/factories/short-video-cut/mindburn.tests.yaml +80 -0
- package/factories/video-facts/README.md +11 -0
- package/factories/video-facts/agents/analyst/agent.md +10 -0
- package/factories/video-facts/agents/reviewer/agent.md +10 -0
- package/factories/video-facts/factory.yaml +13 -0
- package/factories/video-facts/flow.yaml +39 -0
- package/factories/video-facts/mindburn.tests.yaml +34 -0
- package/factories/video-to-posts/README.md +35 -0
- package/factories/video-to-posts/agents/analyst/agent.md +10 -0
- package/factories/video-to-posts/agents/reviewer/agent.md +10 -0
- package/factories/video-to-posts/agents/writer/agent.md +11 -0
- package/factories/video-to-posts/factory.yaml +12 -0
- package/factories/video-to-posts/flow.yaml +62 -0
- package/factories/video-to-posts/mindburn.tests.yaml +34 -0
- package/factories/week-of-posts/README.md +11 -0
- package/factories/week-of-posts/agents/reviewer/agent.md +10 -0
- package/factories/week-of-posts/agents/writer/agent.md +11 -0
- package/factories/week-of-posts/factory.yaml +12 -0
- package/factories/week-of-posts/flow.yaml +46 -0
- package/factories/week-of-posts/mindburn.tests.yaml +80 -0
- package/package.json +15 -2
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/commands/export.mjs +0 -1
- package/packages/cli/src/commands/get.mjs +0 -1
- package/packages/cli/src/commands/inspect.mjs +0 -1
- package/packages/cli/src/commands/list.mjs +1 -6
- package/packages/cli/src/commands/login.mjs +161 -0
- package/packages/cli/src/commands/logout.mjs +43 -0
- package/packages/cli/src/commands/mcp.mjs +0 -1
- package/packages/cli/src/commands/new.mjs +0 -1
- package/packages/cli/src/commands/pack.mjs +0 -1
- package/packages/cli/src/commands/publish.mjs +62 -0
- package/packages/cli/src/commands/pull.mjs +59 -0
- package/packages/cli/src/commands/push.mjs +115 -0
- package/packages/cli/src/commands/resume.mjs +0 -1
- package/packages/cli/src/commands/run.mjs +182 -20
- package/packages/cli/src/commands/runs.mjs +52 -0
- package/packages/cli/src/commands/search.mjs +0 -1
- package/packages/cli/src/commands/validate.mjs +1 -3
- package/packages/cli/src/commands/whoami.mjs +34 -0
- package/packages/cli/src/hosted.mjs +159 -0
- package/packages/cli/src/main.mjs +80 -14
- package/packages/cli/src/tool-sources.mjs +272 -0
- package/packages/cli/src/util.mjs +37 -0
- package/packages/engine/lib/credentials.mjs +121 -0
- package/packages/engine/lib/hosted.mjs +119 -0
- package/packages/engine/lib/hub.mjs +376 -24
- package/packages/engine/lib/nango.mjs +157 -0
- package/packages/engine/lib/node.mjs +161 -33
- package/packages/engine/lib/providers.mjs +8 -3
- package/packages/engine/lib/run.mjs +70 -9
- package/packages/engine/lib/text.mjs +5 -0
- package/packages/engine/package.json +8 -2
- package/packages/engine/src/factory-engine.mjs +415 -68
- package/packages/engine/src/flow-sources.mjs +135 -0
- package/packages/engine/src/mcp-client.mjs +429 -0
- package/packages/engine/src/run.mjs +81 -5
- package/packages/engine/src/tool-sources.mjs +566 -0
- package/packages/mcp/package.json +1 -1
- package/packages/mcp/src/server.mjs +47 -17
- package/packages/sdk/package.json +28 -0
- package/packages/sdk/src/index.d.ts +163 -0
- package/packages/sdk/src/index.mjs +266 -0
- package/spec/README.md +7 -1
- package/spec/factory-format.md +264 -19
- package/spec/schema/factory.yaml.json +815 -0
- package/spec/schema/flow.schema.json +24 -2
- package/spec/skill-export.md +3 -0
package/spec/factory-format.md
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
# The factory format, v1alpha1
|
|
2
2
|
|
|
3
3
|
Status: alpha. This document describes the format as the reference engine in
|
|
4
|
-
[`packages/engine`](../packages/engine) reads and runs it at this commit
|
|
4
|
+
[`packages/engine`](../packages/engine) reads and runs it at this commit,
|
|
5
|
+
except the pack v0 additions that
|
|
6
|
+
[section 12](#pack-v0-additions-not-yet-in-the-reference-engine) lists and
|
|
7
|
+
the single-file form of [section 13](#13-the-single-file-form): the format
|
|
8
|
+
defines them, and the reference engine does not implement them yet.
|
|
5
9
|
Changes go through the [RFC process](rfcs/README.md). The key words MUST,
|
|
6
10
|
MUST NOT, SHOULD and MAY are used as in RFC 2119.
|
|
7
11
|
|
|
@@ -24,6 +28,7 @@ Contents:
|
|
|
24
28
|
10. [Companion files](#10-companion-files)
|
|
25
29
|
11. [What the format leaves out](#11-what-the-format-leaves-out)
|
|
26
30
|
12. [JSON Schemas and conformance](#12-json-schemas-and-conformance)
|
|
31
|
+
13. [The single-file form](#13-the-single-file-form)
|
|
27
32
|
|
|
28
33
|
## 1. Files
|
|
29
34
|
|
|
@@ -33,7 +38,8 @@ flow.yaml inputs, steps, who does each, what each needs
|
|
|
33
38
|
agents/<name>/agent.md one file per agent: its role and standing instructions
|
|
34
39
|
```
|
|
35
40
|
|
|
36
|
-
These three are the core. A factory MAY carry companion files.
|
|
41
|
+
These three are the core. A factory MAY carry companion files. The same files
|
|
42
|
+
can also be written as one YAML file ([section 13](#13-the-single-file-form)). Only paths of
|
|
37
43
|
these forms are part of a factory; a runner MUST ignore every other path:
|
|
38
44
|
|
|
39
45
|
| Path | What it is |
|
|
@@ -230,7 +236,7 @@ done:
|
|
|
230
236
|
| Field | Meaning |
|
|
231
237
|
|---|---|
|
|
232
238
|
| `flow` | `mindburn.flow/v1`. Another value is read with a warning |
|
|
233
|
-
| `requires` | execution features the flow depends on: `scoped-context`, `multiple-outputs
|
|
239
|
+
| `requires` | execution features the flow depends on: `scoped-context`, `multiple-outputs`, `blocking-checks` ([5.3](#blocking-checks)). A runner MUST refuse a flow that requires a feature it does not know |
|
|
234
240
|
| `title` | the human title. Default: the name, with hyphens as spaces |
|
|
235
241
|
| `author`, `license`, `time` | text: who wrote it, its license (an SPDX identifier is recommended), how long a run takes |
|
|
236
242
|
| `version` | the factory's version, as text. Quote it: `"1.0.0"`. Default `1.0.0` |
|
|
@@ -287,6 +293,7 @@ input names; write them normalized, such as `check_kit`.
|
|
|
287
293
|
| `checks` | for a `check`: the work or deliver step it reviews |
|
|
288
294
|
| `shows` | for an `approve`: the work or deliver step it shows the person |
|
|
289
295
|
| `rounds` | how often a check or person may send the work back: 0 to 5. Default 1 for a check, 3 for an approval |
|
|
296
|
+
| `on_fail` | for a `check` only: `flag` (default) or `stop`, what happens when the work still fails after its redos ([blocking checks](#blocking-checks)) |
|
|
290
297
|
| `tools` | tools the step may use ([5.5](#55-tools)) |
|
|
291
298
|
| `context` | scoped context ([5.7](#57-scoped-context)) |
|
|
292
299
|
| `criteria` | a list of statements this step's result is held to, in place of `done` |
|
|
@@ -294,7 +301,7 @@ input names; write them normalized, such as `check_kit`.
|
|
|
294
301
|
| Kind | What happens |
|
|
295
302
|
|---|---|
|
|
296
303
|
| `work` | The agent does one job and hands its result on. |
|
|
297
|
-
| `check` | A reviewer judges the result named in `checks` against the criteria in `task`. If it fails, that work goes back to be redone with the reasons, and everything built on it runs again. After the allowed redos the run continues and the receipt says the check failed (`flagged`). A reviewer that returns malformed output gets one format-repair attempt; if that also fails, the result is `unreviewed`, never passed. |
|
|
304
|
+
| `check` | A reviewer judges the result named in `checks` against the criteria in `task`. If it fails, that work goes back to be redone with the reasons, and everything built on it runs again. After the allowed redos the run continues and the receipt says the check failed (`flagged`); with `on_fail: stop` the work is held for the owner instead ([blocking checks](#blocking-checks)). A reviewer that returns malformed output gets one format-repair attempt; if that also fails, the result is `unreviewed`, never passed. |
|
|
298
305
|
| `approve` | The run stops and shows the person the result named in `shows`. They approve; say what to change, and that work is redone; or reject, which ends the run with no result. Nothing else counts as a decision, and no runner makes one for them. |
|
|
299
306
|
| `deliver` | The agent writes the final deliverable. |
|
|
300
307
|
|
|
@@ -303,6 +310,34 @@ is the first step in its `needs` that is earlier work or deliver, otherwise
|
|
|
303
310
|
the last earlier work or deliver step. The subject MUST be work or deliver
|
|
304
311
|
that the step depends on, directly or through other steps.
|
|
305
312
|
|
|
313
|
+
#### Blocking checks
|
|
314
|
+
|
|
315
|
+
Requires `requires: [blocking-checks]`. A `check` that says `on_fail: stop`
|
|
316
|
+
does not let refused work through:
|
|
317
|
+
|
|
318
|
+
- When the work still fails after its redos (`flagged`), or the reviewer gives
|
|
319
|
+
no valid verdict (`unreviewed`), the run **holds** it for the owner
|
|
320
|
+
([section 7](#7-how-a-run-works)). Nothing built on it runs and nothing is
|
|
321
|
+
delivered; steps that do not depend on it finish first. The owner releases
|
|
322
|
+
the work as it is (`release`) or discards it and ends the run (`discard`).
|
|
323
|
+
- A blocking check gates its subject: every step that needs the subject, other
|
|
324
|
+
than another check of it, waits until the check passes or the owner releases
|
|
325
|
+
the work, whether it needs the check or only the subject. A flow in which the
|
|
326
|
+
blocking check itself needs such a step is invalid, as it would wait for
|
|
327
|
+
itself.
|
|
328
|
+
- `on_fail` is allowed only on a `check`, with the value `stop` or `flag`.
|
|
329
|
+
Without it, or with `flag`, the check behaves as described above.
|
|
330
|
+
- A flow with an `on_fail: stop` check MUST declare
|
|
331
|
+
`requires: [blocking-checks]`, so a runner without blocking checks refuses
|
|
332
|
+
the flow ([5.1](#51-top-level-fields)) instead of delivering work its
|
|
333
|
+
checker refused.
|
|
334
|
+
|
|
335
|
+
An agent following the factory without a runner, such as an exported skill,
|
|
336
|
+
gets this text for the check in place of the "carry on" text, word for word:
|
|
337
|
+
|
|
338
|
+
- with `rounds` 1 or more: `If it fails, send it back to be redone <once|up to N times> with the reasons, and redo every step that used it. If it still fails, stop and ask the person; do not deliver. Nothing that uses "<subject title>" starts until this check passes or the person lets the work through.`
|
|
339
|
+
- with `rounds: 0`: `If it fails, do not redo it. Stop and ask the person; do not deliver. Nothing that uses "<subject title>" starts until this check passes or the person lets the work through.`
|
|
340
|
+
|
|
306
341
|
Fields that other harnesses use for tools and connections (`mcp`,
|
|
307
342
|
`mcpServers`, `mcp_servers`, `connectors`, `plugins`, `skills`) are read as
|
|
308
343
|
tools this step needs ([5.5](#55-tools)). Any other unknown field is kept, has
|
|
@@ -394,14 +429,48 @@ composition:
|
|
|
394
429
|
compiler: mindburn.compose/v1
|
|
395
430
|
intent: The person's original request.
|
|
396
431
|
sources:
|
|
397
|
-
- { id: research, name: market-research, version: "1.0.0", sha256: <64 hex> }
|
|
432
|
+
- { id: research, name: market-research, title: Market research, version: "1.0.0", sha256: <64 hex> }
|
|
398
433
|
unmetCapabilities: []
|
|
399
434
|
```
|
|
400
435
|
|
|
401
|
-
All four fields are required and nothing else is allowed.
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
436
|
+
All four fields are required and nothing else is allowed. Each source has
|
|
437
|
+
`id`, `name`, `version` and `sha256`, and MAY have `title`, the member
|
|
438
|
+
factory's title, at most 120 characters. `composeFactories` in
|
|
439
|
+
[`compose.mjs`](../packages/engine/src/compose.mjs) produces these factories
|
|
440
|
+
from members pinned by hash; the result is an ordinary factory and needs no
|
|
441
|
+
registry to run. A source hash establishes identity, not trust, and a
|
|
442
|
+
`composition` block is text anyone can write: a runner names the members of a
|
|
443
|
+
run in its receipt only for a composition it compiled itself
|
|
444
|
+
([section 8](#8-receipts)).
|
|
445
|
+
|
|
446
|
+
Each member's steps run under the member's id (member `posts`, step `write`
|
|
447
|
+
runs as `posts_write`). A compiler:
|
|
448
|
+
|
|
449
|
+
- refuses member ids where one begins with another followed by `_`, so every
|
|
450
|
+
step belongs to exactly one member;
|
|
451
|
+
- keeps a member check's `on_fail`, and adds `blocking-checks` to `requires`
|
|
452
|
+
when any member check says `on_fail: stop`;
|
|
453
|
+
- MAY take `maxCalls`, a positive whole number, and then refuses a
|
|
454
|
+
composition whose worst-case run needs more model calls (`worstCaseCalls`).
|
|
455
|
+
It returns `worstCaseCalls` with the result. The worst case counts the
|
|
456
|
+
calls one run can make: a work or deliver step with tools may take every
|
|
457
|
+
model turn (8 in the reference runner), one without tools makes one call; a
|
|
458
|
+
check makes two, its verdict and one format repair; an approval makes none.
|
|
459
|
+
Each check or approval may send its subject back as often as its `rounds`
|
|
460
|
+
allow, and each time the subject, the sender and every step built on the
|
|
461
|
+
subject that does not wait for the sender run again.
|
|
462
|
+
|
|
463
|
+
A member MAY carry `rounds: { <step>: <n> }`, with the member's own step
|
|
464
|
+
names. It lowers the revision rounds of its own check or approve steps in the
|
|
465
|
+
composed flow, so a composition fits `maxCalls` without changing the member.
|
|
466
|
+
The compiler refuses something other than a map, a step that is not one of
|
|
467
|
+
the member's checks or approvals, and a fraction, a negative number or more
|
|
468
|
+
rounds than the step has. The member's pin is unchanged.
|
|
469
|
+
|
|
470
|
+
A member's `mindburn.tests.yaml` tests that member alone, so the compiler
|
|
471
|
+
leaves it out of the composed factory. The member's pin stays the bundle hash
|
|
472
|
+
of all its files, the tests file included. Any other file the compiler cannot
|
|
473
|
+
compile is refused.
|
|
405
474
|
|
|
406
475
|
### 5.10 Limits
|
|
407
476
|
|
|
@@ -456,14 +525,30 @@ run; an agent can follow its foreman.
|
|
|
456
525
|
differs for every occurrence, so a delayed decision cannot land on text that
|
|
457
526
|
changed since or on a later review of the same text. With no decision the
|
|
458
527
|
runner returns the run still waiting.
|
|
459
|
-
6. A
|
|
528
|
+
6. A [blocking check](#blocking-checks) that holds work makes the run wait the
|
|
529
|
+
same way, once nothing else can run, with
|
|
530
|
+
`approval: { kind: "blocked", step, title, artifact, artifact_sha256, ask, issues, note, choices: ["release", "discard"], id, revisionsLeft: 0 }`.
|
|
531
|
+
The only answers are `release` and `discard`, with `seen` and the
|
|
532
|
+
approval's id as above; `approve`, `revise` and `reject` are refused at a
|
|
533
|
+
hold, and `release` and `discard` at an approval. `release` lets the run go
|
|
534
|
+
on and the receipt flags the release. `discard` ends the run as `stopped`
|
|
535
|
+
with nothing delivered. A release answers one attempt of its check: when the
|
|
536
|
+
work is redone and the check runs again, the new verdict stands. A runner
|
|
537
|
+
never delivers a run whose blocking check refused work the owner did not
|
|
538
|
+
release; such a run fails instead. An agent app acting for the owner is
|
|
539
|
+
shown the hold's `artifact_sha256` and `issues`, never the held text, and
|
|
540
|
+
cannot release or discard it.
|
|
541
|
+
7. A provider answer that is truncated, incomplete, or asks for a tool the
|
|
460
542
|
step was not offered stops the run with a reason. Failed page reads, missing
|
|
461
543
|
search and partial pages are recorded as limitations when usable work
|
|
462
544
|
continues.
|
|
463
|
-
|
|
464
|
-
searches and 8 model turns per step, 14,000 characters of text per page
|
|
465
|
-
|
|
466
|
-
|
|
545
|
+
8. The reference runner's budgets: 60 model calls and 20 page reads per run, 4
|
|
546
|
+
searches and 8 model turns per step, 14,000 characters of text per page,
|
|
547
|
+
read from at most 1,500,000 bytes of a text, HTML, XML or JSON page.
|
|
548
|
+
9. A finished run ends with the deliverable and a [receipt](#8-receipts). A
|
|
549
|
+
run that was rejected at a decision has no deliverable and no receipt. A
|
|
550
|
+
run whose owner discarded held work has no deliverable and a receipt whose
|
|
551
|
+
`outcome` says so.
|
|
467
552
|
|
|
468
553
|
A repeated run follows the same declared workflow; model outputs can differ.
|
|
469
554
|
|
|
@@ -478,11 +563,41 @@ A completed run produces a receipt (`kind: factory-run-receipt`, `v: 2`):
|
|
|
478
563
|
| `inputs_sha256` | hash of the canonical JSON of the accepted inputs |
|
|
479
564
|
| `runner` | mode, provider and model |
|
|
480
565
|
| `started`, `finished` | ISO 8601 times |
|
|
481
|
-
| `steps` | every step attempt: status, tools used and targets, verdicts, limitations, decisions with `seen_sha256` and `
|
|
482
|
-
| `flags` | what the person should know: failed checks, unreviewed results, limitations |
|
|
566
|
+
| `steps` | every step attempt: status, tools used and targets, verdicts, limitations, decisions with `seen_sha256`, `approval_id` and `decided_by`, a check's `on_fail`, `output_sha256`; for reviews, the target hash, reviewer provider and model, input and evidence hashes and the request hash |
|
|
567
|
+
| `flags` | what the person should know: failed checks, unreviewed results, limitations, released holds |
|
|
483
568
|
| `outputs` | with declared outputs: each output's hash and review |
|
|
484
|
-
| `
|
|
485
|
-
| `
|
|
569
|
+
| `members` | for a composition the runner compiled itself: one entry per member (below) |
|
|
570
|
+
| `outcome` | for a run whose owner discarded held work: `{ status: "blocked", by: "owner", step, target, decision: "discard", at, decided_by }` |
|
|
571
|
+
| `deliverable_review` | `passed`, `limited` (a passing review with missing evidence), `flagged`, `unreviewed` or `not_checked`, for the delivered bytes; `flagged` whenever a release of held work is in effect, whatever a later check says; `not_delivered`, with `sha256: null` and no checks, when the owner discarded held work |
|
|
572
|
+
| `deliverable_sha256`, `usage` | hash of the deliverable, `null` when nothing was delivered; model calls and tokens. Each entry of `usage.metering.calls` names the `step` it was made for |
|
|
573
|
+
|
|
574
|
+
**Decisions.** Every decision record (an approval, and the owner's answer to
|
|
575
|
+
a hold) carries `decided_by: { account, surface }`. `account` is a stable,
|
|
576
|
+
salted hash of the deciding account, never its id, or `null` when no account
|
|
577
|
+
stands behind the decision (a run key). `surface` is how the decision arrived:
|
|
578
|
+
`web`, `mcp`, `a2a`, `email` or `api`. It is a label taken from the request,
|
|
579
|
+
not proof of the channel; who had authority is `account`. No handle or name is
|
|
580
|
+
signed: a reader looks up who an account is while it exists.
|
|
581
|
+
|
|
582
|
+
**Holds.** The owner's answer to a [blocking check](#blocking-checks) is a
|
|
583
|
+
step of `kind: hold`: `{ status: released | discarded, decision, target, seen_sha256, approval_id, decided_by }`,
|
|
584
|
+
kept apart from the check record it answers, which keeps its `flagged` or
|
|
585
|
+
`unreviewed` status.
|
|
586
|
+
|
|
587
|
+
**Members.** A runner adds `members` only for a composition it compiled
|
|
588
|
+
itself, from the sources it hashed, and never from a bundle's own
|
|
589
|
+
`composition` block, which anyone can write. Each entry, in compile order:
|
|
590
|
+
`{ id, name, title, version, source_sha256, status, steps, send_backs, released, usage }`.
|
|
591
|
+
`title` is at most 120 characters; `steps` are the member's namespaced step
|
|
592
|
+
ids; `send_backs` counts its check records that read `sent_back`; `released`
|
|
593
|
+
is true when the owner released work one of its blocking checks refused and
|
|
594
|
+
that check has not run again since; `usage` has the shape of a run's `usage`,
|
|
595
|
+
holding the calls made for its steps. A receipt's `status` is `done`,
|
|
596
|
+
`blocked` (held work, discarded or left held when the run ended), `failed`,
|
|
597
|
+
`stopped` or `skipped`; a runner's live view MAY also show `pending`,
|
|
598
|
+
`running` and `waiting`. Receipts keep counters, not prices.
|
|
599
|
+
|
|
600
|
+
A discarded run's receipt verifies no result: check only its signature.
|
|
486
601
|
|
|
487
602
|
A runner MAY sign a receipt: `signature: { key_id, sig }`, an Ed25519
|
|
488
603
|
signature (base64url) over the canonical JSON of the receipt without its
|
|
@@ -601,6 +716,10 @@ engine on the fixtures in [`fixtures/`](fixtures):
|
|
|
601
716
|
- `semantic/`: the schemas accept them and the engine rejects them, by a rule
|
|
602
717
|
of [section 6](#6-validity-and-runnability) that a per-file schema cannot
|
|
603
718
|
express, such as a missing agent file or a circle of steps.
|
|
719
|
+
- `unimplemented/`: the schemas accept them and the engine refuses them,
|
|
720
|
+
because they require an execution feature it does not implement yet
|
|
721
|
+
(`blocking-checks`). A runner MUST refuse such a flow
|
|
722
|
+
([5.1](#51-top-level-fields)); the test checks that this is the only reason.
|
|
604
723
|
- `lenient/`: the engine accepts them and the schemas reject them. The engine
|
|
605
724
|
converts or ignores values the format does not define. The fixtures cover:
|
|
606
725
|
an uppercase `kind`; an unknown input `type` (read as `text`); a number
|
|
@@ -609,13 +728,139 @@ engine on the fixtures in [`fixtures/`](fixtures):
|
|
|
609
728
|
warning); `rounds` outside 0 to 5 (clamped); an uppercase `agent` (read in
|
|
610
729
|
lowercase); `checks` on a `work` step (ignored); a `done` item that YAML
|
|
611
730
|
reads as a map (joined into text); an input given as plain text (read as
|
|
612
|
-
its help); step names that are not written normalized
|
|
731
|
+
its help); step names that are not written normalized; `on_fail: stop`
|
|
732
|
+
without `requires: [blocking-checks]` (the engine at this commit ignores
|
|
733
|
+
`on_fail` with a warning; it will reject this once it implements blocking
|
|
734
|
+
checks). The engine also
|
|
613
735
|
accepts, without fixtures here, non-boolean `required` and `optional`,
|
|
614
736
|
non-integer `rounds` (the default is used), and scalars where
|
|
615
737
|
`repositories`, `agentDefaults`, `author` or `tags` items belong. Authors
|
|
616
738
|
SHOULD NOT rely on any of these; a future version may reject them.
|
|
617
739
|
|
|
740
|
+
[`schema/factory.yaml.json`](schema/factory.yaml.json) (JSON Schema draft-07)
|
|
741
|
+
describes the single-file form of [section 13](#13-the-single-file-form); its
|
|
742
|
+
fixtures and test are listed there.
|
|
743
|
+
|
|
618
744
|
A conforming factory validates against both schemas and passes the rules of
|
|
619
745
|
[section 6](#6-validity-and-runnability). The engine is the reference: where
|
|
620
746
|
this document and the engine disagree, that is a bug in one of them, and an
|
|
621
747
|
issue is welcome.
|
|
748
|
+
|
|
749
|
+
### Pack v0 additions not yet in the reference engine
|
|
750
|
+
|
|
751
|
+
The format defines these, and the engine and CLI at this commit do not
|
|
752
|
+
implement them yet:
|
|
753
|
+
|
|
754
|
+
- [blocking checks](#blocking-checks): `on_fail`, `requires: [blocking-checks]`,
|
|
755
|
+
the gate on the subject, holds and their answers (section 7, item 6), and the
|
|
756
|
+
export text. The engine refuses a flow that requires `blocking-checks`, as
|
|
757
|
+
5.1 requires, and ignores `on_fail` elsewhere with a warning;
|
|
758
|
+
- in [5.9](#59-composition): recording `title`, the nested member-id refusal,
|
|
759
|
+
carrying `on_fail`, `maxCalls`, `worstCaseCalls`, a member's `rounds` and
|
|
760
|
+
leaving out a member's tests file;
|
|
761
|
+
- in [section 8](#8-receipts): `members`, `outcome`, `decided_by`, `on_fail`,
|
|
762
|
+
`kind: hold`, `deliverable_review.status: not_delivered`, the `flagged`
|
|
763
|
+
status for a release in effect, and `usage.metering.calls[].step`.
|
|
764
|
+
|
|
765
|
+
The schemas already describe the new fields: `on_fail` (only on a `check`,
|
|
766
|
+
`stop` or `flag`), `blocking-checks` in `requires` (required by any
|
|
767
|
+
`on_fail: stop` check), and `title` (at most 120 characters) in a composition
|
|
768
|
+
source.
|
|
769
|
+
|
|
770
|
+
[RFC 0020](rfcs/0020-pack-v0.md) is where these additions are discussed and
|
|
771
|
+
decided. It also proposes who paid for a run and for each call (`funding`,
|
|
772
|
+
`payer`), which this document does not define until the RFC settles them.
|
|
773
|
+
|
|
774
|
+
## 13. The single-file form
|
|
775
|
+
|
|
776
|
+
Proposed in [RFC 0023](rfcs/0023-single-file-factory.md), a draft, which
|
|
777
|
+
gives the full rules. The reference engine and CLI at this commit do not read
|
|
778
|
+
this form yet: `factoryhub validate` and `factoryhub run` read factory folders
|
|
779
|
+
and bundle `.json` files, and `factoryhub push` refuses a single file.
|
|
780
|
+
|
|
781
|
+
A whole factory MAY be written as one YAML file, `factory.yaml`, with
|
|
782
|
+
`format: mindburn.factory.yaml/v1` on a line of its own. Each top-level
|
|
783
|
+
section is one file of the bundle, and its text is that file's exact bytes:
|
|
784
|
+
|
|
785
|
+
```yaml
|
|
786
|
+
# yaml-language-server: $schema=https://raw.githubusercontent.com/Mindburn-Labs/factoryhub/main/spec/schema/factory.yaml.json
|
|
787
|
+
format: mindburn.factory.yaml/v1
|
|
788
|
+
|
|
789
|
+
factory:
|
|
790
|
+
schemaVersion: v1alpha1
|
|
791
|
+
name: one-step-summary
|
|
792
|
+
description: Writes a three-sentence summary of the text you give it.
|
|
793
|
+
|
|
794
|
+
flow:
|
|
795
|
+
flow: mindburn.flow/v1
|
|
796
|
+
inputs:
|
|
797
|
+
text:
|
|
798
|
+
type: longtext
|
|
799
|
+
help: The text to summarise.
|
|
800
|
+
steps:
|
|
801
|
+
summary:
|
|
802
|
+
agent: writer
|
|
803
|
+
task: Summarise the text in three sentences.
|
|
804
|
+
|
|
805
|
+
agents:
|
|
806
|
+
writer:
|
|
807
|
+
description: Writes plain summaries.
|
|
808
|
+
instructions: |
|
|
809
|
+
You write short, plain summaries. You add nothing the text does not say.
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
| Section | Bundle file |
|
|
813
|
+
|---|---|
|
|
814
|
+
| `format` | none; required, `mindburn.factory.yaml/v1` |
|
|
815
|
+
| `factory`, `flow` | `factory.yaml`, `flow.yaml` |
|
|
816
|
+
| `agents` | `agents/<name>/agent.md`, one entry per agent: its settings, then `instructions: \|` |
|
|
817
|
+
| `tests`, `requirements`, `package` | `mindburn.tests.yaml`, `mindburn.requirements.yaml`, `mindburn.package.yaml` |
|
|
818
|
+
| `samples` | `examples/<path>`, one entry per file |
|
|
819
|
+
| `files` | every other file, by its path |
|
|
820
|
+
|
|
821
|
+
- **Sections are files.** The lines of a YAML section, less two spaces of
|
|
822
|
+
indent, are its file, plus one final line break; comments and formatting
|
|
823
|
+
inside a section are the file's own bytes. An agent entry is its
|
|
824
|
+
frontmatter settings, then its body under `instructions: |` (or `|-` for no
|
|
825
|
+
final line break). A file a block cannot carry byte for byte is one JSON
|
|
826
|
+
string, its exact text, on its key's line.
|
|
827
|
+
- **The coordinator.** A writer leaves out `agents/foreman/agent.md` while it
|
|
828
|
+
is exactly what the engine writes from the flow (`withForeman`), and a
|
|
829
|
+
reader writes it again. An authored or stale foreman is kept as written;
|
|
830
|
+
`foreman: ~` says the bundle has none.
|
|
831
|
+
- **Presentation.** Comments and blank lines between sections, section order,
|
|
832
|
+
comments on a section's own line and top-level `x-` keys are no file's
|
|
833
|
+
content. They never change the bundle or its hash.
|
|
834
|
+
- **Unknown keys.** Any other unknown top-level key is an error at its line,
|
|
835
|
+
never dropped. Inside a section every key is kept byte for byte, whether a
|
|
836
|
+
runner reads it or not; `requires` gates features exactly as in
|
|
837
|
+
[5.1](#51-top-level-fields).
|
|
838
|
+
- **Identity.** A single file is a view of its bundle. Its hash is the
|
|
839
|
+
[bundle hash](#9-identity-and-the-transfer-bundle) of the bundle it expands
|
|
840
|
+
to; no byte outside the files counts. Writing a bundle as one file and
|
|
841
|
+
reading it back MUST give the same bundle.
|
|
842
|
+
- **Size.** A file in `samples` or `files` over 32 KiB (32,768 UTF-8 bytes)
|
|
843
|
+
MAY be written as a reference, `{ sha256: "<64 hex>", bytes: <n> }`: the
|
|
844
|
+
same file of the version the text came from. A reader resolves it only
|
|
845
|
+
against that version, and an editor shows it read-only. The bundle the file
|
|
846
|
+
expands to keeps the limits of [section 9](#9-identity-and-the-transfer-bundle).
|
|
847
|
+
- **Versions.** `format` versions the layout; `schemaVersion` and `flow` keep
|
|
848
|
+
versioning their files. A reader MUST refuse a `format` it does not know.
|
|
849
|
+
A file with a line `format: mindburn.factory.yaml/v1` at column 1 is a
|
|
850
|
+
single file, not a bundle's `factory.yaml`.
|
|
851
|
+
|
|
852
|
+
[`schema/factory.yaml.json`](schema/factory.yaml.json) (draft-07) gives
|
|
853
|
+
editors completion, hover text and errors. It is open wherever a file is and
|
|
854
|
+
does not decide validity, which the reader and
|
|
855
|
+
[section 6](#6-validity-and-runnability) do. Its `$id`,
|
|
856
|
+
`https://factory.mindburn.org/schemas/factory.yaml.json`, is its stable
|
|
857
|
+
address on the factoryhub site, which generates the same document. That site
|
|
858
|
+
is in private preview, so point editors at this repository's copy, as the
|
|
859
|
+
example's first line does ([editor setup](../docs/editor-setup.md)).
|
|
860
|
+
|
|
861
|
+
[`fixtures/single-file/`](fixtures/single-file) holds `valid/` (the schema
|
|
862
|
+
accepts them and each is a valid factory; two are house factories, equal to
|
|
863
|
+
their folders byte for byte), `invalid/` (the schema rejects each at the place
|
|
864
|
+
it names) and `reader/` (the schema accepts them, and the rules above reject
|
|
865
|
+
them). [`test/single-file.test.mjs`](test/single-file.test.mjs) checks them,
|
|
866
|
+
and checks the reference engine against them once it reads this form.
|