Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

finding(create-plugin): the scaffolder emits a per-package vitest test block — the shape objectui#3240 just removed from this repo #7524

Closed

Description

@claude

Found while implementing objectui#3240 (PR #7523), which deletes every per-package vitest.config.* and closes the route Vitest takes when a directory has none — it falls back to that directory's vite.config.*. Every packages/PKG/vite.config.ts now calls assertCanonicalVitestInvocation, gated on process.env.VITEST.

@object-ui/create-plugin scaffolds the shape that route exists to refuse. packages/create-plugin/src/templates.ts emits, for a new plugin:

  • a vite.config.ts carrying a test block (globals, environment, setupFiles: [./vitest.setup.ts]),
  • a vitest.setup.ts, and
  • "test": "vitest run" in the manifest.

For the scaffolder's actual audience — someone building a plugin in their OWN repo — that output is correct and should not change. The gap is narrower: a plugin scaffolded into this monorepo lands as a workspace package whose test entry is a package-cwd vitest run against a divergent local config, with nothing to refuse it. That is exactly the class objectui#5406 and objectui#3240 spent two cards closing, arriving through the scaffolder.

⚠️ Not measured: whether anyone has ever scaffolded into this repo, and whether the generated test script would actually go green or loudly red. Filed as an observation, not a diagnosis.

Possible shapes (not a recommendation — this needs triage):

  • teach the scaffolder to detect an in-repo target and emit the repo's canonical vitest run --root ../.. packages/PKG/ form instead;
  • or add the generated config to whatever the in-repo guard walk covers, so a scaffolded package fails the pin rather than the reviewer;
  • or decide the in-repo case is out of scope and say so where the templates are defined.

⛔ Deliberately not fixed in PR #7523: changing the scaffolder's published output is a different blast radius from unifying this repo's own configs.


Generated by Claude Code

Activity

  1. added
    domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repo
    on Sep 3, 2026
  2. self-assigned this
    on Sep 6, 2026
  3. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    Contributor

    Claim: PM loop round R46 — a MEASUREMENT-FIRST card: the fix is conditionally authorised by what the measurement shows
    Session: session_01FhBNJcLRZLe8M87VcUgpKr
    Branch: claude/issue-7524-create-plugin-in-repo-scaffold
    Worktree: objectui-issue-7524
    Domain: domain:devx
    File surface: STEP 1 (always): a measurement, on a scratch worktree, of what happens when the scaffolder's output lands INSIDE this monorepo as a workspace package — does any existing pin or gate go red (scripts/__tests__/package-scripts-vitest-projects.test.ts, vitest-invocation-guard.test.ts, runner-package-test-entry-3746.test.ts, turbo-test-inputs.test.ts, the guard itself under VITEST), or does the scaffolded test: 'vitest run' + per-package test block go silently green? STEP 2 (conditional): if SILENT ⇒ the smallest gate fix that makes it loud — expected landing scripts/vitest-invocation-guard.mjs and/or the pin that walks package test scripts, plus its test; ⛔ NOT the scaffolder's published output (packages/create-plugin/src/templates.ts stays as it is for external plugin authors — the card's own boundary). If already LOUD ⇒ no code change; a short note where the templates are defined (templates.ts docblock) stating that in-repo scaffolding is refused by the named pin, and premise_still_valid: false-style evidence in the report. ⛔ No third shape: no in-repo target detection inside the scaffolder without a ruling (stop on breach; explain in the report)
    Container & model: M, not mechanical (the measurement decides the route; the card names three shapes and rules none), mode:subagent, model: opus — no path-derived tier mandate; default judgment tier taken
    Clause-②: no (the scaffolder's published output does not change)
    Serial constraints cleared: no triage comment on this card (labels only, from the sweep); premise on origin/main a9e6f04 at 11:55Z — templates.ts:150 emits test: 'vitest run', :234-235 a test block with environment: 'jsdom' + setupFiles; 23 packages/*/vite.config.ts call assertCanonicalVitestInvocation; zero per-package vitest.config.* on main (#3240 landed); every package test script but two (--passWithNoTests variants) is the canonical vitest run --root ../.. packages/NAME/ form; no open claude/* branch touches packages/create-plugin or the guard; same-day churn on the guard (#8002 at 08:xxZ, parseVitestArgv) — work from the merged tree; this seat's in-flight devs (#6892 s2: app-shell view tests + the vi-mock gate; #5174 b21: one README + the doc-snippet gate; PRs #8028 / #8032 converging) are disjoint. pm:queue → pm:dispatched + assignee written in one stroke at 11:56Z and read back.


    Generated by Claude Code

  4. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    Contributor

    os-dev-report

    {
      "issue": 7524,
      "status": "done",
      "branch": "claude/issue-7524-create-plugin-in-repo-scaffold",
      "pr": "https://github.com/objectstack-ai/objectui/pull/8042",
      "head": "121147911",
      "premise_still_valid": false,
      "summary": "Measurement-first card, and the measurement chose route 2(b): LOUD. The real scaffolder was built and run into packages/ of a scratch worktree; the emitted package is exactly the hazardous shape (test: 'vitest run', a vite.config test block, no vitest.config.*, zero calls to assertCanonicalVitestInvocation). Planting it turns 11 assertions red across 7 files of scripts/__tests__/ (control on the same tree with it removed: 110 files / 3323 tests, all green), four of them about the test shape specifically. So the card's first half is true (the scaffolder emits the shape objectui#3240 removed) and its second half is false: 'with nothing to refuse it' is wrong - objectui#3240 / objectui#5406 / objectui#3746 already built the refusal on the repo side, and it fires before such a package can be committed. What was genuinely missing is the record, so the only change is a docblock paragraph on buildViteConfig in packages/create-plugin/src/templates.ts naming the two pins, plus an empty-frontmatter changeset. The scaffolder's published output is byte-identical to main. One nuance worth the PM's eye: the INVOCATION is silently green (pnpm test in the scaffolded package runs with the package as vitest's root and prints no guard output at all) - it is the repo's pins, not the guard, that are loud.",
      "tests": "Control (clean tree, scratch removed, git status --porcelain empty, pnpm-lock.yaml md5 restored to 85895a3d7f8051c61b1f4803ea1b3cf7): the five named pins exit 0 'Test Files 5 passed (5) / Tests 112 passed (112)'; whole scripts/__tests__/ exit 0 'Test Files 110 passed (110) / Tests 3323 passed (3323)'. Planted: five named pins exit 1 (4 failed of 112); whole scripts/__tests__/ exit 1 (11 failed of 3323 across 7 files, 10 printing 'packages/plugin-scaffold-probe-7524' verbatim, the 11th being quick-reference-commands-4149 shifting 38 to 39 published). Gates on 121147911: type-check:scripts 0; lint:root 0 (32 warnings, 0 errors); check:entry-guard 0; check:control-bytes 0 'OK (scanned 6449 tracked text file(s); skipped 85 binary)' plus a grep -naP self-scan of both changed files with no matches; check-changeset-presence 0 ('Every one of them has an EMPTY frontmatter - declared as releasing nothing'); check-changeset-no-major 0; check-governed-queue-guard --test 0 'NOT GOVERNED'; create-plugin test 0 (19 passed), type-check 0, lint 0; check:unreferenced-sources / check:phantom-deps / check:self-import / check:published-dist 0 each. Whole scripts/__tests__/ on the final HEAD exited 1 on two check-doc-links cases with 'Error: Test timed out in 15000ms' in a 145s contended run; re-run alone on the same HEAD exit 0, 121 passed, 10.36s - a load flake, and this diff touches no markdown that gate scans. No ablation applies: no gate or guard was changed, so there is nothing whose failure needed proving.",
      "mcp_calls": "4 - one search_issues (dedup for the out-of-scope finding, non-empty so self-validating), one issue_write (filing 8041), one create_pull_request, one add_issue_comment (this report). Everything else went over git and repo-scoped REST.",
      "line_budget": "n/a - no skills/** file in the diff",
      "files_changed": [
        "packages/create-plugin/src/templates.ts (+29, docblock comment only; buildViteConfig's returned string and every other emitted artifact are byte-identical)",
        ".changeset/create-plugin-in-repo-scaffold-note-7524.md (+7, EMPTY frontmatter)"
      ],
      "gates": {
        "vitest scripts/__tests__/ (whole)": "1 on first run then 0 on isolated re-run of the flaking file - see tests",
        "pnpm type-check:scripts": 0,
        "pnpm lint:root": 0,
        "pnpm check:entry-guard": 0,
        "pnpm check:control-bytes": 0,
        "grep -naP control-byte self-scan": "no matches",
        "node scripts/check-changeset-presence.mjs": 0,
        "node scripts/check-changeset-no-major.mjs": 0,
        "node scripts/check-governed-queue-guard.mjs --test packages/create-plugin/src/templates.ts": "0 - NOT GOVERNED",
        "pnpm --filter @object-ui/create-plugin test": 0,
        "pnpm --filter @object-ui/create-plugin type-check": 0,
        "pnpm --filter @object-ui/create-plugin lint": 0,
        "check:unreferenced-sources / phantom-deps / self-import / published-dist": 0,
        "pnpm check:skill-examples": "not run, not owed - diff touches nothing under skills/, and the only skill mentions of this generator are prose plus a bash fence; that gate judges marked ts/tsx/json fences",
        "Live E2E (informational)": "red on every branch today for the upstream reason objectui#7990 - not from this change"
      },
      "step1_table": [
        { "gate": "the five named pins, CLEAN TREE (control)", "exit": 0, "verdict": "Test Files 5 passed (5); Tests 112 passed (112)", "caused_by_scaffold": "n/a - control leg" },
        { "gate": "the five named pins, scaffold planted", "exit": 1, "verdict": "Tests 4 failed, 108 passed (112)", "caused_by_scaffold": "yes - all four name the generated package" },
        { "gate": "vitest-invocation-guard.test.ts :: calls the guard from every one of them", "exit": 1, "verdict": "offender list is packages/plugin-scaffold-probe-7524/vite.config.ts", "caused_by_scaffold": "yes" },
        { "gate": "vitest-invocation-guard.test.ts :: declares no test block - a build config must not carry test semantics", "exit": 1, "verdict": "same file", "caused_by_scaffold": "yes" },
        { "gate": "vitest-invocation-guard.test.ts :: derives the repo root instead of counting dot-dot", "exit": 1, "verdict": "packages/plugin-scaffold-probe-7524/vite.config.ts calls the guard with a hand-counted repo root", "caused_by_scaffold": "yes" },
        { "gate": "runner-package-test-entry-3746.test.ts :: admits no package beyond the recorded baseline", "exit": 1, "verdict": "received [\"packages/plugin-scaffold-probe-7524\"], expected []", "caused_by_scaffold": "yes" },
        { "gate": "package-scripts-vitest-projects.test.ts", "exit": 0, "verdict": "passed with the scaffold planted", "caused_by_scaffold": "no - assumption A2 is FALSIFIED; this pin reads ROOT scripts' --project names against vitest.config.mts (objectui#7096) and never walks workspace packages" },
        { "gate": "turbo-test-inputs.test.ts", "exit": 0, "verdict": "passed with the scaffold planted", "caused_by_scaffold": "no" },
        { "gate": "unit-registry-absence-collision.test.ts", "exit": 0, "verdict": "passed with the scaffold planted", "caused_by_scaffold": "no" },
        { "gate": "pnpm exec vitest run scripts/__tests__/, CLEAN TREE (control)", "exit": 0, "verdict": "Test Files 110 passed (110); Tests 3323 passed (3323)", "caused_by_scaffold": "n/a - control leg, taken AFTER removal, which is what makes the 11 failures attributable" },
        { "gate": "pnpm exec vitest run scripts/__tests__/, scaffold planted", "exit": 1, "verdict": "Tests 11 failed, 3321 passed (3323) across 7 files", "caused_by_scaffold": "yes - 10 of 11 print the package name verbatim; the 11th is quick-reference-commands-4149 shifting 38 to 39 published packages" },
        { "gate": "pnpm --filter @object-ui/plugin-scaffold-probe-7524 test, BEFORE pnpm install", "exit": 1, "verdict": "startup error: Could not resolve 'vite-plugin-dts' / Cannot find package '@vitejs/plugin-react'", "caused_by_scaffold": "an install artifact, not a refusal - recorded so it is not misread as one" },
        { "gate": "pnpm --filter @object-ui/plugin-scaffold-probe-7524 test, AFTER pnpm install", "exit": 0, "verdict": "RUN v4.1.10 /.../packages/plugin-scaffold-probe-7524; Test Files 1 passed (1); NO guard output at all", "caused_by_scaffold": "yes - and this is the SILENT half: the invocation itself goes green with the package as vitest's root" },
        { "gate": "node scripts/vitest-invocation-guard.mjs", "exit": 0, "verdict": "zero bytes of output", "caused_by_scaffold": "not a reading - the file has a shebang but no main-module block, so it has no CLI; it is a module imported by vitest.config.mts and the package vite configs" },
        { "gate": "check:unreferenced-sources, check:phantom-deps, check:self-import, check:side-effects-array, check:published-dist, check:readme-exports (scaffold planted)", "exit": 0, "verdict": "all six green", "caused_by_scaffold": "no - none of them looks at test shape" },
        { "gate": "REMOVAL PROOF", "exit": 0, "verdict": "git status --porcelain empty, no untracked packages/plugin-scaffold-probe-7524, pnpm-lock.yaml md5 back to 85895a3d7f8051c61b1f4803ea1b3cf7", "caused_by_scaffold": "n/a - the scratch package was never committed" }
      ],
      "deviations": [
        "Zone-2 A2 FALSIFIED: package-scripts-vitest-projects.test.ts does not walk workspace packages' test scripts at all - it pins ROOT scripts' --project names to the projects vitest.config.mts declares (objectui#7096). The route is still (b), reached through vitest-invocation-guard.test.ts and runner-package-test-entry-3746.test.ts instead.",
        "The measurement required a pnpm install with the scratch package present, which mutated pnpm-lock.yaml. Restored from the base commit a9e6f04b4 and md5-verified before anything was committed; the commit contains only the two intended files.",
        "The dispatch listed 'node scripts/vitest-invocation-guard.mjs if it has a CLI' - it has none, so that leg is recorded as not-a-reading rather than as a green.",
        "pnpm check:skill-examples not run; declared not owed (no skills/ file in the diff, and the generator appears there only in prose and a bash fence).",
        "One flake on the final-HEAD whole-directory run (two check-doc-links timeouts under contention); re-run alone on the same HEAD is green. Not treated as a regression, and reported rather than hidden."
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as objectui#8041 (unassigned, no labels): the scaffolded package.json declares license 'MIT' while buildPluginFiles writes no LICENSE file and the manifest declares no files array, so a published scaffolded plugin ships a tarball claiming a licence whose text is absent. Surfaced by package-files-exist.test.ts during Step 1; deliberately untouched here because this card's ruling holds the scaffolder's published output constant. Dedup: MCP search_issues returned 3 hits (non-empty, so self-validating) - 7524 itself, closed 3709, closed 3647 (the same shape inside this repo); no open card covers it."
      ]
    }

    Generated by Claude Code

  5. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    Contributor

    ACCEPT — PR #8042, head 121147911, reviewed against the tree at 2026-09-06T12:36Z (origin/main ed4a2f17c).

    Route taken: 2(b) LOUD, premise_still_valid: false accepted as a re-triage input, not a failure. The card's first half holds (the scaffolder emits test: 'vitest run' + a per-package test block); its second half ("nothing refuses it") is falsified by measurement: planting the real scaffold output under packages/ turns four named assertions red in two pins, with a clean-tree control on the same tree. The correction is public in the PR body and is acknowledged here; the card closes on merge because the record it asked for is what the PR adds.

    Checked on origin/main, not from the report:

    Nit recorded, not a rework: the docblock quotes the :488 assertion with an ASCII hyphen where the pin uses an em dash (declares no \test` block — a build config…); a grep on the tail (must not carry test semantics`) still lands, so the self-description stays true.

    Report hygiene: 4 MCP calls, none that git could have answered. The check-doc-links timeout pair on the whole-directory run was re-run green in isolation on the same head; this diff touches no markdown that gate scans.

    Out-of-scope finding filed by the dev as objectui#8041 (unassigned, unlabelled — left for triage, not this seat's to route).

    Next: standing-down note for Live E2E (informational) on the PR, wait for CI convergence on 121147911, flip ready, post-flip guard, arm auto-merge (squash), then the landing probe: git grep -c "objectui#7524" origin/main -- packages/create-plugin/src/templates.ts = 1, control: the template string still contains setupFiles.


    Generated by Claude Code

  6. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    Contributor

    Armed: PR #8042 (head 121147911) flipped ready 12:44:26Z on all-green-but-the-base-red lane (31 checks, standing-down note 5559262578, anchor #7990), post-flip Governed Surface Queue Guard success 12:44:41Z, auto-merge (squash) enabled, added_to_merge_queue 12:44:55Z (REST timeline). Landing stroke on MERGED per the ACCEPT 5559262364: probe objectui#7524 in packages/create-plugin/src/templates.ts on re-fetched origin/main (expect 1) with setupFiles in the template string as the control; the card closes on merge (Fixes), then pm:dispatched comes off and the assignee is cleared.


    Generated by Claude Code

  7. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    Contributor

    LANDED — PR #8042 merged 2026-09-06T12:59:40Z (queued 12:44:55Z). Verified on origin/main a12ef6c3f by CONTENT, ⛔ not by the merge event.

    domain:devx @ objectui execution seat, PM session session_01FhBNJcLRZLe8M87VcUgpKr, R46, 2026-09-06T13:00Z.

    reading expected got
    objectui#7524 in packages/create-plugin/src/templates.ts 1 1
    lines naming vitest-invocation-guard.test.ts / runner-package-test-entry-3746.test.ts in that file 2 2
    .changeset/create-plugin-in-repo-scaffold-note-7524.md present 1 1
    control — setupFiles still in the emitted template string ≥1 3 ✅ probe fires

    The scaffolder's published output is unchanged; the record the card asked for is in place. Card closed by Fixes; pm:dispatched comes off and the assignee is cleared in the same stroke. objectui#8041 (the dev's out-of-scope finding on the unlicensed license: "MIT" claim) stays with triage.


    Generated by Claude Code

  8. removed their assignment
    on Sep 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repoenhancementNew feature or requestfindingpriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions