Skip to content

Commit f06aa34

Browse files
jscraikcodex
andauthored
[codex] Make prepare the UI edit contract
Resolve the agent-design prepare north-star contract work into main after rebasing the PR branch through main and clearing GitHub checks. Validation: - gh pr checks 159 --repo jscraik/Design-System --watch --interval 10 -> pass - pnpm -C packages/agent-design-engine test -> pass - pnpm -C packages/cli test -> pass - AGENT_DESIGN_PREPARE_BASE=origin/main pnpm --silent agent-design:prepare:changed -> pass - pnpm docs:lint -> pass - pnpm --silent agent-design:lint -> pass - git diff --check -> pass Co-authored-by: Codex <noreply@openai.com>
1 parent 81133a3 commit f06aa34

10 files changed

Lines changed: 386 additions & 12 deletions

File tree

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- [ ] I did not push directly to `main`; this PR is from a dedicated branch.
1212
- [ ] Branch name follows policy (`codex/*` for agent-created branches).
1313
- [ ] Required local gates run: `bash scripts/validate-codestyle.sh`, `pnpm check`, `test -f memory.json && jq -e '.meta.version == "1.0" and (.preamble.bootstrap | type == "boolean") and (.preamble.search | type == "boolean") and (.entries | type == "array")' memory.json >/dev/null`.
14+
- [ ] Agent-first UI gate run when UI surfaces changed: `pnpm agent-design:prepare:changed` locally and/or via CI.
1415
- [ ] CodeRabbit review completed and findings handled (or explicitly waived).
1516
- [ ] CodeRabbit review was performed by an independent reviewer (not the coding agent).
1617
- [ ] Codex review completed and findings handled (or explicitly waived).
@@ -26,6 +27,7 @@
2627
- Command: `bash scripts/validate-codestyle.sh` -> pass/fail
2728
- Command: `pnpm check` -> pass/fail
2829
- Command: `test -f memory.json && jq -e '.meta.version == "1.0" and (.preamble.bootstrap | type == "boolean") and (.preamble.search | type == "boolean") and (.entries | type == "array")' memory.json >/dev/null` -> pass/fail
30+
- Command: `pnpm agent-design:prepare:changed` -> pass/fail/n.a. (required locally or via CI when UI surfaces changed)
2931
- Any other command(s):
3032

3133
## Review artifacts

.github/workflows/ci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ jobs:
7676
id: apps-sdk-change
7777
run: node scripts/check-apps-sdk-ui-version.mjs
7878

79+
- name: Agent design prepare evidence (web platform PR only)
80+
if: github.event_name == 'pull_request' && matrix.platform == 'web'
81+
env:
82+
AGENT_DESIGN_PREPARE_BASE: origin/${{ github.base_ref }}
83+
run: pnpm agent-design:prepare:changed
84+
7985
- name: Run Apps SDK UI drift tests
8086
if: steps.apps-sdk-change.outputs.changed == 'true'
8187
run: pnpm test:drift

FORJAMIE.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
| --- | --- | --- |
2525
| Build / CI | Yellow | Focused policy, token, matrix, docs, guidance, whitespace, browser, widget a11y, and aggregate build gates pass for the Agent Design Engine slice |
2626
| Tests | Yellow | Agent-design and release-readiness gates pass (`agent-design-engine`, `cli`, `design-system-guidance`, web E2E, widget a11y, and root build), including fixture-backed CLI JSON/recovery/migration coverage |
27-
| Agent Design Prepare plan | Review green; merge-blocked pending required checks | Reviewer loop is green after wrapper/read-only classification, JSON-safe wrapper, matrix evidence, machine locators, and resolved-vs-deferred spec decisions were tightened; PR #160 remains under heartbeat monitoring until required checks pass |
27+
| Agent Design Prepare plan | Review green; merge-blocked pending required checks | Reviewer loop is green after wrapper/read-only classification, JSON-safe wrapper, matrix evidence, machine locators, and resolved-vs-deferred spec decisions were tightened; PR #159 now carries the prepare contract plus changed-surface evidence gate |
2828
| Security | Clean | 13 CVEs patched; GitHub Actions SHA-pinned |
29-
| Open PRs | 1 | PR #160 carries the agent-design prepare contract hardening slice |
29+
| Open PRs | 1 | PR #159 carries the agent-design prepare north-star and changed-surface gate slice |
3030
| Blockers | None | |
3131
<!-- STATUS_END -->
3232

@@ -212,12 +212,17 @@ See also: `~/.codex/instructions/Learnings.md`
212212
- `pnpm agent-design:proposals` now blocks silent enforced-route and uncovered lifecycle promotion, but the first waiver registry intentionally grandfathered existing ProductComposition and ChatShell gaps. Those waivers should be replaced by accepted proposal records or per-export coverage before expiry.
213213
- `@brainwav/design-system-guidance` imports the public `@brainwav/agent-design-engine` package export, whose package types resolve through `dist`. Its build and type-check scripts must build the sibling engine package first, or clean CI installs can fail before the guidance checks run.
214214
- `pnpm --silent agent-design:prepare --surface <path>` depends on built `packages/agent-design-engine`, `packages/design-system-guidance`, and `packages/skill-ingestion` artifacts because the CLI imports those workspace packages through package exports. Keep it aligned with `pnpm agent-design:lint` by building those packages before building the CLI. The wrapper appends `--json` itself and does not include a default surface; callers provide `--surface` explicitly. The wrapper is build-backed convenience; the read-only contract belongs to the underlying `astudio design prepare` operation once the CLI is available. Use `--silent` whenever an agent or script captures JSON, because plain `pnpm` writes lifecycle banners to stdout.
215+
- `pnpm agent-design:prepare:changed` is the agent-first PR/local evidence gate. It builds the prepare dependencies, discovers changed `.tsx`/`.jsx` UI surfaces under the protected app/widget trees, runs the read-only CLI prepare operation for each surface, and fails closed when a payload is unsafe, incomplete, unparseable, or points outside the repository. Use `-- --surface <path>` to force a single-surface check. GitHub Actions also runs this gate on pull requests in the web platform lane with `AGENT_DESIGN_PREPARE_BASE` pointed at the PR base ref.
215216
- `pnpm quality-debt:report` is warn-first by design. Amber/red radar posture is release-owner evidence, not a new hard-fail gate, until explicit thresholds are approved.
216217
- Quality-debt radar CLI output now includes `service:"quality-debt-radar"` on status/error lines, and flag parsing fails fast when `--output`, `--date`, or `--week` are missing values.
217218
- The next agent-native design-system hardening lane is specified broadly in `docs/specs/2026-04-28-agent-native-design-system-spec.md` and narrowed by `docs/specs/2026-04-30-agent-design-prepare-north-star-spec.md`. The north-star rule is that no protected UI change is ready until `astudio design prepare --surface <path> --json` returns `safeForAutomaticImplementation: true`, or the PR explains the proposal/manual decision required. The focused execution source for this lane is now `docs/plans/2026-04-30-agent-design-prepare-north-star-plan.md`; use the older `docs/plans/2026-04-28-agent-native-design-system-plan.md` only for broader historical context and adjacent non-prepare slices.
218219

219220
## Recent changes
220221

222+
### 2026-05-02
223+
224+
- **PR #159 merge conflict resolution**: rebased the changed-surface evidence gate onto the merged Agent Design Prepare hardening from `main`. The branch now keeps the newer prepare parser/schema/token-contract behavior from `main`, while preserving `pnpm agent-design:cli:prebuild`, `pnpm agent-design:prepare:changed`, the web CI evidence step, PR template checklist, README/workflow docs, and CLI tests that prove the gate builds the prepare stack before checking changed protected UI surfaces.
225+
221226
### 2026-04-30
222227

223228
- **Agent Design Prepare north-star spec**: added `docs/specs/2026-04-30-agent-design-prepare-north-star-spec.md` as the focused HE standard spec for making `astudio design prepare --surface <path> --json` the project front door before AI agents edit UI. The spec keeps the current engine/CLI/guidance package boundaries, requires `designTokenContract` in the prepare payload, adds deterministic design error codes, tightens `astudio.design.prepare.v1` schema expectations, keeps returned validation commands read-only by default, and defers the human Design Prepare Inspector to a companion UI spec before implementation. The spec was then deepened with interface alternatives, selected Shape A (`prepare` in place), token source priority from runtime theme slots and token aliases, additional failure classes, observability fields, and a first-plan sequence. Follow-ups clarified that `pnpm --silent agent-design:prepare --surface <path> --json` is the JSON-safe build-backed wrapper, while `astudio design prepare` is the read-only contract; updated the wrapper to build engine, guidance, and skill-ingestion workspace dependencies before the CLI without baking in a colliding default surface; and moved wrapper reliability/classification to the first recommended planning step so future planning does not defer that gate.

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,20 @@ pnpm --silent agent-design:prepare --surface <path>
128128

129129
That wrapper may build local workspace packages before invoking the CLI. The read-only operation contract belongs to `astudio design prepare` itself once the CLI is available. Use `pnpm --silent` when a script or agent needs to capture the JSON payload, because plain `pnpm` adds lifecycle banners to stdout. Supporting commands such as `astudio design lint`, `export`, `components`, `coverage`, and `propose-abstraction` are diagnostics rather than the normal pre-edit happy path.
130130

131+
Before PR handoff for protected UI changes, run the changed-surface evidence gate:
132+
133+
```bash
134+
pnpm agent-design:prepare:changed
135+
```
136+
137+
For a targeted local check, pass one or more explicit surfaces through the gate:
138+
139+
```bash
140+
pnpm agent-design:prepare:changed -- --surface <path>
141+
```
142+
143+
CI runs the changed-surface gate on pull requests in the web platform lane, using the PR base ref as the comparison point. That makes the prepare evidence rule automatic for UI changes while keeping the direct `astudio design prepare` operation read-only.
144+
131145
## Verify
132146

133147
- Widget Gallery: open <http://localhost:5173/>

docs/guides/AGENT_DESIGN_WORKFLOW.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ astudio design prepare --surface <path> --json
2828
1. In this repo, the clean-checkout convenience wrapper is:
2929

3030
```bash
31-
pnpm --silent agent-design:prepare --surface <path> --json
31+
pnpm --silent agent-design:prepare --surface <path>
3232
```
3333

3434
The wrapper is build-backed setup. It may build `packages/agent-design-engine`, `packages/design-system-guidance`, `packages/skill-ingestion`, and `packages/cli` before invoking the CLI. The read-only operation contract belongs to `astudio design prepare` itself once the CLI is available. Use `pnpm --silent` for JSON capture, because plain `pnpm` prints lifecycle banners before script output.
@@ -37,6 +37,8 @@ The wrapper is build-backed setup. It may build `packages/agent-design-engine`,
3737
1. If implementation is safe, use the returned `recommendedRoutes`, `designTokenContract`, `requiredStates`, `relevantExamples`, `forbiddenPatterns`, and `validationCommands` as the implementation brief.
3838
1. Edit the UI.
3939
1. Run the returned read-only validation commands that apply to the changed surface.
40+
1. Before PR handoff, run `pnpm agent-design:prepare:changed`. It builds the local CLI dependencies, checks changed `.tsx`/`.jsx` UI surfaces with the read-only prepare command, and fails if any surface is unsafe or missing prepare evidence. Use `pnpm agent-design:prepare:changed -- --surface <path>` for a single surface.
41+
1. CI reruns the changed-surface gate on pull requests in the web platform lane. If it fails, treat that as a missing or unsafe prepare contract, not as a generic CI failure.
4042
1. If validation fails or a proposal-required stop appears, fix the underlying design-system evidence or open the proposal/manual decision path.
4143

4244
Supporting commands such as `astudio design lint`, `astudio design export`, `astudio design components`, `astudio design coverage`, and `astudio design propose-abstraction` are diagnostics. They are not the normal happy path before UI edits.

package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"build:astudio-icons": "pnpm -C packages/astudio-icons build",
2222
"build:astudio-json-render": "pnpm -C packages/json-render build",
2323
"build:astudio": "pnpm build:astudio-tokens && pnpm build:astudio-ui && pnpm build:astudio-icons && pnpm build:astudio-json-render",
24-
"skill-ingestion:build": "pnpm -C packages/skill-ingestion build",
24+
"skill-ingestion:build": "pnpm -C packages/skill-ingestion clean && pnpm -C packages/skill-ingestion build",
2525
"design-system-guidance:build": "pnpm -C packages/design-system-guidance build",
2626
"design-system-guidance:type-check": "pnpm -C packages/design-system-guidance type-check",
2727
"design-system-guidance:check": "pnpm -C packages/design-system-guidance run build && node packages/design-system-guidance/dist/cli.js check .",
@@ -39,7 +39,9 @@
3939
"agent-design:boundaries": "node scripts/check-agent-design-boundaries.mjs",
4040
"agent-design:boundaries:self-test": "node scripts/check-agent-design-boundaries.mjs --self-test",
4141
"agent-design:proposals": "pnpm agent-design:build && node scripts/check-agent-design-proposals.mjs",
42-
"agent-design:prepare": "pnpm agent-design:build && pnpm design-system-guidance:build && pnpm skill-ingestion:build && pnpm -C packages/cli build && node packages/cli/dist/index.js design prepare --json",
42+
"agent-design:cli:prebuild": "pnpm agent-design:build && pnpm design-system-guidance:build && pnpm skill-ingestion:build && pnpm -C packages/cli build",
43+
"agent-design:prepare": "pnpm agent-design:cli:prebuild && node packages/cli/dist/index.js design prepare --json",
44+
"agent-design:prepare:changed": "pnpm agent-design:cli:prebuild && node scripts/check-agent-design-prepare-evidence.mjs",
4345
"agent-design:prepare:smoke": "pnpm --silent agent-design:prepare --surface packages/ui/src/app/settings/AppsPanel/AppsPanel.tsx",
4446
"tracked-ignored:check": "node scripts/check-tracked-ignored-artifacts.mjs",
4547
"tracked-ignored:check:self-test": "node scripts/check-tracked-ignored-artifacts.mjs --self-test",
@@ -128,7 +130,7 @@
128130
"agent-design:build": "pnpm -C packages/agent-design-engine build",
129131
"agent-design:type-check": "pnpm -C packages/agent-design-engine type-check",
130132
"agent-design:test": "pnpm -C packages/agent-design-engine test",
131-
"agent-design:lint": "pnpm agent-design:build && pnpm design-system-guidance:build && pnpm skill-ingestion:build && pnpm -C packages/cli build && node packages/cli/dist/index.js design lint --file DESIGN.md --json"
133+
"agent-design:lint": "pnpm agent-design:cli:prebuild && node packages/cli/dist/index.js design lint --file DESIGN.md --json"
132134
},
133135
"devDependencies": {
134136
"@argos-ci/cli": "^3.0.6",

packages/agent-design-engine/src/token-contract.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,11 @@ function stripCssComments(content: string): string {
158158
* Preserves newlines from removed comments so original line positions remain aligned and keeps escaped quotes inside string/template literals intact.
159159
*
160160
* @param content - Source JavaScript/TypeScript text to strip comments from
161-
* @returns The input text with `//` and `/* */` comments removed while leaving quoted and template-literal content unchanged
161+
* @returns The input text with line and block comments removed while leaving quoted and template-literal content unchanged
162162
*/
163163
function stripJsTsComments(content: string): string {
164164
let result = "";
165-
let quote: "'" | '"' | "`" | undefined;
165+
let quote: string | undefined;
166166
let escaped = false;
167167

168168
for (let index = 0; index < content.length; index += 1) {
@@ -183,7 +183,7 @@ function stripJsTsComments(content: string): string {
183183
}
184184
continue;
185185
}
186-
if (character === "'" || character === '"' || character === "`") {
186+
if (character === "'" || character === '"' || character.charCodeAt(0) === 96) {
187187
quote = character;
188188
result += character;
189189
continue;

packages/cli/tests/cli.test.mjs

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,7 @@ test("prepare command schema rejects missing north-star payload fields", async (
561561
);
562562

563563
const invalidRoute = cloneJson(payload);
564+
assert.ok(invalidRoute.data.recommendedRoutes[0], "prepare fixture should include a route");
564565
invalidRoute.data.recommendedRoutes[0].unexpectedFutureDrift = { bad: true };
565566
assert.equal(
566567
validateDesignCommandEnvelope(invalidRoute),
@@ -598,21 +599,33 @@ test("prepare command schema rejects missing north-star payload fields", async (
598599
test("root prepare wrapper builds CLI dependencies before prepare", () => {
599600
const packageJson = JSON.parse(fs.readFileSync(path.join(repoRoot, "package.json"), "utf8"));
600601
const prepareScript = packageJson.scripts["agent-design:prepare"];
602+
const prebuildScript = packageJson.scripts["agent-design:cli:prebuild"];
601603
assert.equal(typeof prepareScript, "string");
604+
assert.equal(typeof prebuildScript, "string");
602605
assert.equal(
603606
prepareScript.includes("--surface"),
604607
false,
605608
"root prepare wrapper must not bake in a default surface",
606609
);
607610

608-
const expectedSegments = [
611+
const expectedPrebuildSegments = [
609612
"pnpm agent-design:build",
610613
"pnpm design-system-guidance:build",
611614
"pnpm skill-ingestion:build",
612615
"pnpm -C packages/cli build",
613-
"node packages/cli/dist/index.js design prepare --json",
614616
];
615617
let previousIndex = -1;
618+
for (const segment of expectedPrebuildSegments) {
619+
const index = prebuildScript.indexOf(segment);
620+
assert.ok(index > previousIndex, `${segment} must appear after the prior prebuild step`);
621+
previousIndex = index;
622+
}
623+
624+
const expectedSegments = [
625+
"pnpm agent-design:cli:prebuild",
626+
"node packages/cli/dist/index.js design prepare --json",
627+
];
628+
previousIndex = -1;
616629
for (const segment of expectedSegments) {
617630
const index = prepareScript.indexOf(segment);
618631
assert.ok(index > previousIndex, `${segment} must appear after the prior wrapper step`);
@@ -625,6 +638,55 @@ test("root prepare wrapper builds CLI dependencies before prepare", () => {
625638
);
626639
});
627640

641+
test("root changed-surface prepare gate builds dependencies before evidence check", () => {
642+
const packageJson = JSON.parse(fs.readFileSync(path.join(repoRoot, "package.json"), "utf8"));
643+
const prepareChangedScript = packageJson.scripts["agent-design:prepare:changed"];
644+
const prebuildScript = packageJson.scripts["agent-design:cli:prebuild"];
645+
assert.equal(typeof prepareChangedScript, "string");
646+
assert.equal(typeof prebuildScript, "string");
647+
648+
const expectedPrebuildSegments = [
649+
"pnpm agent-design:build",
650+
"pnpm design-system-guidance:build",
651+
"pnpm skill-ingestion:build",
652+
"pnpm -C packages/cli build",
653+
];
654+
let previousIndex = -1;
655+
for (const segment of expectedPrebuildSegments) {
656+
const index = prebuildScript.indexOf(segment);
657+
assert.ok(index > previousIndex, `${segment} must appear after the prior prebuild step`);
658+
previousIndex = index;
659+
}
660+
661+
const expectedSegments = [
662+
"pnpm agent-design:cli:prebuild",
663+
"node scripts/check-agent-design-prepare-evidence.mjs",
664+
];
665+
previousIndex = -1;
666+
for (const segment of expectedSegments) {
667+
const index = prepareChangedScript.indexOf(segment);
668+
assert.ok(
669+
index > previousIndex,
670+
`${segment} must appear after the prior prepare evidence step`,
671+
);
672+
previousIndex = index;
673+
}
674+
675+
const gateSource = fs.readFileSync(
676+
path.join(repoRoot, "scripts", "check-agent-design-prepare-evidence.mjs"),
677+
"utf8",
678+
);
679+
assert.match(gateSource, /packages\/ui\/src\//);
680+
assert.match(gateSource, /platforms\/web\/apps\/web\/src\//);
681+
assert.match(gateSource, /safeForAutomaticImplementation === true/);
682+
assert.match(gateSource, /surface is outside the repository/);
683+
684+
const ciWorkflow = fs.readFileSync(path.join(repoRoot, ".github", "workflows", "ci.yml"), "utf8");
685+
assert.match(ciWorkflow, /Agent design prepare evidence \(web platform PR only\)/);
686+
assert.match(ciWorkflow, /AGENT_DESIGN_PREPARE_BASE: origin\/\$\{\{ github\.base_ref \}\}/);
687+
assert.match(ciWorkflow, /pnpm agent-design:prepare:changed/);
688+
});
689+
628690
test("design command error fixtures expose stable recovery payloads", async (t) => {
629691
for (const fixture of designCommandFixtures.errors) {
630692
await t.test(fixture.name, async () => {

packages/skill-ingestion/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"build": "tsc -p tsconfig.build.json",
2020
"type-check": "tsc -p tsconfig.json --noEmit",
2121
"test": "vitest run",
22-
"clean": "rm -rf dist"
22+
"clean": "rm -rf dist node_modules/.tmp/tsconfig.tsbuildinfo"
2323
},
2424
"devDependencies": {
2525
"@types/node": "^25.2.0",

0 commit comments

Comments
 (0)