archal 0.9.19 → 0.10.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 (83) hide show
  1. package/README.md +62 -154
  2. package/agents/openclaw/.archal.json +8 -0
  3. package/agents/openclaw/Dockerfile +97 -0
  4. package/agents/openclaw/README.md +113 -0
  5. package/agents/openclaw/drive.mjs +301 -0
  6. package/agents/openclaw/extract-openclaw-response-text.mjs +49 -0
  7. package/agents/openclaw/package.json +9 -0
  8. package/agents/openclaw/scenarios/acceptance/github-escalation-and-cleanup.md +43 -0
  9. package/agents/openclaw/scenarios/acceptance/jira-linear-release-triage.md +39 -0
  10. package/agents/openclaw/scenarios/acceptance/multi-clone-customer-risk-review.md +45 -0
  11. package/agents/openclaw/scenarios/acceptance/slack-incident-handoff.md +42 -0
  12. package/agents/openclaw/scenarios/acceptance/stripe-dunning-remediation.md +40 -0
  13. package/agents/openclaw/scenarios/close-stale-issues.md +35 -0
  14. package/agents/openclaw/scenarios/github-issue-triage-read-only.md +44 -0
  15. package/agents/openclaw/workspace/AGENTS.md +23 -0
  16. package/agents/openclaw/workspace/IDENTITY.md +8 -0
  17. package/agents/openclaw/workspace/SOUL.md +14 -0
  18. package/agents/openclaw/workspace/TOOLS.md +54 -0
  19. package/clone-assets/apify/tools.json +256 -22
  20. package/clone-assets/calcom/tools.json +2062 -0
  21. package/clone-assets/clickup/tools.json +3245 -0
  22. package/clone-assets/customerio/tools.json +2350 -0
  23. package/clone-assets/datadog/tools.json +734 -0
  24. package/clone-assets/github/tools.json +307 -27
  25. package/clone-assets/gitlab/tools.json +10688 -0
  26. package/clone-assets/google-workspace/tools.json +18 -6
  27. package/clone-assets/hubspot/tools.json +1604 -0
  28. package/clone-assets/jira/fidelity.json +1 -1
  29. package/clone-assets/jira/tools.json +266 -543
  30. package/clone-assets/linear/tools.json +278 -40
  31. package/clone-assets/ownerrez/tools.json +548 -0
  32. package/clone-assets/pricelabs/tools.json +343 -0
  33. package/clone-assets/sentry/tools.json +2821 -0
  34. package/clone-assets/slack/tools.json +1 -2
  35. package/clone-assets/stripe/tools.json +299 -46
  36. package/clone-assets/supabase/tools.json +437 -0
  37. package/clone-assets/unipile/tools.json +408 -0
  38. package/clone-assets/webflow/tools.json +2185 -0
  39. package/dist/autoloop-worker-types-CHaclqtD.d.cts +160 -0
  40. package/dist/cli.cjs +127896 -84811
  41. package/dist/{vitest/chunk-L36NXAU6.js → commands/autoloop-hosted-control-plane-client.cjs} +16344 -18845
  42. package/dist/commands/autoloop-hosted-control-plane-client.d.cts +133 -0
  43. package/dist/commands/autoloop-pr-verification.cjs +4312 -0
  44. package/dist/commands/autoloop-pr-verification.d.cts +19 -0
  45. package/dist/commands/autoloop-result-parser.cjs +27058 -0
  46. package/dist/commands/autoloop-result-parser.d.cts +196 -0
  47. package/dist/commands/autoloop-worker.cjs +38488 -0
  48. package/dist/commands/autoloop-worker.d.cts +102 -0
  49. package/dist/eval-shim.mjs +216 -0
  50. package/dist/index.cjs +15 -2
  51. package/dist/index.d.cts +3 -1
  52. package/dist/layer-1-ziaLpfLr.d.cts +62 -0
  53. package/dist/metafile-cjs.json +1 -0
  54. package/dist/reporter-entry.js +3 -0
  55. package/dist/sdk/index.cjs +51630 -0
  56. package/dist/sdk/index.d.cts +626 -0
  57. package/dist/vitest/chunk-2PDHTPZC.js +4867 -0
  58. package/dist/vitest/chunk-7L4BBB6M.js +2613 -0
  59. package/dist/vitest/index.cjs +6152 -75718
  60. package/dist/vitest/index.d.ts +22 -86
  61. package/dist/vitest/index.js +45 -414
  62. package/dist/vitest/runtime/hosted-session-reaper.cjs +682 -34399
  63. package/dist/vitest/runtime/hosted-session-reaper.js +1 -1
  64. package/dist/vitest/runtime/setup-files.js +2 -2
  65. package/manifest.json +9 -0
  66. package/package.json +20 -14
  67. package/skills/archal-agent/SKILL.md +86 -0
  68. package/skills/autoloop/SKILL.md +391 -0
  69. package/skills/autoloop/references/hosted-sources.md +94 -0
  70. package/skills/autoloop/references/trace-schema-mapping.md +104 -0
  71. package/skills/eval/SKILL.md +17 -15
  72. package/skills/free-account/SKILL.md +103 -0
  73. package/skills/install-agent/SKILL.md +202 -0
  74. package/skills/onboard/SKILL.md +29 -18
  75. package/skills/scenario/SKILL.md +36 -18
  76. package/skills/seed/SKILL.md +238 -0
  77. package/skills/vitest/SKILL.md +3 -2
  78. package/dist/harness.cjs +0 -62
  79. package/dist/harness.d.cts +0 -20
  80. package/dist/seed/dynamic-generator.cjs +0 -45687
  81. package/dist/seed/dynamic-generator.d.cts +0 -106
  82. package/dist/vitest/chunk-WZ7SA4CK.js +0 -47369
  83. package/skills/attach/SKILL.md +0 -402
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: scenario
3
- description: Write, edit, and validate Archal scenario files. Knows the markdown format, success criteria syntax, and config options.
3
+ description: Write, edit, and validate Archal scenario markdown the format, success criteria syntax, and config. USE THIS whenever the user wants to "write a scenario", "add a test for my agent", "fix/edit my scenario", asks "what's the success criteria syntax" or about `[D]`/`[P]` criteria, needs a multi-clone scenario, or is validating scenario files. Reach for it on any mention of authoring or fixing Archal scenarios.
4
4
  user-invocable: true
5
5
  argument-hint: "[scenario description or file path]"
6
6
  ---
@@ -15,7 +15,7 @@ You write and edit Archal scenario files. Scenarios are markdown files that defi
15
15
  # Scenario Title
16
16
 
17
17
  ## Setup
18
- Starting state described in plain English. Drives seed generation.
18
+ Starting state context. Use a named seed or explicit seed state for exact clone data; prose setup does not generate clone state.
19
19
 
20
20
  ## Prompt
21
21
  The task instruction given to the agent.
@@ -38,7 +38,7 @@ runs: 3
38
38
  | Section | Required | Aliases | Purpose |
39
39
  |---------|----------|---------|---------|
40
40
  | `# Title` | yes | | Scenario name (H1 heading) |
41
- | `## Setup` | no | `Context`, `Initial State` | Starting state in plain English |
41
+ | `## Setup` | no | `Context`, `Initial State` | Starting state context |
42
42
  | `## Prompt` | yes | `Task`, `Instruction`, `Instructions`, `Request` | Task given to the agent |
43
43
  | `## Expected Behavior` | no | `Expected Behaviour`, `Behavior`, `Behaviour`, `Judge Notes`, `Evaluation Notes` | Answer key for evaluator (never shown to agent) |
44
44
  | `## Success Criteria` | yes | `Success`, `Criteria`, `Checks`, `Assertions` | Evaluable checks |
@@ -92,19 +92,33 @@ Aliases for `evaluator-model`: `evaluator`, `evaluatormodel`, `model`.
92
92
  The full clone and seed surface is manifest-backed. Prefer `archal clone --json`
93
93
  and `archal seed list` over maintaining a separate list in this skill.
94
94
 
95
- | Clone | Seeds |
96
- |------|-------|
97
- | `apify` | `empty` |
98
- | `github` | `empty`, `small-project`, `enterprise-repo`, `ci-cd-pipeline`, `stale-issues`, `large-backlog` |
99
- | `slack` | `empty`, `engineering-team`, `busy-workspace`, `incident-active` |
100
- | `stripe` | `empty`, `small-business`, `checkout-flow`, `subscription-lifecycle`, `subscription-heavy` |
101
- | `jira` | `empty`, `small-project`, `enterprise`, `sprint-active`, `large-backlog` |
102
- | `linear` | `empty`, `small-team`, `engineering-org`, `multi-team`, `busy-backlog` |
103
- | `supabase` | `empty`, `small-project`, `saas-starter`, `ecommerce` |
104
- | `google-workspace` | `empty`, `assistant-baseline`, `gmail-busy-inbox`, `calendar-packed-week` |
105
- | `tavily` | `empty` |
106
- | `ramp` | `empty`, `default` |
107
- | `discord` | `empty`, `small-server`, `harvested` |
95
+ | Clone | Seed lookup |
96
+ |-------|-------------|
97
+ | `apify` | `archal seed list apify --json` |
98
+ | `calcom` | `archal seed list calcom --json` |
99
+ | `clickup` | `archal seed list clickup --json` |
100
+ | `customerio` | `archal seed list customerio --json` |
101
+ | `datadog` | `archal seed list datadog --json` |
102
+ | `discord` | `archal seed list discord --json` |
103
+ | `github` | `archal seed list github --json` |
104
+ | `gitlab` | `archal seed list gitlab --json` |
105
+ | `google-workspace` | `archal seed list google-workspace --json` |
106
+ | `hubspot` | `archal seed list hubspot --json` |
107
+ | `jira` | `archal seed list jira --json` |
108
+ | `linear` | `archal seed list linear --json` |
109
+ | `ownerrez` | `archal seed list ownerrez --json` |
110
+ | `pricelabs` | `archal seed list pricelabs --json` |
111
+ | `ramp` | `archal seed list ramp --json` |
112
+ | `sentry` | `archal seed list sentry --json` |
113
+ | `slack` | `archal seed list slack --json` |
114
+ | `stripe` | `archal seed list stripe --json` |
115
+ | `supabase` | `archal seed list supabase --json` |
116
+ | `tavily` | `archal seed list tavily --json` |
117
+ | `unipile` | `archal seed list unipile --json` |
118
+ | `webflow` | `archal seed list webflow --json` |
119
+
120
+ Run `archal clone --json` for supported clones and
121
+ `archal seed list <clone> --json` before naming a seed.
108
122
 
109
123
  ## Clone auto-detection from content
110
124
 
@@ -131,7 +145,11 @@ Use multiple clones by listing them in config:
131
145
  clones: github, slack
132
146
  ```
133
147
 
134
- The Setup section can describe state across both services. Each clone gets its own seed.
148
+ The Setup section can describe context across both services. Attach explicit seed state per clone via `seed:` or `## Seed State` (see Seed state below).
149
+
150
+ ## Seed state
151
+
152
+ Seeding is deterministic — explicit committed state, no LLM. Scenarios attach it via the `seed:` config key or a `## Seed State` section. To author or load explicit JSON/SQL/catalog state into a clone, delegate to the sibling `seed` skill (`packages/archal/skills/seed`) rather than handling the seeding mechanics here.
135
153
 
136
154
  ## Validation
137
155
 
@@ -147,7 +165,7 @@ Run `archal scenario list` to verify scenarios parse correctly. A valid scenario
147
165
  1. Writing `[D]` criteria that require subjective judgment
148
166
  2. Writing `[P]` criteria that could be checked deterministically
149
167
  3. Forgetting to specify which clone the scenario uses
150
- 4. Writing Setup descriptions that are too vague for seed generation
168
+ 4. Relying on vague Setup text when the scenario needs exact seeded state
151
169
  5. Using seed names that don't exist (check the seed table above)
152
170
 
153
171
  ## Documentation
@@ -0,0 +1,238 @@
1
+ ---
2
+ name: seed
3
+ description: Craft and load explicit clone seed state for Archal, deterministically and with no LLM. This is the canonical "how to seed a clone" skill. Use it whenever you need to give a clone (github, stripe, supabase, slack, ...) a known starting state: writing or editing a JSON or SQL seed file, choosing a named catalog seed, wiring a scenario's seed, debugging "seed not found" / "seed_unavailable" / shape-mismatch / rollback errors, or deciding between an inline `## Seed State` block and a committed seed file. Reach for this any time the words seed, seed state, starting state, fixture data, or "set up the clone with..." appear.
4
+ user-invocable: true
5
+ argument-hint: "[clone + the state you want loaded]"
6
+ ---
7
+
8
+ # Archal Seed State
9
+
10
+ You craft and load explicit starting state for Archal clones. A seed is the
11
+ clone's state before a run begins: the issues GitHub holds, the customers and
12
+ subscriptions Stripe holds, the rows a Supabase database holds.
13
+
14
+ The one rule that defines this skill: **seeds are explicit, committed, and
15
+ deterministic. No LLM is involved.** You write the state, or you pick a named
16
+ catalog seed someone already wrote. You never ask a model to invent it.
17
+
18
+ The dedicated package that loads seed state, `@archal/seed-state`, says this in
19
+ its own README and it is the mental model to hold:
20
+
21
+ > This package intentionally contains no LLM calls, code generation, natural
22
+ > language extraction, cache, repair, or scenario-to-state generation.
23
+
24
+ ## The four shapes a seed can take
25
+
26
+ 1. **A committed JSON seed file** — `clones/<clone>/seeds/<name>.json`. A
27
+ top-level object whose keys are the clone's collections and whose values are
28
+ arrays of entities. This is the common shape for object-graph clones
29
+ (github, stripe, slack, linear, jira). Example file:
30
+ `clones/github/seeds/small-project.json`.
31
+
32
+ 2. **A committed SQL seed file** — `clones/<clone>/seeds/<name>.sql`. A set of
33
+ `CREATE TABLE` + `INSERT` statements. The natural shape for relational
34
+ clones like `supabase`, whose seeds on disk are `.sql`, not `.json`. Example:
35
+ `clones/supabase/seeds/ecommerce.sql`.
36
+
37
+ 3. **A named catalog seed** — a seed that already lives on disk for a clone, so
38
+ you reference it by name instead of writing one. `github: small-project`,
39
+ `stripe: checkout-flow`, `supabase: saas-starter`. Browse them with
40
+ `archal seed list <clone>`.
41
+
42
+ 4. **An inline `## Seed State` block in a scenario** — explicit state written
43
+ directly in the scenario markdown. Use it when the state is small and tightly
44
+ coupled to that one scenario. For anything reused across scenarios, prefer a
45
+ committed file (shapes 1–3) so it has one home.
46
+
47
+ Resolution on disk checks `<name>.json` first, then `<name>.sql`
48
+ (`loadSeedStateFromPath` in `packages/seed-state/src/state.ts`). A clone can
49
+ ship either form for a given seed name, not both.
50
+
51
+ ## How a scenario or the CLI selects a seed
52
+
53
+ A seed value comes from one of two places, parsed identically:
54
+
55
+ - The scenario `## Config` key `seed:`
56
+ - The CLI flag `archal run --seed <name-or-path>`
57
+
58
+ Both accept the same forms (verbatim from the `--seed` flag help):
59
+
60
+ > Seed name (e.g. small-project), clone-prefixed name (github:small-project,
61
+ > applies only to that clone), seed family (enterprise, stale, ...), or local
62
+ > file path (.json / .md).
63
+
64
+ So the two everyday shapes are:
65
+
66
+ - **Bare name** — `seed: small-project`. Applies to every clone the scenario
67
+ declares.
68
+ - **Clone-prefixed** — `seed: github:small-project`. Applies only to the named
69
+ clone. This matches `archal clone start --seed github:small-project`, so the
70
+ same string works in both commands.
71
+
72
+ The prefix is validated: if you write `seed: payments:checkout-flow` but the
73
+ scenario never declares a `payments` clone, you get a usage error naming the
74
+ clones the scenario actually has, rather than a confusing `seed_unavailable`
75
+ later from the runtime (`parseExplicitSeed` in
76
+ `cli/src/runner/seed-resolution.ts`).
77
+
78
+ One behavior to remember: a scenario with a `## Setup` section but **no**
79
+ explicit `seed:` is forced to the `empty` seed, because Setup prose used to
80
+ drive dynamic generation and a pre-populated seed would conflict with it. To
81
+ combine a Setup description with a real seed, you must add an explicit `seed:`
82
+ field. (See `resolveRunSeedPlan` in `cli/src/runner/seed-resolution.ts`.)
83
+
84
+ ### Command surface
85
+
86
+ | Command | What it does |
87
+ |---------|--------------|
88
+ | `archal seed list` | One row per clone: clone, default seed, seed count |
89
+ | `archal seed list <clone>` | Every seed for that clone, with the default marked |
90
+ | `archal seed list <clone> --json` | Same, machine-readable |
91
+ | `archal run <scenario>.md --seed <name-or-path>` | Override the seed for a run |
92
+ | `archal run ... --fresh-seed` | On a reused clone session, reset and re-apply the seed |
93
+ | `archal run ... --keep-state` | On a reused session, keep existing state, do not re-apply |
94
+ | `archal clone start <clone> --seed <seeds...>` | Start a live clone pre-seeded |
95
+ | `archal clone start <clone> --seed-file <path>` | Start a live clone, then load a JSON or SQL seed file |
96
+ | `archal clone seed <clone> <name>` | Sideload a named catalog seed into a running clone |
97
+ | `archal clone seed <clone> --file <path>` | Sideload a JSON or SQL seed file into a running clone |
98
+
99
+ Prefer `archal seed list` over memorizing a seed table. The catalog is derived
100
+ from `clones/<clone>/seeds/*.{json,sql}` on disk, so the CLI is always current.
101
+
102
+ ## The deterministic load flow
103
+
104
+ When a run seeds a clone, the loader does this, in order
105
+ (`packages/runtime/src/seed-loader.ts`):
106
+
107
+ 1. **Snapshot first.** `GET /state` on each target clone and keep the response
108
+ text. This is the rollback point (`snapshotSeedTargets` →
109
+ `fetchSeedStateSnapshot`).
110
+ 2. **Apply the seed.** `PUT /state` with the seed body — `application/json` for
111
+ a JSON seed, `text/sql` for a SQL seed — one clone at a time, tracking each
112
+ one that committed.
113
+ 3. **Roll back on failure.** If any clone's load throws, restore the clones that
114
+ already committed by replaying their snapshots, then re-throw the original
115
+ error (`restoreSeedTargets`). A clone is never left half-seeded.
116
+ 4. **Capture the baseline after seeding.** Once seeding succeeds, the post-seed
117
+ state is captured as the baseline by `@archal/vitest` bootstrap
118
+ (`captureBaselineCloneStates` in `packages/vitest/src/runtime/bootstrap.ts`).
119
+ Resets between runs restore *this* seeded baseline, not an empty clone — so
120
+ every run in a multi-run scenario starts from the same seeded state.
121
+
122
+ ### How state reaches the clone (the `/state` endpoint)
123
+
124
+ The clone server exposes `/state` (`clones/core/src/rest/rest-built-in-endpoints.ts`):
125
+
126
+ - `GET /state` — read the current state (used for the snapshot and baseline).
127
+ - `PUT /state` — load state. The handler branches on `Content-Type`:
128
+ - `text/sql` or `application/sql` → parsed and loaded as SQL (only when the
129
+ clone exposes SQL loading; otherwise it returns a 400 telling you to send
130
+ JSON).
131
+ - otherwise → loaded as JSON state.
132
+ - `PUT /state?seed=<name>` with a `{}` body → load a named catalog seed
133
+ server-side, without sending a state body at all.
134
+ - `DELETE /state` — wipe state (used by `--fresh-seed` before re-applying).
135
+
136
+ A successful `PUT` returns `{ ok: true }`. The content-type the CLI sends is set
137
+ in one place — `text/sql` when there is SQL, `application/json` otherwise
138
+ (`pushStateToCloud` in `cli/src/runner/execution/agent-http.ts`); named-seed
139
+ loads always send `application/json` with an empty body.
140
+
141
+ ## Do not do these
142
+
143
+ - **Do not synthesize seed data from scenario prose.** A `## Setup` paragraph is
144
+ context for the evaluator, not a source you extract state from. If you need
145
+ populated state, write a committed seed (or pick a named one) and reference it
146
+ with `seed:`.
147
+ - **Do not call an LLM to generate, repair, or "fill in" a seed.** The old
148
+ dynamic seed-generation path is being removed; `@archal/seed-state` was built
149
+ specifically to have none of it. Explicit committed seeds only.
150
+ - **Do not invent collection names.** A JSON seed must use the clone's real
151
+ collection keys (see "Writing a good JSON seed"). Unknown keys are dropped by
152
+ normalization, so a typo silently seeds nothing.
153
+ - **Do not hand-tune both `.json` and `.sql` for the same name.** Pick one form
154
+ per seed name; resolution stops at the first that exists.
155
+ - **Do not blow away a sideloaded session by accident.** On a reused
156
+ `archal clone start` session the loader probes for existing state before
157
+ re-applying. Use `--keep-state` to keep it or `--fresh-seed` to reset on
158
+ purpose, rather than fighting the guard.
159
+
160
+ ## Writing a good JSON seed
161
+
162
+ The seed file must mirror the clone's real state shape. The fastest reliable way
163
+ to get the shape right is to open an existing catalog seed for that clone and
164
+ match its top-level keys and per-entity fields.
165
+
166
+ A JSON seed is a top-level object: each key is a collection, each value is an
167
+ array of entity objects.
168
+
169
+ ```jsonc
170
+ {
171
+ "users": [{ "id": "u1", "login": "octocat", "type": "User" }],
172
+ "repos": [{ "id": "r1", "name": "demo", "fullName": "octocat/demo", "private": false }],
173
+ "issues": [{ "id": "i1", "repoId": "r1", "number": 1, "title": "First issue", "state": "open" }]
174
+ }
175
+ ```
176
+
177
+ Match the clone, not your imagination:
178
+
179
+ - Use the same collection names the clone uses. `clones/github/seeds/small-project.json`
180
+ has `users`, `repos`, `issues`, `pullRequests`, `labels`, and more.
181
+ - Give each entity the fields the clone expects, especially `id` and the foreign
182
+ keys that wire entities together (`repoId`, `issueNumber`, ...). The clone
183
+ maintains those relationships; broken references produce realistic errors at
184
+ runtime, not seed-time.
185
+ - Only arrays survive normalization — non-array top-level values are dropped
186
+ (`normalizeSeedState`). Keep everything in collection arrays.
187
+
188
+ ## When SQL fits
189
+
190
+ Use a `.sql` seed for relational clones whose state is naturally tables and
191
+ rows — `supabase` is the canonical case, and its seeds on disk are `.sql`. The
192
+ SQL seed is plain `CREATE TABLE` + `INSERT INTO ... VALUES (...)`:
193
+
194
+ ```sql
195
+ CREATE TABLE customers (id serial, email text, name text);
196
+ INSERT INTO customers (email, name) VALUES
197
+ ('ada@example.com', 'Ada Lovelace'),
198
+ ('alan@example.com', 'Alan Turing');
199
+ ```
200
+
201
+ The SQL parser is deliberately small (`parseSqlSeed` in
202
+ `packages/seed-state/src/state.ts`): it understands `CREATE TABLE` (including
203
+ `IF NOT EXISTS`), `INSERT INTO ... VALUES`, schema-qualified and quoted
204
+ identifiers, line and block comments, and auto-assigns serial `id`s. It is not a
205
+ full SQL engine — anything other than `CREATE TABLE` / `INSERT` throws an
206
+ "Unsupported SQL seed statement" error. Keep seeds to those two statements.
207
+
208
+ ## Failure taxonomy
209
+
210
+ | Symptom | Likely cause | Fix |
211
+ |---------|--------------|-----|
212
+ | `Could not resolve static seed "<name>"` / `seed_unavailable` | Seed name is misspelled, not in this clone's catalog, or the hosted session was started with a different seed | `archal seed list <clone>` to confirm the name; re-provision the session with the right seed |
213
+ | `clone "<x>" is not part of this scenario` | Clone-prefixed seed names a clone the scenario doesn't declare | Add the clone to `clones:`, or drop the prefix |
214
+ | Seed loads but state looks empty / partial | Wrong collection keys, or non-array top-level values dropped by normalization | Match an existing catalog seed's keys; keep every collection an array |
215
+ | `Failed to parse seed file ...` | Malformed JSON | Validate the JSON; check trailing commas and quoting |
216
+ | `Unsupported SQL seed statement: ...` | SQL beyond `CREATE TABLE` / `INSERT` | Reduce the seed to those two statements |
217
+ | `…does not expose SQL state loading` (HTTP 400) | Sent SQL to a clone that only loads JSON | Send JSON state, or use a clone that supports SQL |
218
+ | `Rollback failed after partial seed load` | A clone errored mid-load and the snapshot restore also failed | The clones may be in a mixed state; restart the clone session and retry |
219
+ | Seed "not re-applied" warning on a reused session | The loader kept existing sideloaded state instead of overwriting it | `--fresh-seed` to reset and re-apply, or `--keep-state` to accept it on purpose |
220
+
221
+ ## What to report back
222
+
223
+ After authoring or loading a seed, tell the user:
224
+
225
+ - the clone(s) and the seed shape used (named catalog seed, JSON file, SQL file,
226
+ or inline `## Seed State`)
227
+ - the seed name or file path, and how a scenario/run selects it (`seed:` or
228
+ `--seed`)
229
+ - the entity counts loaded per clone (the loader logs e.g. `7 issues, 3 repos`)
230
+ - for a new seed file, that it mirrors an existing catalog seed's shape
231
+ - any blocker: missing seed name, shape mismatch, SQL parse error, or a rollback
232
+ that fired — with the exact next command
233
+
234
+ ## Docs
235
+
236
+ - Seeds guide: https://docs.archal.ai/guides/seeds
237
+ - Clones and seeds overview: https://docs.archal.ai/clones/overview
238
+ - Writing scenarios: https://docs.archal.ai/guides/writing-scenarios
@@ -17,7 +17,8 @@ Claude already knows what Vitest is and how a fetch interceptor works. These are
17
17
  - Clones are hosted on **ECS Fargate** in Archal's AWS. First run = ~30s cold start. Subsequent runs within the 30-min idle TTL = ~2s. Tell the user; they'll think it's hung otherwise.
18
18
  - Session cache key = `(projectName, services, seeds)` hash. Change any of those and the cache misses.
19
19
  - **Seeds = starting state.** Omit to get the clone's default. Named seeds give fixtures (e.g. `small-project` for GitHub, `small-business` for Stripe). Never ask "what seed?" open-ended - the user doesn't know the catalog.
20
- - Route-mode clone availability is defined by `SHARED_ROUTE_MANIFESTS` in `packages/route-runtime-core/src/manifests.ts`; use `archal clone --json` / `archal seed list` before naming supported services.
20
+ - Route-mode clone availability comes from the packaged route manifest; use
21
+ `archal clone --json` / `archal seed list` before naming supported services.
21
22
 
22
23
  ## Discover before you ask
23
24
 
@@ -131,4 +132,4 @@ console.log(getInstalledArchalVitestSession()?.resolvedRuntime.resolvedServices)
131
132
  ## Docs
132
133
 
133
134
  - Guide: https://docs.archal.ai/guides/vitest
134
- - Package reference: `packages/vitest/README.md`
135
+ - Package reference: `archal/vitest` in the `archal` npm package
package/dist/harness.cjs DELETED
@@ -1,62 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/harness.ts
21
- var harness_exports = {};
22
- __export(harness_exports, {
23
- reportAgentMetrics: () => reportAgentMetrics
24
- });
25
- module.exports = __toCommonJS(harness_exports);
26
- var import_promises = require("fs/promises");
27
- var import_node_path = require("path");
28
- async function reportAgentMetrics(metrics, options = {}) {
29
- assertNonNegativeInteger("inputTokens", metrics.inputTokens);
30
- assertNonNegativeInteger("outputTokens", metrics.outputTokens);
31
- assertNonNegativeInteger("llmCallCount", metrics.llmCallCount);
32
- const metricsFile = options.metricsFile ?? process.env["AGENT_METRICS_FILE"] ?? process.env["ARCHAL_METRICS_FILE"];
33
- if (!metricsFile) {
34
- return false;
35
- }
36
- await (0, import_promises.mkdir)((0, import_node_path.dirname)(metricsFile), { recursive: true });
37
- await (0, import_promises.writeFile)(
38
- metricsFile,
39
- JSON.stringify({
40
- version: 1,
41
- inputTokens: metrics.inputTokens,
42
- outputTokens: metrics.outputTokens,
43
- llmCallCount: metrics.llmCallCount,
44
- ...nonEmptyString(metrics.provider) ? { provider: metrics.provider.trim() } : {},
45
- ...nonEmptyString(metrics.model) ? { model: metrics.model.trim() } : {}
46
- }),
47
- "utf8"
48
- );
49
- return true;
50
- }
51
- function nonEmptyString(value) {
52
- return typeof value === "string" && value.trim().length > 0;
53
- }
54
- function assertNonNegativeInteger(name, value) {
55
- if (!Number.isSafeInteger(value) || value < 0) {
56
- throw new TypeError(`${name} must be a non-negative safe integer`);
57
- }
58
- }
59
- // Annotate the CommonJS export names for ESM import in node:
60
- 0 && (module.exports = {
61
- reportAgentMetrics
62
- });
@@ -1,20 +0,0 @@
1
- interface AgentMetrics {
2
- inputTokens: number;
3
- outputTokens: number;
4
- llmCallCount: number;
5
- provider?: string;
6
- model?: string;
7
- }
8
- interface ReportAgentMetricsOptions {
9
- metricsFile?: string;
10
- }
11
- /**
12
- * Write agent-side token usage for `archal run`.
13
- *
14
- * Archal sets AGENT_METRICS_FILE when it launches a harness. Calling this
15
- * helper before the harness exits lets the dashboard show agent input/output
16
- * token counts without exposing the artifact wire format to user code.
17
- */
18
- declare function reportAgentMetrics(metrics: AgentMetrics, options?: ReportAgentMetricsOptions): Promise<boolean>;
19
-
20
- export { type AgentMetrics, type ReportAgentMetricsOptions, reportAgentMetrics };