Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .agents/setup
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ if [[ "$(node -p 'process.versions.node.split(".")[0]')" != "$major" ]]; then
fi
pin="$(node -p 'JSON.parse(require("node:fs").readFileSync("package.json", "utf8")).packageManager || "pnpm"')"
manager="${pin%%@*}"
corepack enable
if ! corepack enable >/dev/null 2>&1; then
shims="$HOME/.local/bin"
mkdir -p "$shims"
corepack enable --install-directory "$shims"
export PATH="$shims:$PATH"
fi
if [[ "$pin" == *@* ]]; then
corepack prepare "$pin" --activate
fi
Expand Down
7 changes: 4 additions & 3 deletions .agents/skills/verify-interface/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,15 @@ Each step writes `<run>/evidence/<feature>/<journey>/<NN-step>/` with `command.t
node_modules/.bin/antelopejs-verify clean <run>
```

Each journey deletes its scratch folder and `HOME`, its install included, when it ends: passed, failed or interrupted. Only its evidence stays. `clean` stops what the run started, by recorded PID and container name, and removes everything but `evidence/` and `run.json`, the folders `context.prepared` kept included. Run it after every run, failed ones included.
Each journey deletes its scratch folder and `HOME`, its install included, when it ends: passed, failed or interrupted. Only its evidence stays. `clean` stops what the run started, by recorded PID and container name, and removes everything but `evidence/` and `run.json`, the folders `context.prepared` kept included. Run it after every run, failed ones included. It cleans only a run this checkout created, the folder `new` printed: it refuses the shared runs folder, a repository's folder of runs and another checkout's run, which belong to other sessions. Never delete under the runs folder yourself, with `rm` or a glob over run names.

## The repository's own layer

- `verify.config.ts` default-exports a `VerifyConfig` from `@antelopejs/tooling-configs/verify`:
- `doors`: one entry per door kind (`data`, `format`, `contract`, `outbound`, `exposure`, `publish`), each `null` when it cannot apply or `{ globs, funnels, why }`.
- `journeys`: the repository's journeys by id, each `{ title, entryPoint, run(context) }`, using the check helpers the same import exports. A check states what the product must do; an environment that went away is never a failing check. When a journey fails, the harness reruns each service's readiness command, up to four times over about 3.5 s, and looks at every `ajs project dev` the journey started, its own readiness probe included. The journey ends NOT VERIFIED, not FAIL, when a service still fails every rerun, an app was killed by SIGKILL, SIGTERM, SIGHUP or SIGINT that the harness did not send, or the app the harness started failed to bind the port the harness gave it (`EADDRINUSE` naming that port). An app that exits on its own with an exit code, one that crashes by another signal such as SIGABRT or SIGSEGV, and one that logs `EADDRINUSE` for any other port are the product's failure. A change that takes its own service down still reads as an outage: the service stays down, so the journey is NOT VERIFIED. For anything else the journey depends on, such as a process it started with `context.command` or an outside endpoint, probe it when a check fails and call `context.notVerified(reason)` when it no longer answers.
- `context.prepared(key, build)` does the preparation many journeys repeat once per run, such as scaffolding and installing a project, and returns the journey's own copy at `<work>/<key>`. The first journey that asks for `key` runs `build(folder)` on the empty folder with its usual steps, after a step `prepared <key>` that marks them as the build and says whether it was kept. A build is kept until `clean` only when it returns, records at least one check, passes every check, and leaves only files, directories and symlinks in the folder. Every later journey of the run, also in a later `journey` command, gets a fresh copy and one step, `prepared <key>`, that names the journey that built it and holds that build's evidence under `build/`. A build that is not kept is built again by the next journey, and rerunning the journey that built builds again. An absolute symlink into the folder points into each copy; other symlinks keep their target. `build` writes only inside the folder it is given: a write elsewhere, such as a sibling under `<work>` or the repository, stays with the journey that built. Two concurrent `journey` commands that reach the same key at once both build, and the first to finish is kept. The commands `build` runs get a `HOME` of their own that is deleted when it ends: redo after `prepared` anything a later step needs in `HOME`, such as `ajs config set git`. Pass the same `build` for a key in every journey.
- `journeys`: the repository's journeys by id, each `{ title, entryPoint, run(context) }`, using the check helpers the same import exports. A check states what the product must do; an environment that went away is never a failing check. When a journey fails, the harness reruns each service's readiness command, up to four times over about 3.5 s, and looks at every `ajs project dev` the journey started, its own readiness probe included. The journey ends NOT VERIFIED, not FAIL, when a service still fails every rerun, an app was killed by SIGKILL, SIGTERM, SIGHUP or SIGINT that the harness did not send, or the app the harness started failed to bind the port the harness gave it (`EADDRINUSE` naming that port), or the first failing step is an install, image pull or image build whose failed requests went only to fixed public registry names that also fail a fresh DNS and TCP probe at verdict time. A registry that answers that probe makes the failure the product's, whatever the output says. An app that exits on its own with an exit code, one that crashes by another signal such as SIGABRT or SIGSEGV, and one that logs `EADDRINUSE` for any other port are the product's failure. A change that takes its own service down still reads as an outage: the service stays down, so the journey is NOT VERIFIED. For anything else the journey depends on, such as a process it started with `context.command` or an outside endpoint, probe it when a check fails and call `context.notVerified(reason)` when it no longer answers.

- `context.prepared(key, build)` does the preparation many journeys repeat once per run, such as scaffolding and installing a project, and returns the journey's own copy at `<work>/<key>`. The first journey that asks for `key` runs `build(folder)` on the empty folder with its usual steps, after a step `prepared <key>` that marks them as the build and says whether it was kept. A build is kept until `clean` only when it returns, records at least one check, passes every check, and leaves only files, directories and symlinks in the folder. Every later journey of the run, also in a later `journey` command, gets a fresh copy and one step, `prepared <key>`, that names the journey that built it and holds that build's evidence under `build/`. A build that is not kept is built again by the next journey, and rerunning the journey that built builds again. An absolute symlink into the folder points into each copy; other symlinks keep their target. A file with a hard link outside the folder, such as a package file pnpm links from its store, is linked into each copy rather than copied: `context.edit` gives it a new inode, and a journey that writes it another way replaces it instead of writing it in place. `build` writes only inside the folder it is given: a write elsewhere, such as a sibling under `<work>` or the repository, stays with the journey that built. Two concurrent `journey` commands that reach the same key at once both build, and the first to finish is kept. A project `build` creates with `scaffold` starts each copy as `scaffold` starts one: a copy with no installed module gets a module cache an earlier passing journey kept, and a passing journey keeps the registry modules installed into its copy. The commands `build` runs get a `HOME` of their own that is deleted when it ends: redo after `prepared` anything a later step needs in `HOME`, such as `ajs config set git`. Pass the same `build` for a key in every journey.
- `env`, `setup` (commands replacing the build), `userFacing` and `shared` (globs replacing the kind's default; `shared` lists the files whose change runs every feature), and `formal` (formal checks: `name`, `covers`, `command`, `violation` with an optional `states` group for the counterexample length, and optionally `behaviour` and `baseCommand`).
- `services`: image, port, readiness command and a `reset` command run before every journey, as for a module. `new` starts them in Docker on free ports; a journey reads them with `context.service(name)` and `context.native(...)`.
- `interface.provide(api, services)` runs in the stub provider after the generic stubs attach, for example to hand a client pointed at `services` to `internal.SetClient`.
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ Verify a boundary against the imports a developer or agent would plausibly write
| String-keyed object tables are read through own keys only | `antelopejs/no-inherited-key-lookup` |
| A type guard checks each member it narrows to; keys with `Object.hasOwn` | `antelopejs/no-presence-only-type-guard` |
| A type guard checks the nested elements and values it claims | review; no tool |
| `Object.assign` writes no `unknown`, `any` or mistyped value over a field | `antelopejs/no-unsafe-object-assign` |
| Every file type-aware lint reads is listed by a tsconfig | `antelopejs/require-tsconfig-include` |
| Params ≤ 5, function ≤ 120 lines, file ≤ 500 lines, depth ≤ 4, complexity ≤ 20 | `eslint/max-*`, `eslint/complexity` |
| Cleanup preserves declarations, runtime exports and DMS auto-imports | `antelopejs-api-diff <base-ref>` |
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"@antelopejs/api": "1.7.0",
"@antelopejs/core": "^1.21.0",
"@antelopejs/interface-core": ">=0.4.0 <1.0.0",
"@antelopejs/tooling-configs": "^0.4.0",
"@antelopejs/tooling-configs": "^0.5.0",
"@types/mocha": "^10.0.10",
"@types/node": "^22.19.15",
"@types/sinon": "^17.0.4",
Expand Down
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading