code-foundry 1.12.0 → 1.14.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.
@@ -41,13 +41,14 @@ This repository uses the `direct` workflow. Topic pull requests target `main`.
41
41
  - Open every ordinary pull request as a draft. Use `gh pr create --draft` or
42
42
  set `draft: true` in the GitHub API; never create a ready ordinary pull
43
43
  request as a shortcut.
44
- - Keep ordinary pull requests in draft while making commits. The generated
45
- Draft Guard resets a ready ordinary pull request to draft on creation,
46
- reopening, or a new commit, and runner-heavy validation starts only after an
44
+ - Keep ordinary pull requests in draft while preparing them. The generated
45
+ Draft Guard converts ready ordinary pull requests to draft when they are
46
+ opened or reopened, and runner-heavy validation starts only after an
47
47
  explicit `ready_for_review` transition.
48
48
  - Run local validation and finish review preparation before marking an ordinary
49
- pull request ready. After any later commit, mark it ready again only after
50
- the current head is ready for review.
49
+ pull request ready. Ready pull requests stay ready when new commits arrive,
50
+ and validation reruns for the current head; draft updates allocate no
51
+ validation runner until the pull request is ready.
51
52
  - Release Please version pull requests are managed by the Code Foundry release
52
53
  workflow; do not manually change their draft state unless the workflow asks.
53
54
 
@@ -183,7 +184,7 @@ Keep pull requests focused and reviewable. Include screenshots or recordings for
183
184
  | Push to a working branch | Draft PR workflow |
184
185
  | Push to `main` | Release workflow plus default-branch CodeQL scan; validation ran on the merged PR |
185
186
 
186
- Draft pull requests do not start validation. The lightweight Draft Guard also converts ordinary pull requests opened, reopened, or updated while ready back to draft; it never checks out pull-request code and it excludes Release Please version heads, whose release workflow owns their state. Marking a pull request ready for review starts the applicable validation tier. Convert it back to draft after an update, then mark it ready again after every update so the required checks attach to the current head. Converting it to draft runs only the lightweight cancellation control.
187
+ Draft pull requests do not start validation. The lightweight Draft Guard converts ordinary pull requests opened or reopened while ready back to draft; it never checks out pull-request code and it excludes Release Please version heads, whose release workflow owns their state. Marking a pull request ready for review starts the applicable validation tier, and each new commit on a ready pull request reruns that tier for the current head. Draft updates allocate no validation runner. Converting a pull request to draft runs only the lightweight cancellation control.
187
188
 
188
189
  Pull-request validation keys concurrency by event and pull-request head, so a newer update cancels its superseded run. Scheduled and manual audits use a separate caller pinned to the protected default branch; this prevents caller-selected runtime code from executing with default-branch cache access. Pull-request and scheduled/manual callers use the mode-aware orchestrator, which fans out only the required jobs and concludes with the stable aggregate gate. Main pushes run the default-branch CodeQL lane separately.
189
190
 
@@ -8,7 +8,6 @@ on:
8
8
  types:
9
9
  - opened
10
10
  - reopened
11
- - synchronize
12
11
 
13
12
  permissions:
14
13
  pull-requests: write
@@ -55,8 +54,8 @@ jobs:
55
54
  ;;
56
55
  esac
57
56
 
58
- # A newer state transition or commit superseded this event. Do not
59
- # undo a user's later explicit readiness decision with a stale event.
57
+ # A newer state transition superseded this event. Do not undo a
58
+ # user's later explicit readiness decision with a stale event.
60
59
  if [ "$head_sha" != "$EVENT_HEAD_SHA" ] || [ "$updated_at" != "$EVENT_UPDATED_AT" ]; then
61
60
  echo 'A newer pull-request state or head commit superseded this draft-guard event; leaving the current state unchanged.'
62
61
  exit 0
@@ -76,4 +75,4 @@ jobs:
76
75
  "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER" \
77
76
  -F draft=true \
78
77
  --silent >/dev/null
79
- echo "Converted ordinary pull request #$PR_NUMBER to draft; runner-heavy validation waits for ready_for_review."
78
+ echo "Converted ordinary pull request #$PR_NUMBER to draft; validation waits for ready_for_review."
@@ -5,6 +5,7 @@ on:
5
5
  branches: [main, staging]
6
6
  types:
7
7
  - ready_for_review
8
+ - synchronize
8
9
  workflow_dispatch:
9
10
 
10
11
  permissions:
@@ -13,7 +14,7 @@ permissions:
13
14
  jobs:
14
15
  detect:
15
16
  name: OpenCode Security / Detect
16
- if: vars.CI_BILLING_PAUSED != 'true'
17
+ if: vars.CI_BILLING_PAUSED != 'true' && (github.event_name == 'workflow_dispatch' || github.event.pull_request.draft == false)
17
18
  runs-on: ubuntu-slim
18
19
  outputs:
19
20
  enabled: ${{ steps.detect.outputs.enabled }}
@@ -7,6 +7,7 @@ on:
7
7
  branches: [main, staging]
8
8
  types:
9
9
  - ready_for_review
10
+ - synchronize
10
11
 
11
12
  # Default every caller job to no repository permissions. Individual jobs grant
12
13
  # only the scopes their own validation path consumes.
@@ -20,9 +21,10 @@ concurrency:
20
21
  jobs:
21
22
  mode:
22
23
  name: Mode
23
- # The mode classifier is only needed for pull requests. Main pushes use
24
- # the dedicated default-branch CodeQL lane below.
25
- if: vars.CI_BILLING_PAUSED != 'true' && github.event_name == 'pull_request'
24
+ # The mode classifier is only needed for ready pull requests. Main pushes
25
+ # use the dedicated default-branch CodeQL lane below; draft updates do not
26
+ # allocate a validation runner.
27
+ if: vars.CI_BILLING_PAUSED != 'true' && github.event_name == 'pull_request' && github.event.pull_request.draft == false
26
28
  runs-on: ubuntu-slim
27
29
  timeout-minutes: 10
28
30
  permissions:
@@ -62,7 +64,7 @@ jobs:
62
64
  validation:
63
65
  name: Validation
64
66
  needs: mode
65
- if: vars.CI_BILLING_PAUSED != 'true' && github.event_name == 'pull_request'
67
+ if: vars.CI_BILLING_PAUSED != 'true' && github.event_name == 'pull_request' && github.event.pull_request.draft == false
66
68
  # Reusable workflows can only maintain or reduce the caller job's scopes.
67
69
  # The audit tier needs security-events: write for CodeQL uploads.
68
70
  permissions:
package/AGENTS.md CHANGED
@@ -103,13 +103,14 @@ This repository uses the `direct` workflow. Topic pull requests target `main`.
103
103
  - Open every ordinary pull request as a draft. Use `gh pr create --draft` or
104
104
  set `draft: true` in the GitHub API; never create a ready ordinary pull
105
105
  request as a shortcut.
106
- - Keep ordinary pull requests in draft while making commits. The generated
107
- Draft Guard resets a ready ordinary pull request to draft on creation,
108
- reopening, or a new commit, and runner-heavy validation starts only after an
106
+ - Keep ordinary pull requests in draft while preparing them. The generated
107
+ Draft Guard converts ready ordinary pull requests to draft when they are
108
+ opened or reopened, and runner-heavy validation starts only after an
109
109
  explicit `ready_for_review` transition.
110
110
  - Run local validation and finish review preparation before marking an ordinary
111
- pull request ready. After any later commit, mark it ready again only after
112
- the current head is ready for review.
111
+ pull request ready. Ready pull requests stay ready when new commits arrive,
112
+ and validation reruns for the current head; draft updates allocate no
113
+ validation runner until the pull request is ready.
113
114
  - This contract is mandatory for every agent scope. Nested `AGENTS.md` files
114
115
  may add stricter rules but must not weaken or replace it.
115
116
  - Release Please version pull requests are managed by the Code Foundry release
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.14.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.13.0...v1.14.0) (2026-09-09)
4
+
5
+
6
+ ### Features
7
+
8
+ * **cli:** add shared validation plans and agent check evidence ([#538](https://github.com/0xPlayerOne/code-foundry/issues/538)) ([95af9ed](https://github.com/0xPlayerOne/code-foundry/commit/95af9ed42682ff3ed1dc74609ea4628d0c95a799))
9
+
10
+ ## [1.13.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.12.0...v1.13.0) (2026-09-09)
11
+
12
+
13
+ ### Features
14
+
15
+ * **fleet:** add declared inventory and resumable canary rollouts ([#536](https://github.com/0xPlayerOne/code-foundry/issues/536)) ([6aa86d4](https://github.com/0xPlayerOne/code-foundry/commit/6aa86d4cd85cdbd4041c70d8c01d8e351e21fc0b))
16
+
3
17
  ## [1.12.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.11.0...v1.12.0) (2026-09-09)
4
18
 
5
19
 
package/README.md CHANGED
@@ -76,12 +76,13 @@ The standard workflow triggers are:
76
76
 
77
77
  Automated feature/fix and staging-promotion pull requests open as drafts.
78
78
  The trusted Draft Guard is a fallback for manually created or reopened ready
79
- PRs and for new commits to ordinary ready PRs: it converts them to drafts
80
- without checking out PR code. It verifies the event head and update timestamp
81
- before changing state, and excludes Release Please version PRs whose release
82
- workflow owns readiness. Pull-request validation runs only on the
83
- ready-for-review transition. Converting a PR to draft runs only the lightweight
84
- cancellation control. Scheduled and manually dispatched audits are unaffected.
79
+ PRs: it converts them to drafts without checking out PR code. It verifies the
80
+ event head and update timestamp before changing state, and excludes Release
81
+ Please version PRs whose release workflow owns readiness. Pull-request
82
+ validation runs on the ready-for-review transition and on new commits while a
83
+ PR remains ready; draft updates allocate no validation runner. Converting a PR
84
+ to draft runs only the lightweight cancellation control. Scheduled and manually
85
+ dispatched audits are unaffected.
85
86
 
86
87
  Jobs are language-aware and skip irrelevant setup inside the applicable
87
88
  aggregate checks. TypeScript uses Oxlint, Oxfmt, and Bun's native
@@ -15,9 +15,9 @@ belong to the run that produced them, not the source tree.
15
15
  | Format, lint, type-check, and build | 15 s | Bound the local CI feedback loop |
16
16
  | Runtime dependencies | 0 | Keep the installed CLI dependency-free |
17
17
  | Development dependencies | 4 | Prevent unreviewed toolchain growth |
18
- | Packed artifact | 200 kB | Bound registry transfer and install cost |
19
- | Unpacked artifact | 750 kB | Bound installed footprint |
20
- | Packed files | 80 | Detect accidental release contents |
18
+ | Packed artifact | 210 kB | Bound registry transfer and install cost |
19
+ | Unpacked artifact | 820 kB | Bound installed footprint |
20
+ | Packed files | 92 | Detect accidental release contents |
21
21
 
22
22
  The performance workflow disables build-cache reads and writes for this task.
23
23
  That makes timing comparisons independent of a warm protected-branch cache and
package/docs/README.md CHANGED
@@ -14,6 +14,8 @@ its own names, environments, and deployment details.
14
14
  - [Caching and remote caching](CACHING.md)
15
15
  - [Performance budgets and baselines](PERFORMANCE.md)
16
16
  - [Required capabilities and task evidence](required-capabilities.md)
17
+ - [Agent-facing validation commands](agent-validation.md)
18
+ - [Declarative fleet inventory and staged rollouts](fleet-rollouts.md)
17
19
 
18
20
  ## Repository-specific documentation
19
21
 
package/docs/WORKFLOWS.md CHANGED
@@ -15,19 +15,19 @@ pull_request:
15
15
  # direct topology: branches: [main]
16
16
  ```
17
17
 
18
- The generated validation caller listens for `ready_for_review` and `push` to
19
- `main`. Draft pull requests register no validation checks and allocate no
20
- validation runner; main pushes run only the default-branch CodeQL lane, while
21
- full validation remains pull-request-only.
22
- A separate lightweight Draft Guard runs from the trusted base branch on
23
- `opened`, `reopened`, and `synchronize`; it converts ordinary ready pull
24
- requests back to draft without checking out pull-request code. It rechecks the
25
- current head and update timestamp before mutating state, so a stale event
26
- cannot undo a later draft or ready transition. Release Please version heads are
27
- excluded because the release workflow owns their state. A separate draft-control
28
- caller listens for `converted_to_draft` and cancels queued or running
29
- pull-request workflows without creating skipped validation jobs. Marking a pull
30
- request ready again starts validation for the current head.
18
+ The generated validation caller listens for `ready_for_review` and
19
+ `synchronize`. Its jobs require the pull request to remain ready, so draft
20
+ updates allocate no validation runner; main pushes run only the default-branch
21
+ CodeQL lane, while full validation remains pull-request-only. A separate
22
+ lightweight Draft Guard runs from the trusted base branch on `opened` and
23
+ `reopened`; it converts ordinary ready pull requests back to draft without
24
+ checking out pull-request code. It rechecks the current head and update
25
+ timestamp before mutating state, so a stale event cannot undo a later draft or
26
+ ready transition. Release Please version heads are excluded because the
27
+ release workflow owns their state. A separate draft-control caller listens for
28
+ `converted_to_draft` and cancels queued or running pull-request workflows.
29
+ Marking a pull request ready starts validation, and each new commit on a ready
30
+ pull request starts it again for the current head.
31
31
 
32
32
  The separate `validation-audit.yml` caller is pinned to the configured released
33
33
  runtime and handles scheduled and manual audits:
@@ -108,7 +108,7 @@ opt in or out without a code change.
108
108
  | Security | Profile, audits, and public-only Dependency Review |
109
109
  | CodeQL | GitHub-native code scanning, kept separate from CI |
110
110
  | Draft PR | Create/update development pull requests |
111
- | Draft Guard | Keep ordinary PRs draft until `ready_for_review` |
111
+ | Draft Guard | Keep opened/reopened ordinary PRs draft until `ready_for_review` |
112
112
  | Release PR | Promote `staging` into `main` (staging-release topology only) |
113
113
  | Release | Release Please, GitHub release, and optional npm publication |
114
114
 
@@ -0,0 +1,94 @@
1
+ # Agent-facing validation commands
2
+
3
+ The public CLI now exposes a stable plan/check interface using the same discovery,
4
+ required-capability policy, ecosystem executor, and task receipts as reusable CI.
5
+
6
+ ```sh
7
+ code-foundry plan --changed --base origin/main --json
8
+ code-foundry check --tier fast --json
9
+ code-foundry check --tier audit --json
10
+ ```
11
+
12
+ Both commands accept `--target PATH`. Use the Code Foundry version pinned by the
13
+ repository, not an unreviewed floating installation. `plan` executes discovery
14
+ only: it does not install dependencies, run project checks, modify source files,
15
+ or emit skip-receipt files. Required entrypoints are validated across the complete
16
+ task set, including tasks deferred from the selected local tier.
17
+
18
+ ## Tiers and change awareness
19
+
20
+ `fast` selects formatting, linting, type checking, build, unit tests, and performance.
21
+ `audit` adds integration, E2E, and smoke tests. Ecosystem commands and applicability
22
+ come from the shared runtime; the CLI does not invent alternate test commands.
23
+ Repository-owned scripts remain authoritative. Missing required tasks fail
24
+ planning instead of returning a misleading successful subset.
25
+
26
+ `--changed` includes paths changed from the selected base, staged changes,
27
+ unstaged changes, and untracked files. Committed paths use the merge-base with
28
+ that ref, so an independently advanced base branch does not make base-only
29
+ changes look like head changes. `--base` defaults to HEAD and requires `--changed`.
30
+ Invalid or unavailable base revisions fail rather than being treated as no changes.
31
+ Paths use Git's NUL-separated format, preserving whitespace and unusual filenames.
32
+ Generated `.code-foundry/` evidence is excluded from change annotations. Change awareness is **annotation-only**: without a verified dependency
33
+ graph it does not skip required tasks or assume a documentation change cannot
34
+ affect a custom command.
35
+
36
+ Local tiers are not a replacement for the complete GitHub Validation / Gate.
37
+ Security scans, CodeQL, release-diff policy where applicable, protected-environment
38
+ checks, and required reviews remain separate. Every plan/result explicitly marks
39
+ remote validation as required. A fast result also names deferred local tasks.
40
+ A local audit result is not permission to mark a PR ready or merge it.
41
+
42
+ ## Execution and evidence
43
+
44
+ Install the repository's locked dependencies through its normal setup process
45
+ before running checks. This CLI does not add an implicit install step or grant
46
+ credentials. It runs trusted repository scripts in the existing environment;
47
+ those scripts are not sandboxed and retain their normal tool/network behavior.
48
+ The formatter/runtime's existing semantics are unchanged: a configured command
49
+ that rewrites files still rewrites files. Prefer check-only scripts in CI.
50
+
51
+ Task stdout/stderr goes to stderr, keeping `--json` stdout parseable. Each selected
52
+ applicable task runs through the public runtime. A zero exit without a fresh,
53
+ matching, successful task receipt fails. A failed task blocks remaining applicable
54
+ tasks; optional inapplicable tasks are reported as skipped. An entirely skipped
55
+ check is labeled `skipped`, never `passed`.
56
+
57
+ A run stores `.code-foundry/agent-results/check-*/summary.json` and snapshots of
58
+ its task receipts. The result includes the source commit, dirty-tree indication,
59
+ selected/deferred tasks, reasons, exit codes, signals, receipt paths, and repository
60
+ artifact paths such as coverage or browser evidence. HEAD identifies the base
61
+ commit; a dirty working tree is not a cryptographically identified immutable
62
+ source snapshot. Reports are local evidence, not signed provenance.
63
+
64
+ The aggregate and task receipts are retained per run so later checks do not
65
+ overwrite the earlier JSON evidence. Artifact paths inside receipts point to
66
+ repository-owned files and may be overwritten by subsequent test runs; copy them
67
+ into a CI artifact for long-term retention. Do not upload the whole hidden
68
+ repository tree or secrets. The CLI neither captures environment variables into
69
+ reports nor grants publish/merge/deploy access.
70
+
71
+ An exclusive local `agent-results/active.lock` prevents overlapping agent checks
72
+ from confusing receipts. After a killed process, inspect the checkout and confirm
73
+ there is no active check before manually removing a stale lock. Normal completion
74
+ and failures clean the lock. This is a local CLI lock, not a distributed lock
75
+ against every other tool writing into the repository.
76
+
77
+ `--timeout SECONDS` bounds each check subprocess (default 600, range 1–3600).
78
+ A timeout or missing receipt fails. Project scripts remain responsible for
79
+ cleaning up their own servers and subprocesses. Plans do not accept an execution
80
+ timeout. Unknown, duplicate, or ignored arguments fail rather than silently alter
81
+ validation behavior.
82
+
83
+ ## Integration and tests
84
+
85
+ This change depends on the required-capabilities/task-evidence runtime change.
86
+ It deliberately imports shared policy instead of maintaining a competing copy.
87
+ Merge that prerequisite before this CLI change and retain `runtime-core.mjs` when
88
+ vendoring the runtime.
89
+
90
+ Run `node --test test/agent-check.test.mjs`. Tests exercise real Git change
91
+ inspection and the actual policy/evidence wrapper with a deterministic ecosystem
92
+ executor, including read-only planning, required deferred tasks, failed commands,
93
+ stale evidence, receipt snapshots, locking, and separation of JSON from task logs.
94
+ Full ecosystem dependencies and GitHub-side checks still need their own CI run.
@@ -0,0 +1,139 @@
1
+ # Declarative fleet inventory and staged rollouts
2
+
3
+ Place `code-foundry-fleet.json` in the directory passed to `--root`. Its presence
4
+ opts that fleet into inventory-based discovery and controlled upgrades, without
5
+ changing legacy directory discovery for existing users.
6
+
7
+ ```json
8
+ {
9
+ "schemaVersion": 1,
10
+ "cohorts": ["canary", "applications"],
11
+ "repositories": [
12
+ {
13
+ "repository": "owner/package-canary",
14
+ "path": "packages/package-canary",
15
+ "cohort": "canary",
16
+ "profile": "published-package",
17
+ "expected": { "git_workflow": "direct" },
18
+ "requiredCapabilities": ["unit", "performance"],
19
+ "validation": [
20
+ ["bun", "install", "--frozen-lockfile"],
21
+ ["bun", "run", "test:unit"],
22
+ ["bun", "run", "test:consumer"],
23
+ ["bun", "run", "performance:check"]
24
+ ],
25
+ "requiredChecks": ["Validation / Gate"]
26
+ },
27
+ {
28
+ "repository": "owner/application",
29
+ "path": "applications/application",
30
+ "cohort": "applications",
31
+ "validation": [
32
+ ["bun", "install", "--frozen-lockfile"],
33
+ ["bun", "run", "type-check"],
34
+ ["bun", "run", "test:unit"]
35
+ ],
36
+ "requiredChecks": ["Validation / Gate"]
37
+ }
38
+ ]
39
+ }
40
+ ```
41
+
42
+ Repository names in the example are placeholders. Populate the actual fleet
43
+ before use. Paths are relative to the manifest, may be arbitrarily nested, and
44
+ must not escape through `..`, absolute paths, or symlinks. Missing checkouts and
45
+ origin mismatches remain visible as blocked inventory entries rather than silently
46
+ disappearing. There is no automatic clone or repository-settings mutation.
47
+
48
+ `profile` is a descriptive inventory annotation; it does not install tools or
49
+ activate a quality profile. `expected` maps scalar `.github/code-foundry.yml` keys
50
+ to desired values; `requiredCapabilities` audits declarations in that same file.
51
+ The runtime-upgrade operation does not silently author missing capability policy.
52
+ Adopt those requirements in consumer repositories before requiring them here.
53
+
54
+ ## Commands
55
+
56
+ ```sh
57
+ code-foundry fleet status --root /path/to/fleet
58
+ code-foundry fleet upgrade --root /path/to/fleet --dry-run
59
+ code-foundry fleet upgrade --root /path/to/fleet --create-pr
60
+ ```
61
+
62
+ Run from the intended released Code Foundry installation/checkout. The existing
63
+ source-version guard still rejects mismatched `--version` requests. Manifest mode
64
+ requires `--create-pr` or `--dry-run` and never syncs original checkouts in place.
65
+ `--force` does not bypass dirty-tree safety in manifest mode. Dry-run reports
66
+ inventory, target version, and configuration drift without network calls, running
67
+ consumer commands, or modifying files. Status likewise audits local facts; it does
68
+ not pretend to verify remote branch protection or environment settings.
69
+
70
+ The first incomplete cohort is the only cohort allowed to create PRs. All
71
+ non-excepted members of each earlier cohort must have a matching managed upgrade
72
+ PR that is merged, successful explicitly named required checks on its head SHA,
73
+ no still-pending/failed checks, and the target runtime/configuration still present
74
+ on its current base branch. Neutral/skipped required checks do not qualify.
75
+ Unknown, inaccessible, closed-without-merge, stale, or failed evidence does not
76
+ unlock subsequent cohorts. One local validation failure stops remaining work.
77
+
78
+ Each repository must supply explicit validation argv arrays. Include locked
79
+ installation, application checks, and genuine consumer compatibility tests where
80
+ relevant. No shell splitting is used. Commands run in an isolated detached
81
+ worktree, have bounded execution time, and must not rewrite the candidate source.
82
+ Validation is not a security sandbox: commands run as the invoking user with its
83
+ inherited environment and network access. Treat the manifest and every validation
84
+ command as trusted code; do not use this feature with unreviewed manifests or
85
+ credentials that the checks should not access.
86
+ Only files changed by Code Foundry sync are staged; generated test evidence and
87
+ other untracked files are not swept into the commit. A commit-hook change to the
88
+ validated Git tree is rejected before publishing.
89
+
90
+ This implementation does not create an automatic scheduler, mark PRs ready,
91
+ merge PRs, lower checks, or bypass review. After reviewing and validating canaries,
92
+ merge their PRs normally and run the fleet command again to advance the cohort.
93
+ A repository already at the target version with no managed PR does not establish
94
+ canary evidence; choose a real upgrade canary rather than treating an empty diff
95
+ as successful rollout validation.
96
+
97
+ ## Resuming and intentional exceptions
98
+
99
+ The target version and complete repository policy produce a deterministic branch
100
+ and PR marker. Repeated runs return an existing matching open PR instead of
101
+ creating duplicates. If push succeeded but PR creation failed, the next run
102
+ recognizes the managed commit and recorded tree identity, reruns consumer
103
+ validation, and creates the missing **draft** PR without force-pushing. Unknown
104
+ branches or commits with mismatched tree markers are preserved and blocked for
105
+ manual review. Local managed refs preserve committed work after a failed push.
106
+ The marker is an ownership/recovery guard, not a cryptographic signature.
107
+
108
+ PR creation is draft-first in both manifest and legacy discovery modes. A PR that
109
+ a human has already made ready is not silently converted back or modified.
110
+
111
+ An entry may include a reviewed time-limited exception:
112
+
113
+ ```json
114
+ { "exception": { "reason": "Pending consumer compatibility work", "expires": "2026-10-01" } }
115
+ ```
116
+
117
+ Exceptions appear explicitly in inventory/rollout output. Expired/invalid dates
118
+ fail parsing. The command's existing `--exclude` flag is also honored. Excluding
119
+ all canaries never satisfies a canary gate or unlocks later cohorts. Update the
120
+ manifest deliberately when cohort membership or compatibility policy changes.
121
+
122
+ ## Evidence and tests
123
+
124
+ Upgrade output is schema-versioned JSON with target version, aggregate status,
125
+ per-repository cohort/status, PR link, and local validation command exit statuses.
126
+ Failed command output is not copied into reports, avoiding accidental credentials
127
+ in logs; reproduce the declared command locally for full debugging output. A
128
+ failed rollout returns a nonzero exit status. Pending PRs are not failures and do
129
+ not grant permission to advance a cohort. Worktree cleanup failures preserve the
130
+ isolated path and report it rather than deleting unknown paths.
131
+
132
+ `node --test test/fleet-manifest.test.mjs` includes actual local Git repositories,
133
+ bare remotes, isolated worktrees, validation failure, orphan-branch recovery,
134
+ clean-original preservation, and canary advancement. Only GitHub responses are
135
+ fixture-backed; no real fleet repositories or remote PRs are modified by tests.
136
+
137
+ GitHub CLI contracts:
138
+ https://cli.github.com/manual/gh_pr_list
139
+ https://cli.github.com/manual/gh_pr_create
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-foundry",
3
- "version": "1.12.0",
3
+ "version": "1.14.0",
4
4
  "description": "A fast, language-aware repository factory for agent-ready workflows, testing, security, and release automation.",
5
5
  "homepage": "https://github.com/0xPlayerOne/code-foundry#readme",
6
6
  "bugs": {
package/src/cli.mjs CHANGED
@@ -16,6 +16,8 @@ Usage:
16
16
  npx code-foundry init [--target PATH]
17
17
  npx code-foundry sync [--target PATH]
18
18
  npx code-foundry doctor [--target PATH]
19
+ npx code-foundry plan [--target PATH] [--tier fast|audit] [--changed] [--base REF] [--json]
20
+ npx code-foundry check [--target PATH] [--tier fast|audit] [--changed] [--base REF] [--timeout SECONDS] [--json]
19
21
  npx code-foundry ci pause|resume|status [--target PATH]
20
22
  npx code-foundry release reconcile [--github] [--base BRANCH] [--head BRANCH]
21
23
  npx code-foundry release hook --tag TAG --workflow WORKFLOW
@@ -124,6 +126,11 @@ function parseArgs(argv) {
124
126
  }
125
127
 
126
128
  async function main() {
129
+ if (['plan', 'check'].includes(process.argv[2])) {
130
+ const { agentCommand } = await import('./commands/agent-check.mjs')
131
+ process.exitCode = agentCommand(process.argv.slice(2))
132
+ return
133
+ }
127
134
  const { command, options } = parseArgs(process.argv.slice(2))
128
135
  const target = resolve(options.target)
129
136