From 7e0c440bedd79a714d9cbad4eedeccf40341626b Mon Sep 17 00:00:00 2001 From: Leif Date: Wed, 22 Jul 2026 19:23:32 -0600 Subject: [PATCH] Fix CI dogfood binary selection and refresh verification --- .github/workflows/ci.yml | 4 + .github/workflows/linux-smoke.yml | 5 + .../approvals.json | 7 + .../state.json | 3 +- .../approvals.json | 199 ++++++++++++++++++ .../state.json | 2 +- .../verification-attempts.json | 18 ++ .../verification.json | 12 +- AGENTS.md | 49 ++++- Scripts/ci-dogfood.sh | 41 ++++ Scripts/smoke.ps1 | 7 +- Scripts/smoke.sh | 5 +- fledge.toml | 6 +- 13 files changed, 339 insertions(+), 19 deletions(-) create mode 100755 Scripts/ci-dogfood.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc199ff..9257a10 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,3 +55,7 @@ jobs: env: APS_BIN: ${{ matrix.aps_bin }} run: ./Scripts/smoke.sh + - name: CI dogfood (use aps as a job-scoped helper) + env: + APS_BIN: ${{ matrix.aps_bin }} + run: ./Scripts/ci-dogfood.sh diff --git a/.github/workflows/linux-smoke.yml b/.github/workflows/linux-smoke.yml index 9425ef7..59a3841 100644 --- a/.github/workflows/linux-smoke.yml +++ b/.github/workflows/linux-smoke.yml @@ -44,3 +44,8 @@ jobs: env: APS_BIN: .build/debug/aps run: ./Scripts/smoke.sh + + - name: CI dogfood (use aps as a job-scoped helper) + env: + APS_BIN: .build/debug/aps + run: ./Scripts/ci-dogfood.sh diff --git a/.specsync/changes/CHG-0038-harden-adversarial-findings-safer-reset-secret-set-unlock-root-state-dir-sch/approvals.json b/.specsync/changes/CHG-0038-harden-adversarial-findings-safer-reset-secret-set-unlock-root-state-dir-sch/approvals.json index 2f84ab3..323b897 100644 --- a/.specsync/changes/CHG-0038-harden-adversarial-findings-safer-reset-secret-set-unlock-root-state-dir-sch/approvals.json +++ b/.specsync/changes/CHG-0038-harden-adversarial-findings-safer-reset-secret-set-unlock-root-state-dir-sch/approvals.json @@ -41,6 +41,13 @@ "timestamp": 1784648535, "digest": "e2a7a5f1d3132822831ecd65de7a444de41904d4a4f04745b40e901c38eb1ca4", "note": null + }, + { + "gate": "definition", + "actor": "Codex", + "timestamp": 1784768758, + "digest": "d93882378f14b9cad70eee22629fe83d0e1adc3fde3bc4fe4e54608d24a43492", + "note": "Refresh approval for AGENTS.md documentation coverage after rebasing onto merged PR #83." } ], "reopenings": [] diff --git a/.specsync/changes/CHG-0038-harden-adversarial-findings-safer-reset-secret-set-unlock-root-state-dir-sch/state.json b/.specsync/changes/CHG-0038-harden-adversarial-findings-safer-reset-secret-set-unlock-root-state-dir-sch/state.json index f806e0c..2ad6f2d 100644 --- a/.specsync/changes/CHG-0038-harden-adversarial-findings-safer-reset-secret-set-unlock-root-state-dir-sch/state.json +++ b/.specsync/changes/CHG-0038-harden-adversarial-findings-safer-reset-secret-set-unlock-root-state-dir-sch/state.json @@ -8,7 +8,7 @@ "state": "implementing", "base_commit": "2eac0ec7e7bf7bbd69976c30d9d553f19aacacc1", "created_at": 1784646126, - "updated_at": 1784648535, + "updated_at": 1784768758, "affected_specs": [ "aps-cli", "state-store" @@ -17,6 +17,7 @@ "Sources/aps/", "Tests/apsTests/", "Scripts/", + "AGENTS.md", "README.md", "specs/", ".specsync/change-sequence.json", diff --git a/.specsync/changes/CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations/approvals.json b/.specsync/changes/CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations/approvals.json index fa61bac..a33490b 100644 --- a/.specsync/changes/CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations/approvals.json +++ b/.specsync/changes/CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations/approvals.json @@ -48,6 +48,13 @@ "timestamp": 1784767876, "digest": "e5f5694b768a0174aab17d0deebde732e96b53b86ff2877a6efdbe604105f0ad", "note": "Acceptance after rebased branch verification." + }, + { + "gate": "acceptance", + "actor": "Codex", + "timestamp": 1784769636, + "digest": "bb8d18e3565bc28e654e62ef1012f05387e59294497169456b77dc9846be4ed4", + "note": "Acceptance after CI binary-path fix and smoke re-verification." } ], "reopenings": [ @@ -242,6 +249,198 @@ }, "stale_acceptance_input_digest": "c638f9bf3b8762c8c0b4b6c21e63eb6ecd4ef315d98a8217becb9144b7e49e45", "current_acceptance_input_digest": "581db891b8bb35709a6c7012356d0c3cb12c926ec74c3ac1140320f0443070bf" + }, + { + "schema_version": 1, + "change_id": "CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations", + "actor": "codex", + "reason": "Re-verify accepted CHG-0041 after rebasing PR #86 onto merged PR #83 and changing smoke isolation.", + "timestamp": 1784769548, + "from_state": "accepted", + "to_state": "verifying", + "superseded_approval": { + "gate": "acceptance", + "actor": "Codex", + "timestamp": 1784767876, + "digest": "e5f5694b768a0174aab17d0deebde732e96b53b86ff2877a6efdbe604105f0ad", + "note": "Acceptance after rebased branch verification." + }, + "prior_verification": { + "timestamp": 1784767865, + "commit": "427f42e57bd11a2b92b6245abbcc347549cacec6", + "contract_digest": "d0845b60a9c43a12bdb1f6588e678b92d18f05ef83644edcc009ea40a5b58720", + "workspace_digest": "372b56f7730cfe3c512902828b84742b222e671e92116377173c500de9fd9826", + "acceptance_input_digest": "581db891b8bb35709a6c7012356d0c3cb12c926ec74c3ac1140320f0443070bf", + "acceptance_manifest": { + "schema_version": 1, + "entries": [ + { + "path": ".specsync/change-sequence.json", + "kind": "file", + "mode": 33188, + "payload_digest": "f9c5f154ca02b24d3dbcbe27f638b9c2a2656aaddf58291d3f6a6a37298968a4", + "entry_digest": "423f74daedf58367dd90a7b6169a7cbe676a581c31c134428d92c3134b938bc1", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "Scripts/smoke.sh", + "kind": "file", + "mode": 33261, + "payload_digest": "ea93b7ee69bbd829015e5ed2980f6889332db914a36d5074e6ca64159eaac3ad", + "entry_digest": "42bc00afd55e8963205030f0651e720ced04c3ece87b0e24968c44daa60e8e82", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "Sources/aps/DynamicKeyStorage.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "83d1001c687c8d87978e377a973e5f306b4bce876c990bd6cae9ec76361435be", + "entry_digest": "18980a16da10134ffb2226baba26375f21f3b6761d13337db1004ecf18062ae6", + "owners": [ + "state-store" + ] + }, + { + "path": "Sources/aps/SchemaFileLock.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "944429324e43897d2404675f3e767b8c0c30122964572e457e175c3408942104", + "entry_digest": "d75c086410c8c8649f6ef1e10c1f2b19eb140786a502f84e3120be0890f01192", + "owners": [ + "aps-cli" + ] + }, + { + "path": "Sources/aps/StateStore.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "543158d8ef7553c81015fddebd19f9bdbd3039b769f97682dd514124316e2986", + "entry_digest": "63d59cf0372bfaffd8c83492562711219500721ccab5f7979e0712161ea80d53", + "owners": [ + "state-store" + ] + }, + { + "path": "specs/aps-cli/aps-cli.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a34659e33913de1f023f5496e840deb31214b5de95c13dc5ed6605789cae8682", + "entry_digest": "af1dd90a0c2b304b2dae25bfcc685db76efbbbda9bb67d7bea3ac764ba433b17", + "owners": [ + "aps-cli" + ] + }, + { + "path": "specs/aps-cli/context.md", + "kind": "file", + "mode": 33188, + "payload_digest": "b6b45cae19244f96b97854129adc5794b76623aa0547b5b5ba27fd20e522948f", + "entry_digest": "3d95dbf704bd5d40be4f8f4c95897cf6e5549152b4cdaab0adc43328febf8b90", + "owners": [ + "aps-cli" + ] + }, + { + "path": "specs/aps-cli/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "8cb54f4892cbaf772a325831685da8d2ee9821ecb53c269c555c26ff66c47b1c", + "entry_digest": "a489d70664df850e07b811552a5b40ebfc5e7330ea5df82494fd8bafe7b83320", + "owners": [ + "aps-cli" + ] + }, + { + "path": "specs/aps-cli/tasks.md", + "kind": "file", + "mode": 33188, + "payload_digest": "83d2620192191bceccaa4a8758b8c7120300db800d7595309ddbc96ec6591525", + "entry_digest": "16ee871a59dd92753ba0d3be7f10aff13bd6a0d622abfada0d67073e6ccf0c90", + "owners": [ + "aps-cli" + ] + }, + { + "path": "specs/aps-cli/testing.md", + "kind": "file", + "mode": 33188, + "payload_digest": "e67750e6f7395b76924cbc0855203f13e3c9f94b17e6683df75efd29fad1ac18", + "entry_digest": "84df77693472fc697971f28150ceb74299d8a30803bf059a92cf9dd974b1da4c", + "owners": [ + "aps-cli" + ] + }, + { + "path": "specs/state-store/context.md", + "kind": "file", + "mode": 33188, + "payload_digest": "9148fb7ca2a5c078d57b477c4b84625dbe9e6a19c4d764854f3232e8ab48595b", + "entry_digest": "052b5cac0066e6399cd129acf2f35f018337005a79425a0e6e7e64e08c725e1e", + "owners": [ + "state-store" + ] + }, + { + "path": "specs/state-store/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "1b37b782eb02875ed5044b933e00a9b27fc7c721f6fe60055faadfd4c81b4c60", + "entry_digest": "9be552e6e1a5df22eef12906fde78a289500d26689c0096edafc91075b32eb2a", + "owners": [ + "state-store" + ] + }, + { + "path": "specs/state-store/state-store.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "f38de1c661bb60fdaee4616bfbbba73a388e4f08fbc3641eacb1762577a45e77", + "entry_digest": "5b599611b22a63e5e6746e42c0bbf56f017213c486e3442e797b012c528c6f74", + "owners": [ + "state-store" + ] + }, + { + "path": "specs/state-store/tasks.md", + "kind": "file", + "mode": 33188, + "payload_digest": "0f02b782887467b358568bf22c2d68f39c40a00d56143bd6c64abdf8198cf433", + "entry_digest": "8f828f3625d4f24c3c71852bd28f76aac97cd31ace2a18d1a901a3d34642de8d", + "owners": [ + "state-store" + ] + }, + { + "path": "specs/state-store/testing.md", + "kind": "file", + "mode": 33188, + "payload_digest": "4251736322194cd40b5c0f059e454853e8982ee5de85924ee76dde01b2c9907d", + "entry_digest": "e38d9ef8f8ab5b0445dc4a4cd35430d88319eb1a35a064c3b9e301cb9b4ee802", + "owners": [ + "state-store" + ] + } + ] + }, + "passed": true, + "commands": [ + { + "command": "fledge lanes run verify", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-aps-cli-025", + "REQ-state-store-019" + ] + }, + "stale_acceptance_input_digest": "581db891b8bb35709a6c7012356d0c3cb12c926ec74c3ac1140320f0443070bf", + "current_acceptance_input_digest": "f003e0e71ab347492e47a5ca902fbf595c390a325fa1a14bc235f98a4b566f8b" } ] } diff --git a/.specsync/changes/CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations/state.json b/.specsync/changes/CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations/state.json index 301c47a..6f6fc93 100644 --- a/.specsync/changes/CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations/state.json +++ b/.specsync/changes/CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations/state.json @@ -9,7 +9,7 @@ "canonical_applied": true, "base_commit": "6a40258d80047be13132e68b0597ff3bfe9b52b7", "created_at": 1784763748, - "updated_at": 1784767876, + "updated_at": 1784769636, "affected_specs": [ "state-store", "aps-cli" diff --git a/.specsync/changes/CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations/verification-attempts.json b/.specsync/changes/CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations/verification-attempts.json index 8c410d5..fec0428 100644 --- a/.specsync/changes/CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations/verification-attempts.json +++ b/.specsync/changes/CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations/verification-attempts.json @@ -139,6 +139,24 @@ "REQ-aps-cli-025", "REQ-state-store-019" ] + }, + { + "timestamp": 1784769617, + "commit": "efc56b441f641f1311c8b4b08332876b0bf694b8", + "contract_digest": "d0845b60a9c43a12bdb1f6588e678b92d18f05ef83644edcc009ea40a5b58720", + "workspace_digest": "e2ca7cd6b5fe9865aa854869b7ef203de499e5ced25e97603458f5a608ad9003", + "passed": true, + "commands": [ + { + "command": "fledge lanes run verify", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-aps-cli-025", + "REQ-state-store-019" + ] } ] } diff --git a/.specsync/changes/CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations/verification.json b/.specsync/changes/CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations/verification.json index 8ed5dac..09b20f7 100644 --- a/.specsync/changes/CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations/verification.json +++ b/.specsync/changes/CHG-0041-serialize-cross-process-filestate-and-slice-profile-read-modify-write-operations/verification.json @@ -1,9 +1,9 @@ { - "timestamp": 1784767865, - "commit": "427f42e57bd11a2b92b6245abbcc347549cacec6", + "timestamp": 1784769617, + "commit": "efc56b441f641f1311c8b4b08332876b0bf694b8", "contract_digest": "d0845b60a9c43a12bdb1f6588e678b92d18f05ef83644edcc009ea40a5b58720", - "workspace_digest": "372b56f7730cfe3c512902828b84742b222e671e92116377173c500de9fd9826", - "acceptance_input_digest": "581db891b8bb35709a6c7012356d0c3cb12c926ec74c3ac1140320f0443070bf", + "workspace_digest": "e2ca7cd6b5fe9865aa854869b7ef203de499e5ced25e97603458f5a608ad9003", + "acceptance_input_digest": "f003e0e71ab347492e47a5ca902fbf595c390a325fa1a14bc235f98a4b566f8b", "acceptance_manifest": { "schema_version": 1, "entries": [ @@ -21,8 +21,8 @@ "path": "Scripts/smoke.sh", "kind": "file", "mode": 33261, - "payload_digest": "ea93b7ee69bbd829015e5ed2980f6889332db914a36d5074e6ca64159eaac3ad", - "entry_digest": "42bc00afd55e8963205030f0651e720ced04c3ece87b0e24968c44daa60e8e82", + "payload_digest": "430bebc7d4a1539115bbe0f3620bc872e53bcf8e2e0b64ab50c84748704a2ad0", + "entry_digest": "bfb75c49144f37901337044676b88bfefb2d8874f09c521c9dbb38735d436a13", "owners": [ "@exact:delivery" ] diff --git a/AGENTS.md b/AGENTS.md index 54eb98d..50c931a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,22 +10,59 @@ A Swift CLI that dogfoods [AppState](https://github.com/0xLeif/AppState) outside | `Tests/apsTests/` | Round-trip, watch, reset, and dependency tests | | `specs/` | SpecSync contracts for the CLI and state surface | | `Scripts/smoke.sh` | End-to-end CLI smoke checks | +| `Scripts/ci-dogfood.sh` | Job-scoped APS_HOME proof that CI *uses* aps | ## Workflow ```sh -fledge lanes run verify # build + test + smoke +fledge lanes run verify # build + test + smoke + ci-dogfood fledge trust verify # full trust gate when tools are installed ./Scripts/smoke.sh +./Scripts/ci-dogfood.sh ``` ## Dogfooding aps -Use the tool itself for agent state on this project: `fledge aps` (live-linked -plugin) or `aps` from the tap. Persist working/session state in the default -state root (`~/.aps`) with `aps key add` + `set`/`get` instead of scratch -files. Leave the demo keys for tests and smoke; add your own keys for real -state (see `docs/design/dynamic-schema.md`). +Use the tool itself for agent and CI state on this project: `fledge aps` +(live-linked plugin) or `aps` from a local build / the tap. Prefer aps keys +over scratch files. + +### Bootstrap (Linux cloud / this repo) + +```sh +./Scripts/build.sh -c release # portable; raw swift build can fail on Linux 6.0.x +export PATH="$PWD/.build/release:$PATH" +# Optional isolation from a polluted home root: +# export APS_HOME=/tmp/aps-agent-$USER +``` + +### Session keys (FileState only) + +Leave demo seed keys (`counter`, `message`, `flag`, `note`, `profile`, `secret`, +`profileName`) for tests and `Scripts/smoke.sh`. Add your own keys: + +```sh +aps key add agentStatus --type String --storage FileState --path agent-status.json --initial '' +aps key add agentIssue --type Int --storage FileState --path agent-issue.json --initial 0 +aps key add agentBranch --type String --storage FileState --path agent-branch.json --initial '' +aps set agentStatus exploring +aps set agentIssue 82 +aps set agentBranch "$(git branch --show-current)" +aps get agentStatus --json +aps dump --json +``` + +Rules: + +- Prefer **FileState** for anything that must survive process boundaries. +- Avoid **StoredState** for agent keys until #82 (user StoredState is not + scoped by `--state-dir` / `APS_HOME`). +- Avoid `aps reset --all` on a dogfood root that holds agent keys (it resets + every registered key). +- In CI, always set a job-scoped `APS_HOME` or `--state-dir` (see + `Scripts/ci-dogfood.sh`). + +See `docs/design/dynamic-schema.md` for the registry model. ## Multi-agent ticket claiming diff --git a/Scripts/ci-dogfood.sh b/Scripts/ci-dogfood.sh new file mode 100755 index 0000000..a33c467 --- /dev/null +++ b/Scripts/ci-dogfood.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# Prove aps is usable as a CI helper: job-scoped state root, dynamic FileState +# keys, cross-process get/set, and JSON dump. Demo seed keys are left alone. +set -euo pipefail + +root="$(cd "$(dirname "$0")/.." && pwd)" +cd "$root" + +if [[ -z "${APS_BIN:-}" ]]; then + ./Scripts/build.sh -c debug + APS_BIN=".build/debug/aps" +fi +bin="$APS_BIN" + +DOGFOOD_HOME="$(mktemp -d "${TMPDIR:-/tmp}/aps-ci-dogfood.XXXXXX")" +export APS_HOME="$DOGFOOD_HOME" +cleanup() { rm -rf "$DOGFOOD_HOME"; } +trap cleanup EXIT + +"$bin" schema >/dev/null + +"$bin" key add ciStatus --type String --storage FileState --path ci-status.json --initial '' --doc 'CI lane status' +"$bin" key add ciRun --type String --storage FileState --path ci-run.json --initial '' --doc 'CI run id or branch' + +"$bin" set ciStatus starting >/dev/null +"$bin" set ciRun "${GITHUB_RUN_ID:-local}-$(uname -s)" >/dev/null + +# Fresh process: FileState must survive (State would not). +test "$("$bin" get ciStatus)" = "starting" +"$bin" set ciStatus ok >/dev/null +test "$("$bin" get ciStatus)" = "ok" + +"$bin" get ciStatus --json | grep -q '"value":"ok"' +"$bin" dump --json | grep -q '"key":"ciStatus"' +"$bin" dump --json | grep -q '"key":"ciRun"' + +# Demo keys remain available and untouched by the helper keys. +"$bin" keys | grep -q counter +"$bin" keys | grep -q ciStatus + +echo "ci-dogfood ok (APS_HOME=$APS_HOME)" diff --git a/Scripts/smoke.ps1 b/Scripts/smoke.ps1 index ff8433a..0080a66 100644 --- a/Scripts/smoke.ps1 +++ b/Scripts/smoke.ps1 @@ -56,8 +56,11 @@ function Invoke-ApsExpectFail { } } -$smokeHome = if ($env:APS_HOME) { - $env:APS_HOME +# Always isolate smoke in a fresh root. Agents/CI often export APS_HOME for +# dogfooding; reusing that root makes key-count assertions flake. Override with +# APS_SMOKE_HOME when needed. +$smokeHome = if ($env:APS_SMOKE_HOME) { + $env:APS_SMOKE_HOME } else { Join-Path ([System.IO.Path]::GetTempPath()) ("aps-smoke-" + [guid]::NewGuid().ToString('N')) } diff --git a/Scripts/smoke.sh b/Scripts/smoke.sh index ccec614..e02a2a1 100755 --- a/Scripts/smoke.sh +++ b/Scripts/smoke.sh @@ -4,7 +4,10 @@ set -euo pipefail root="$(cd "$(dirname "$0")/.." && pwd)" cd "$root" -SMOKE_HOME="${APS_HOME:-$(mktemp -d "${TMPDIR:-/tmp}/aps-smoke.XXXXXX")}" +# Always isolate smoke in a fresh root. Agents/CI often export APS_HOME for +# dogfooding; reusing that root makes `keys --quiet | wc -l` flake (demo + agent +# keys). Override explicitly with APS_SMOKE_HOME when needed. +SMOKE_HOME="${APS_SMOKE_HOME:-$(mktemp -d "${TMPDIR:-/tmp}/aps-smoke.XXXXXX")}" export APS_HOME="$SMOKE_HOME" mkdir -p "$APS_HOME" diff --git a/fledge.toml b/fledge.toml index 85ff921..761e0d5 100644 --- a/fledge.toml +++ b/fledge.toml @@ -7,6 +7,8 @@ test = "./Scripts/test.sh" test-parallel = "./Scripts/test-parallel.sh" release-build = "./Scripts/build.sh -c release" smoke = "./Scripts/smoke.sh" +# Use aps as a CI helper under a job-scoped APS_HOME (not only smoke the binary). +ci-dogfood = "./Scripts/ci-dogfood.sh" # Manifest-only: warns if `.build/release/aps` is missing (created by release/install hooks). plugin-validate = "fledge plugins validate ." # Keep specsync out of lanes.verify: Trust/SpecSync run it as a top-level gate @@ -15,5 +17,5 @@ spec = "specsync check" check = "fledge run build && fledge run test && fledge run test-parallel && fledge run smoke && fledge run plugin-validate && fledge run spec" [lanes.verify] -description = "Native quality gate (build, test, parallel isolation, smoke, plugin manifest)" -steps = ["build", "test", "test-parallel", "smoke", "plugin-validate"] +description = "Native quality gate (build, test, parallel isolation, smoke, ci-dogfood, plugin manifest)" +steps = ["build", "test", "test-parallel", "smoke", "ci-dogfood", "plugin-validate"]