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
8 changes: 4 additions & 4 deletions docs/a38.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The [example manifest](../examples/a38.json) is illustrative: replace its job an

Separately from that optional policy object, when every changed path ends with `.md` (case-sensitive) and the same fail-closed inventory rules hold, A38 omits **all** required jobs as `not_applicable` with log text `omitted: markdown-only change set` and report flag `markdown_only: true`. No author report is required for Ready when the guard independently confirms that markdown-only inventory. A pure `README.md` change set is both README-only and markdown-only; the full markdown skip applies and `readme_only: true` is set only when configured `omit_jobs` also matched.

Each required job contains `id`, `name`, `timeout_s`, `workflow`, and `job`, plus exactly one input: either `command` or `executor`. The legacy `command` form remains an exact local shell command and is preserved unchanged. An `executor` contains exactly `adapter` and `config`; `adapter` is one of `commands`, `compose`, `http-smoke`, or `immutable`, and its object-valued `config` is validated by that adapter's pure, strict parser. For example:
Each required job contains `id`, `name`, `timeout_s`, `workflow`, and `job`, plus exactly one input: either `command` or `executor`. An optional `lock` may appear on the `command` form (`null` or a nonempty name of ASCII letters, digits, `.`, `_`, or `-`). Executor jobs set `lock` in `executor.config`, not as a sibling of `executor`. The legacy `command` form remains an exact local shell command and is preserved unchanged. An `executor` contains exactly `adapter` and `config`; `adapter` is one of `commands`, `compose`, `http-smoke`, or `immutable`, and its object-valued `config` is validated by that adapter's pure, strict parser. For example:

```json
{
Expand All @@ -33,7 +33,7 @@ Each required job contains `id`, `name`, `timeout_s`, `workflow`, and `job`, plu
}
```

Central policy loading normalizes this structured form to a command-only internal job: `agent a38 job ADAPTER --config ` followed by shell-quoted, compact, sorted-key, ASCII JSON. Non-finite values are rejected. Execution, the frozen command-only report schema, report verification, and Guard comparison all use that same deterministic command string. The [A38 job adapters](a38-job-adapters.md) document each adapter's configuration contract.
Central policy loading normalizes this structured form to an internal job with that same command string plus the resolved `lock` (`null` when none): `agent a38 job ADAPTER --config ` followed by shell-quoted, compact, sorted-key, ASCII JSON. Non-finite values are rejected. Execution, the frozen command-only report schema, report verification, and Guard comparison all use that same deterministic command string. The [A38 job adapters](a38-job-adapters.md) document each adapter's configuration contract.

IDs are unique, and timeouts are finite positive seconds up to 86400. Workflow paths identify `.github/workflows/*.yml` or `*.yaml`; `job` is the workflow's job identifier. An exclusion contains only `workflow`, `job`, and a meaningful `reason`. A workflow/job pair appears exactly once across required jobs and exclusions.

Expand Down Expand Up @@ -90,7 +90,7 @@ agent a38 run --repo . --policy /tmp/a38-run/policy.json \
--output /tmp/a38-run/report.md --logs-dir /tmp/a38-run/logs --private
```

The runner identifies the GitHub repository from `origin` by default; for a fork, pass `--repository OWNER/NAME` with the PR target repository. Without `--private` or `--public`, visibility lookup requires `--github-session SESSION` bound explicitly in `$AGENT_HOME/github-accounts.json`. The executor verifies the selected account and refuses an absent binding or mismatched login; it never uses ambient host authentication. Explicit `--private` or `--public` supplies the report visibility without a GitHub lookup. A38 checks that visibility against the actual repository. The runner walks the complete required job list sequentially, records each command's result, exit code, elapsed time and timeout, and continues independent jobs after failures. When the change set is markdown-only, every required job is recorded as `not_applicable` without executing the command. Otherwise, configured `readme_only.omit_jobs` are recorded as `not_applicable` without executing the command when the change set is README-only; other jobs still run. It exposes `A38_HEAD_SHA` and `A38_BASE_SHA` to commands, removes GitHub token variables from job environments, and retains per-job logs locally. It terminates timed-out process groups. An interrupted run or checkout drift must never produce a successful report.
The runner identifies the GitHub repository from `origin` by default; for a fork, pass `--repository OWNER/NAME` with the PR target repository. Without `--private` or `--public`, visibility lookup requires `--github-session SESSION` bound explicitly in `$AGENT_HOME/github-accounts.json`. The executor verifies the selected account and refuses an absent binding or mismatched login; it never uses ambient host authentication. Explicit `--private` or `--public` supplies the report visibility without a GitHub lookup. A38 checks that visibility against the actual repository. The runner records each command's result, exit code, elapsed time and timeout. Jobs whose lock domains do not conflict may run at the same time: non-docker jobs share a CPU domain so lint, type-check and Jest do not overlap each other; `docker-heavy` may overlap that CPU domain. A `lock` on the command form coordinates only inside that `agent a38 run`. Cross-process exclusivity is the adapter lock (`executor.config.lock`, including the `docker-heavy` default for compose and http-smoke). `A38_MAX_IN_FLIGHT` caps concurrency (default 2, integer ≥ 1). After a job failure, independent jobs still run; a dirty tree or HEAD change still aborts the rest. When the change set is markdown-only, every required job is recorded as `not_applicable` without executing the command. Otherwise, configured `readme_only.omit_jobs` are recorded as `not_applicable` without executing the command when the change set is README-only; other jobs still run. It exposes `A38_HEAD_SHA` and `A38_BASE_SHA` to commands, removes GitHub token variables from job environments, and retains per-job logs locally. It terminates timed-out process groups. An interrupted run or checkout drift must never produce a successful report.

Job adapter behavior is defined separately in [A38 job adapters](a38-job-adapters.md). Use `agent a38 job <commands|compose|http-smoke|immutable> --config '<JSON>'`; this standard intentionally does not duplicate adapter schemas.

Expand All @@ -106,7 +106,7 @@ agent a38 verify --policy /tmp/a38-run/policy.json \

Only a complete `run` plus successful local `verify` for the signed, clean final SHA may be recorded as `local_check_pass`. That final SHA must be on the open draft with no intervening commit after the verified measurement. Early draft publication may precede this final measurement ([pull request lifecycle](pull-request-lifecycle.md)). Any fix, amend, rebase, or other new SHA requires a new signed clean commit and a complete run and verification from the beginning.

The generated `report.md` is ready to publish: one short sentence under `EN:`, one under `DE:`, and a closed `<details>` section containing a mandatory table followed by the unchanged machine-readable block in its own nested closed details section. Labels appear on their own lines; blank lines separate the languages and follow `</summary>` so GitHub renders the enclosed Markdown. The summary describes the evidence without declaring failed or interrupted runs successful. The table lists **every recorded A38 job**, in execution order, with its ID/name, duration, final result and exit code, including failed, errored or timed-out jobs. Display durations in seconds, always rounded **up to whole seconds** (84.467 → 85 s; 84 → 84 s; 0 → 0 s). Preserve the exact fractional measurements in the original machine block. Rows represent A38 jobs, not every underlying test case in a suite. Job names are escaped so they cannot alter the table or HTML structure. Commands and exact evidence remain in the nested original report. Adopters and plugins use this central output rather than maintaining another format template.
The generated `report.md` is ready to publish: one short sentence under `EN:`, one under `DE:`, and a closed `<details>` section containing a mandatory table followed by the unchanged machine-readable block in its own nested closed details section. Labels appear on their own lines; blank lines separate the languages and follow `</summary>` so GitHub renders the enclosed Markdown. The summary describes the evidence without declaring failed or interrupted runs successful. The table lists **every recorded A38 job**, in policy order (manifest `jobs` order), with its ID/name, duration, final result and exit code, including failed, errored or timed-out jobs. Display durations in seconds, always rounded **up to whole seconds** (84.467 → 85 s; 84 → 84 s; 0 → 0 s). Preserve the exact fractional measurements in the original machine block. Rows represent A38 jobs, not every underlying test case in a suite. Job names are escaped so they cannot alter the table or HTML structure. Commands and exact evidence remain in the nested original report. Adopters and plugins use this central output rather than maintaining another format template.

Post the generated `report.md` unchanged as a PR comment **using the PR author's GitHub account**, preserving its markers and fenced JSON block. For legacy reports, adding this presentation around the original marked block is allowed only if that block remains byte-for-byte unchanged; preserve all measured data and timestamps, then verify and reassess the edited comment. Publishing is separate from running and verification. Do not paste raw logs containing credentials into the comment and do not hand-edit or reconstruct a passing payload.

Expand Down
Loading
Loading