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.
- package/README.md +62 -154
- package/agents/openclaw/.archal.json +8 -0
- package/agents/openclaw/Dockerfile +97 -0
- package/agents/openclaw/README.md +113 -0
- package/agents/openclaw/drive.mjs +301 -0
- package/agents/openclaw/extract-openclaw-response-text.mjs +49 -0
- package/agents/openclaw/package.json +9 -0
- package/agents/openclaw/scenarios/acceptance/github-escalation-and-cleanup.md +43 -0
- package/agents/openclaw/scenarios/acceptance/jira-linear-release-triage.md +39 -0
- package/agents/openclaw/scenarios/acceptance/multi-clone-customer-risk-review.md +45 -0
- package/agents/openclaw/scenarios/acceptance/slack-incident-handoff.md +42 -0
- package/agents/openclaw/scenarios/acceptance/stripe-dunning-remediation.md +40 -0
- package/agents/openclaw/scenarios/close-stale-issues.md +35 -0
- package/agents/openclaw/scenarios/github-issue-triage-read-only.md +44 -0
- package/agents/openclaw/workspace/AGENTS.md +23 -0
- package/agents/openclaw/workspace/IDENTITY.md +8 -0
- package/agents/openclaw/workspace/SOUL.md +14 -0
- package/agents/openclaw/workspace/TOOLS.md +54 -0
- package/clone-assets/apify/tools.json +256 -22
- package/clone-assets/calcom/tools.json +2062 -0
- package/clone-assets/clickup/tools.json +3245 -0
- package/clone-assets/customerio/tools.json +2350 -0
- package/clone-assets/datadog/tools.json +734 -0
- package/clone-assets/github/tools.json +307 -27
- package/clone-assets/gitlab/tools.json +10688 -0
- package/clone-assets/google-workspace/tools.json +18 -6
- package/clone-assets/hubspot/tools.json +1604 -0
- package/clone-assets/jira/fidelity.json +1 -1
- package/clone-assets/jira/tools.json +266 -543
- package/clone-assets/linear/tools.json +278 -40
- package/clone-assets/ownerrez/tools.json +548 -0
- package/clone-assets/pricelabs/tools.json +343 -0
- package/clone-assets/sentry/tools.json +2821 -0
- package/clone-assets/slack/tools.json +1 -2
- package/clone-assets/stripe/tools.json +299 -46
- package/clone-assets/supabase/tools.json +437 -0
- package/clone-assets/unipile/tools.json +408 -0
- package/clone-assets/webflow/tools.json +2185 -0
- package/dist/autoloop-worker-types-CHaclqtD.d.cts +160 -0
- package/dist/cli.cjs +127896 -84811
- package/dist/{vitest/chunk-L36NXAU6.js → commands/autoloop-hosted-control-plane-client.cjs} +16344 -18845
- package/dist/commands/autoloop-hosted-control-plane-client.d.cts +133 -0
- package/dist/commands/autoloop-pr-verification.cjs +4312 -0
- package/dist/commands/autoloop-pr-verification.d.cts +19 -0
- package/dist/commands/autoloop-result-parser.cjs +27058 -0
- package/dist/commands/autoloop-result-parser.d.cts +196 -0
- package/dist/commands/autoloop-worker.cjs +38488 -0
- package/dist/commands/autoloop-worker.d.cts +102 -0
- package/dist/eval-shim.mjs +216 -0
- package/dist/index.cjs +15 -2
- package/dist/index.d.cts +3 -1
- package/dist/layer-1-ziaLpfLr.d.cts +62 -0
- package/dist/metafile-cjs.json +1 -0
- package/dist/reporter-entry.js +3 -0
- package/dist/sdk/index.cjs +51630 -0
- package/dist/sdk/index.d.cts +626 -0
- package/dist/vitest/chunk-2PDHTPZC.js +4867 -0
- package/dist/vitest/chunk-7L4BBB6M.js +2613 -0
- package/dist/vitest/index.cjs +6152 -75718
- package/dist/vitest/index.d.ts +22 -86
- package/dist/vitest/index.js +45 -414
- package/dist/vitest/runtime/hosted-session-reaper.cjs +682 -34399
- package/dist/vitest/runtime/hosted-session-reaper.js +1 -1
- package/dist/vitest/runtime/setup-files.js +2 -2
- package/manifest.json +9 -0
- package/package.json +20 -14
- package/skills/archal-agent/SKILL.md +86 -0
- package/skills/autoloop/SKILL.md +391 -0
- package/skills/autoloop/references/hosted-sources.md +94 -0
- package/skills/autoloop/references/trace-schema-mapping.md +104 -0
- package/skills/eval/SKILL.md +17 -15
- package/skills/free-account/SKILL.md +103 -0
- package/skills/install-agent/SKILL.md +202 -0
- package/skills/onboard/SKILL.md +29 -18
- package/skills/scenario/SKILL.md +36 -18
- package/skills/seed/SKILL.md +238 -0
- package/skills/vitest/SKILL.md +3 -2
- package/dist/harness.cjs +0 -62
- package/dist/harness.d.cts +0 -20
- package/dist/seed/dynamic-generator.cjs +0 -45687
- package/dist/seed/dynamic-generator.d.cts +0 -106
- package/dist/vitest/chunk-WZ7SA4CK.js +0 -47369
- package/skills/attach/SKILL.md +0 -402
package/skills/scenario/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: scenario
|
|
3
|
-
description: Write, edit, and validate Archal scenario
|
|
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
|
|
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
|
|
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 |
|
|
96
|
-
|
|
97
|
-
| `apify` | `
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
107
|
-
| `
|
|
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
|
|
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.
|
|
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
|
package/skills/vitest/SKILL.md
CHANGED
|
@@ -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
|
|
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: `
|
|
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
|
-
});
|
package/dist/harness.d.cts
DELETED
|
@@ -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 };
|