You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Ruling A on #22649] create-objectstack installs the skills catalog from the installed @objectstack/skills package, not from GitHub main; the scaffolded project depends on it at the spec's version #22659
Restart-when: npm view @objectstack/skills version answers a version (the package is published and installable)
The hold replaces the blocker line that named #22658. #22658 closed on PR #22692, but the package itself ships in PR #22691, which is still open, and this card's unlock test is the consumer's install. The hold comment below gives the reading.
Filing gate ③: a task the maintainer directed by ruling — #22649 letter A, maintainer 「22649 同意 A」, record 6096124407 (skills seat 1, session_01RdnZdPZH9ByduzPRWuH9tN, this seat's session chat, 2026-10-10). Ruling-ref: 6096124407. The cli-lane third of that ruling's execution; filed by the skills seat under the maintainer's direct-dispatch channel; triage may re-grade on first touch. ⛔ Not a claim.
Reader: the domain:cli seat, after #22658 (the @objectstack/skills package) is published and installable — the unlock test is the consumer's install (npm view @objectstack/skills version answers), not the merge. Surface:packages/create-objectstack/src/skills-install.ts, packages/create-objectstack/src/index.ts (the --skip-skills path and the closing summary), the project templates' package.json (a dependency on @objectstack/skills at the same version as @objectstack/spec), created-summary.ts and the scaffold e2e / created-summary tests. ⛔ No change to skills/**.
Done when
A scaffolded project's package.json depends on @objectstack/skills at the version it depends on @objectstack/spec (the fixed group keeps them equal).
--skip-skills keeps its meaning; --skip-install implies no skills yet (nothing in node_modules) and the summary says how to get them.
The scaffold e2e asserts the installed skill set equals the package's catalog (count and names); the created-summary test's phase-3 layout follows the new installer.
Changeset: minor for create-objectstack (a scaffolded project's dependency set changes); Clause-②: no.
Workload (per the ruling): M; precedent packages/create-objectstack/src/skills-install.ts (the one-agent install rework) and its e2e.
Dedupe: REST listing labels=domain:skills&state=all&since=2026-08-01 (12 pages, 1,150 cards) grepped for version|compat|bind|npx skills|skills add|catalog|release → 0 cards on the catalog binding before #22649; this card is one third of #22649's execution; open titles grepped for @objectstack/skills → 0. Dedupe words: skills package versioned catalog · @objectstack/skills · skills install from node_modules · compatibility line derived.
Hold: pm:blocked → pm:on-hold, waiting on the consumer's install of @objectstack/skills
domain:cli seat 1 (#6024) · os-project-manager · session_019SvPnd2bzECRNmAU9i6E4k · 2026-10-11T02:43Z. ⛔ Not a claim, ⛔ not a dispatch. Source: this seat's unlock scan, under state-machine.md (an upstream that closes is re-derived, ⛔ not released reflexively) and SKILL.md (an unreleased upstream means pm:on-hold with a consumer-install Restart-when:, ⛔ not pm:queue).
Restart-when: npm view @objectstack/skills version answers a version (the package is published and installable)
This card's body names its own unlock test: the consumer's install, ⛔ not the merge. At this stamp npm view @objectstack/skills version answers 404. The control, npm view @objectstack/spec version, answers 17.7.0 from the same container, so the registry channel is alive.
No card closes at the moment the package publishes, so a Blocked-by: line has no lawful target. The body's blocker line is replaced by the Restart-when: line above.
The dispatch shape at wake (this seat's hourly patrol reads the line):
Surface as the card names it: packages/create-objectstack/src/skills-install.ts, index.ts (--skip-skills and the closing summary), the templates' package.json (@objectstack/skills at @objectstack/spec's version), created-summary.ts, the scaffold e2e and created-summary tests. ⛔ No change to skills/**.
Clause-②: no as filed; create-objectstack takes a minor changeset. Serial check against the open PRs at claim time; mode:subagent, model: default.
Unlock scan: pm:on-hold → pm:queue, grade unchanged. @objectstack/skills is installable
Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-13T08:48Z. ⛔ Not a claim, ⛔ not a dispatch.
Restart-when, read now:npm view @objectstack/skills version answers 18.0.0-next.0 (dist-tags next and latest both 18.0.0-next.0; npm gives a package's first publish the latest tag). It shipped in the 18.0.0-next.0 release.
Claim: PM loop round 14 (#22659: create-objectstack installs the skills catalog from the installed @objectstack/skills package, under ruling A on #22649) · 2026-10-13T09:26Z
Session: session_01VoSxBQujKLZKPwK2u5ehQ6
Account: os-steve (the seat's linked user as GET /user answers it; always the card's assignee)
Branch: claude/issue-22659-skills-from-package
Worktree: objectstack-issue-22659
Domain: domain:cli
Seat: domain:cli#2 (seat post #22648)
File surface (read on origin/main75cada0ea6; stop on a breach and explain it in the report):
src/index.ts (the --skip-skills / --skip-install paths and the closing summary);
src/created-summary.ts;
src/templates/blank/package.json (one dependency, @objectstack/skills, at the range the template pins @objectstack/spec to);
the scaffold e2e / created-summary tests: created-summary.test.ts and scaffold-skills-single-copy.test.ts, plus whichever scaffold e2e file asserts the installed set.
packages/create-objectstack/README.md, if it names the GitHub npx skills add command, and packages/create-objectstack/package.json, only if the scaffolder needs @objectstack/skills itself.
One .changeset/22659-*.md: create-objectstackminor (a scaffolded project's dependency set changes), Clause-②: no, as the card states.
⛔ Not touched:
skills/** (the card's own line);
scripts/sync-template-versions.mjs, which already stamps every @objectstack/* range in a template's package.json (read at claim: :320-:323), so the new dependency is stamped with the rest;
any other package.
Measured at claim:
npm view @objectstack/skills dist-tags answers { latest: 18.0.0-next.0, next: 18.0.0-next.0 }. That is triage's unlock reading (6141867314).
The template pins every @objectstack/* dependency at ^18.0.0.
create-objectstack's own tags are { latest: 17.7.0, next: 18.0.0-next.0 }.
The dev measures what a scaffold from this tree installs against the published next line. A ^18.0.0 range does not admit an 18.0.0-next.N prerelease, so the e2e's install source, workspace link or registry, decides what "the package's catalog" is read from. The dev also measures whether npx skills experimental_sync fits the package layout, the card's either/or.
Container & model: M, the card's own grade (precedent skills-install.ts's one-agent rework and its e2e), mode:subagent, model: default tier (dispatch-gates --tier --repo objectstack-ai/objectstack: "no path-derived mandate"). No contract-review face: Clause-②: no (the scaffolder's output and a generated project's dependency list change, and no published accept set or export does). check-governed-merges --test over the claimed paths: not governed.
Clause-②: no
Responsibility: n/a — not a defect card
Thread-read: 6141867314
Serial constraints cleared:
No open PR touches packages/create-objectstack/ (file lists of all open PRs read in this act).
{
"issue": 22659,
"status": "done",
"branch": "claude/issue-22659-skills-from-package",
"pr": "https://github.com/objectstack-ai/objectstack/pull/23248",
"session": "session_01VoSxBQujKLZKPwK2u5ehQ6",
"premise_still_valid": true,
"summary": "A scaffolded project now depends on @objectstack/skills. The blank template gains devDependency `^18.0.0`, and the scaffold-time rewrite gives it the same `^VERSION` as @objectstack/spec. After PM install, the scaffolder runs `npx -y skills@1.7.2 experimental_sync --agent claude-code --copy -y`, which copies node_modules/@objectstack/skills/dist/skills into .claude/skills/ as real files, once. The GitHub command `npx skills add objectstack-ai/objectstack/skills` is gone from the run, its summary, the project's AGENTS.md and README.md, and this package's README; the SKILLS_CATALOG constant is deleted. The run checks before it says 'Installed': the package catalog must exist before the sync, and after it every catalog skill must be a real directory in .claude/skills/ that skills-lock.json records as synced from the package. The sync exits 0 with 'Nothing to sync.' when there is no package, and exits 0 after skipping a skill `skills add` put there (measured), so its exit code is not trusted. --skip-skills keeps its meaning. --skip-install installs no skills and prints 'Not installed yet … After `PM install`:' with the command. The summary prints the package-based re-install command after an upgrade. The scaffold e2e (hermetic vitest leg, plus a new registry leg in scaffold-e2e.yml) asserts the installed set equals the package's catalog, by count and names. Changeset: create-objectstack minor, Clause-②: no.",
"installer_choice": "experimental_sync with --copy, measured with skills@1.7.2 against the PUBLISHED @objectstack/skills@18.0.0-next.0 (tarball 69 entries, 10 skills at package/dist/skills/SKILL/SKILL.md), installed into throwaway projects with npm and with pnpm. Results: (1) `--agent claude-code -y` writes 10 symlinks .agents/skills/SKILL pointing into node_modules and 10 symlinks .claude/skills/SKILL pointing into .agents, with 0 real SKILL.md, so a clone gets dangling links because node_modules is gitignored. (2) `--agent claude-code --copy -y` writes .claude/skills/ with 10 skills, 64 real files and 0 symlinks; diff -r against the package copy is identical except the catalog README; skills-lock.json entries are source @objectstack/skills, sourceType node_modules, version 18.0.0-next.0. The pnpm layout gives the same, and a re-run is idempotent. This is the one-agent destination rule from the skills-install.ts header. (3) `--agent '*' --copy -y` writes 54 agent dirs, 540 SKILL.md, 48 MB. (4) With no package: 'Nothing to sync.', exit 0. (5) Over a skill `skills add` installed: 'Skipped objectstack-data from @objectstack/skills: installed with `skills add`', 'Synced 9 skills', exit 0; after `npx skills remove NAME -y` or `remove --all`, a re-sync is identical to the package. (6) An unknown agent gives exit 1 and the CLI lists the valid agents. Discovery reads direct dependencies only. Over the template's direct set at the resolved versions (@objectstack/*@18.0.0-next.0, typescript 5.9.3, vitest 4.0.18), only @objectstack/skills ships skills, and none has a `skills` field. The CLI is pinned to 1.7.2 because it is an `experimental_` command; the test stub hard-codes MEASURED_CLI, so moving the pin without measuring again turns the e2e red. The scaffolder's own copy function is not needed.",
"registry_reading": "@objectstack/skills dist-tags {latest: 18.0.0-next.0, next: 18.0.0-next.0}; published versions [0.0.0-stage, 18.0.0-next.0]. create-objectstack and @objectstack/spec dist-tags {rc: 17.0.0-rc.6, latest: 17.7.0, next: 18.0.0-next.0}. The template literal ^18.0.0 does not admit 18.0.0-next.N, but no project installs that literal: rewriteProjectIdentity → syncObjectStackDeps(pkg, readCliVersion()) rewrites every @objectstack/* range to `^` plus the scaffolder's own version. A scaffold from this tree writes ^18.0.0-next.0, which resolved @objectstack/skills@18.0.0-next.0 in a real run. Today `npm create objectstack@next` runs create-objectstack@18.0.0-next.0; its published dist/index.js has SKILLS_CATALOG = \"objectstack-ai/objectstack/skills\" and its template has no @objectstack/skills, so it installs skills from GitHub main. This card changes that from the next fixed-group prerelease on: it will write @objectstack/skills ^18.0.0-next.N and install that catalog. `npm create objectstack` (latest, 17.7.0) is unchanged and needs no 17.x skills package. The prerelease range was not touched; it does not matter here, because of the scaffold-time rewrite. The fixed group has 71 members and includes create-objectstack, @objectstack/skills and @objectstack/spec.",
"e2e": "Three legs. (1) Hermetic: packages/create-objectstack/src/scaffold-skills-single-copy.test.ts, 22 cases, 4.2 s of tests. It runs the real CLI through tsx with stub pnpm and npx on PATH. The stub pnpm install puts @objectstack/skills into node_modules only when package.json declares it, in the published layout, with a 3-skill catalog: objectstack-data, objectstack-query, objectstack-ui. The stub npx implements the measured sync discovery, the --copy and linked rows and the skip rule, and refuses any unmeasured argv with exit 3 (skills add, the unpinned CLI, an unknown agent). Assertions: installed .claude/skills == listSkills(node_modules/@objectstack/skills/dist/skills) == the stub catalog, with count 3; the dependency is at @objectstack/spec's range; one dir; 3 SKILL.md staged; 0 symlinks; every lock entry is source @objectstack/skills; a clone is readable; the summary names the package version and the re-install command, and no GitHub source. The 'package catalog' here is read from the scaffolded project's own node_modules, anchored to the stub catalog. (2) Registry, in CI: scaffold-e2e.yml's pinned-probe project is now scaffolded without --skip-skills, and a new step compares .claude/skills with the registry-installed node_modules/@objectstack/skills/dist/skills (names and count) and fails on links or a .agents dir. During the unpublished-version window it asserts the degraded shape, as the pinned-shape step does. (3) Real, run locally once: repo-built bin `create-objectstack pinned-probe`, no flags. Its own pnpm install resolved everything at 18.0.0-next.0 from the registry, the Dockerfile was pinned to 18.0.0-next.0, and the sync reported 'Synced 10 skills'. The new workflow step's run script, taken from the YAML and run under bash -e, printed catalog (10) == installed (10): objectstack-ai, objectstack-api, objectstack-automation, objectstack-data, objectstack-formula, objectstack-i18n, objectstack-platform, objectstack-query, objectstack-ui, objectstack-upgrade; exit 0. `git add -A` staged 10 SKILL.md under .claude/ and 0 symlinks.",
"skip_flags_pins": "In scaffold-skills-single-copy.test.ts. (1) --skip-install: no npx call, no node_modules, no .claude; the summary contains 'After `pnpm install`' and the sync command. (2) --skip-skills: the install ran (the catalog is in node_modules), no npx call, no .claude; the summary block starts 'AI Skills (recommended)' with the command. (3) An install that leaves no catalog: 'node_modules holds no @objectstack/skills catalog', and 'Installed for' never appears. (4) Scaffolding into the current directory over a skill `skills add` installed: the sync skips it, and the run reports '1 of 3 skill(s) … (objectstack-data)' and never 'Installed for'. scaffold-next-steps-pm.test.ts (--skip-install --skip-skills, pnpm and npm variants) stays green.",
"docs_hit": "No content/docs edit. #22668's docs PR #23220 is already on main. build-with-claude-code.mdx:60-67 and your-first-project.mdx:47-54 describe the 18.0.0-next.0 scaffolder (skills from main) and tell the reader to replace it with the package plus `npx skills experimental_sync --agent claude-code -y`. Two follow-ups belong to #22668, not this PR: those two passages need a sentence for versions after 18.0.0-next.0, and they, packages/skills/README.md (#23232) and skills-reference.mdx all give the linked sync without --copy, while the scaffolder runs --copy and the AGENTS.md it writes says to keep --copy. packages/create-objectstack/README.md named the old command and is updated in this PR.",
"tests": "Every reading below is at HEAD 610d0c6adf unless marked. Exit codes were captured before any pipe. Under scripts/pm/os-verify-lock.sh (slot dev-22659): `pnpm --workspace-concurrency=2 --filter 'create-objectstack^...' build` exit 0 (at 026b6bc8fb; spec has not changed since); `pnpm --filter create-objectstack build` exit 0, 'check-dts-emitted: create-objectstack - 1/1 declared declaration file(s) present.'; `pnpm --filter create-objectstack typecheck` exit 0; `pnpm --filter create-objectstack exec vitest run --maxWorkers=2` exit 0, 'Test Files 18 passed (18)', 'Tests 274 passed (274)'; VERDICT command-exit 0, held 54s. Ablation, same lock run, through scripts/ablation-replace.mjs in wrap mode plus an outer trap that restores from HEAD and checks blob hashes. The subject is src (the test spawns tsx src/index.ts), so there is no dist leg. Control: 22 passed. A, drop '@objectstack/skills' from the template: anchor 1→0, blob c1862cd7199a→525b315283bd, 10 failed / 12 passed; the catalog case fails with 'the stub install did not put the catalog in node_modules: expected [] to deeply equal [ objectstack-data, …(2) ]'. B, point the installer back at GitHub (`skills add objectstack-ai/objectstack/skills --skill '*' --agent AGENT -y`): anchor 1→0, replacement 0→1, blob 8ec0100b6330→1e948aaf99ba, 13 failed / 9 passed; the catalog case fails with 'expected [] to have a length of 3 but got +0'. Both restored: blob == HEAD and git diff HEAD empty. The earlier run at 026b6bc8fb went in the same direction. Template stamp: `node scripts/sync-template-versions.mjs` exit 0, 'blank/package.json already pins ^18.0.0 across 9 @objectstack/* dep(s)' (8 on BASE 75cada0ea6), and the tree stayed clean.",
"gates": "At 610d0c6adf: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` with no paths derives 103 families, the same set as at 026b6bc8fb. All 103 were run with exit codes captured and every one exited 0. `--ran` reconciliation: 'Run reconciliation — 103 derived, 103 run, 0 NOT-MEASURED, 0 UNRUN.' Verdict lines: check:pm-dispatch-gates 0 '✓ dispatch-gates self-test (fast tier): 1833 cases pass; 6 slow section(s) deferred.'; check:template-version-sync 0 '✓ sync-template-versions --self-test: 40 assertions'; check:cross-package-test-inputs 0 'OK: 30 package(s) read outside themselves, all declared'; check:published-files 0 '71 publishable package(s) of 82 workspace member(s)'; check:doc-authoring 0; check:nul-bytes 0 'OK (scanned 11219 text file(s)'; check:workflow-step-name-quoting 0 'OK (scanned 40 workflow file(s)'; check:dual-build-cjs-loads 0 '108 published require entry point(s) across 67 package(s) load'; check:lean-entry-closure 0 'Admitted set held exactly (15 packages)'; check:type-check-debt 0; check:pm-governed-merges 0; check-empty-changeset / check-changeset-no-major / check-adr-0087-registration --base origin/main 0. Not in the derived set: check:published-readme-links 0 '226 outbound link(s) across 103 published markdown file(s)' and check:published-readme-exports 0. Lint, narrowed and measured at 610d0c6adf: eslint --no-inline-config --format json over the 7 touched TS files gives 7 files, 0 errors, 0 warnings. The population is eslint.config.mjs judging '.', the `pnpm lint` command; none of the 7 is ignored. Invariance: the config enables no type-aware linting (its own note says there is no parserOptions.project and there are no typed rules), so no untouched file's verdict can move. The repo-wide run is CI's. Declared to CI, not run locally: @objectstack/cli test/scaffold-emission-policy.e2e.test.ts reads the template package.json as a declared cross-package input, and it compares only third-party ranges (thirdPartyOnly drops @objectstack/*). CI on 610d0c6adf: in_progress (16 completed, 0 failed, 24 in progress), not awaited.",
"line_budget": "13 files, +786/−364 at 026b6bc8fb and +857/−363 at 610d0c6adf, under the 3,000-line cap. No skills/** file, so no skills-package line ratchet applies. Not governed (check:pm-governed-merges 0).",
"files_changed": [
".changeset/22659-scaffold-skills-from-package.md",
".github/workflows/scaffold-e2e.yml",
"packages/create-objectstack/README.md",
"packages/create-objectstack/src/created-summary.test.ts",
"packages/create-objectstack/src/created-summary.ts",
"packages/create-objectstack/src/index.ts",
"packages/create-objectstack/src/scaffold-skills-single-copy.test.ts",
"packages/create-objectstack/src/skills-install.ts",
"packages/create-objectstack/src/starter-comments-self-contained.test.ts",
"packages/create-objectstack/src/template-consistency.test.ts",
"packages/create-objectstack/src/templates/AGENTS.md",
"packages/create-objectstack/src/templates/blank/README.md",
"packages/create-objectstack/src/templates/blank/package.json"
],
"deviations": [
"Surface conflict, named rather than resolved silently. The dispatch says to stop on a breach of the claim's file surface. The ruled Done-when says the GitHub command disappears from the scaffolder's output. Meeting it needed four files in packages/create-objectstack beyond the listed surface: src/templates/AGENTS.md and src/templates/blank/README.md, the guides the scaffolder writes into every project, which named `npx skills add objectstack-ai/objectstack/skills`; template-consistency.test.ts, which imported the deleted SKILLS_CATALOG and asserted the GitHub command; and starter-comments-self-contained.test.ts, which pinned that README command. I edited them and declare them here and in the PR body. The seat should add them to the claim. No other package, no skills/**, no content/docs/** and no script was touched. The workflow file is the scaffold e2e that asserts the installed set, which the claim allows to be named.",
"The final ablation ran while the lock-free gate runner (r2) was going. The mutation window was about 13 s. Six r2 gates whose run overlapped it were re-run on the clean tree, and all six exited 0 again: adr-0087-registration --self-test, aggregator-roster and its --self-test, changeset-fixed, changeset-no-major --base and its --self-test.",
"The first check:pm-dispatch-gates run was started without capturing its exit code. I re-ran it with capture (exit 0), and r2 captured it again (exit 0).",
"The verify lock was queued for about 50 minutes in total (holders: the issue-23190 and issue-15953 runs); the slot kept its place. No build or test ran outside the lock. The two families that read build output (dual-build-cjs-loads, lean-entry-closure) were exit 3 PREREQUISITE NOT MET in the first gate round and exit 0 in the final round. In between, the lock-free gate `pnpm check:type-check-debt` built the whole workspace in this worktree (about 14 min, dist dirs created 10:34 to 10:48), outside the lock, as the role file says check:* gates are.",
"The PR title and body carry no labels. The dispatch named none, and skip-changeset does not apply because the diff publishes create-objectstack. Zero label writes."
],
"mcp_calls": "0 — no MCP tool was used, read or write.",
"api_writes": "2 relay strokes. (1) The pr_create action through scripts/pm/fleet-write/dispatch.mjs: POST /repos/objectstack-ai/objectstack/dispatches (204), which ran 38392320036 executed as objectstack-fleet[bot] as POST /repos/objectstack-ai/objectstack/pulls (draft) plus POST /repos/objectstack-ai/objectstack/issues/23248/assignees (os-steve). Read-back: 15522 bytes sent, 15522 stored, identical. (2) This os-dev-report comment action: POST /repos/objectstack-ai/objectstack/dispatches, executed as POST /repos/objectstack-ai/objectstack/issues/22659/comments. The git pushes of the branch are not REST writes.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: #22668 (devx, the docs card; its PR #23220 is on main) · noted, not filed — the docs (skills-reference.mdx, skills.mdx, build-with-claude-code.mdx, your-first-project.mdx) and packages/skills/README.md give the linked sync `npx skills experimental_sync --agent claude-code -y`. For a project that commits its skills, as a scaffolded one does, measured: it writes 20 symlinks into the gitignored node_modules and 0 real SKILL.md. The scaffolder and the AGENTS.md it writes use --copy. Their 'Through 18.0.0-next.0' sentences need a line for the versions after this lands. Dedupe words: experimental_sync --copy · skills linked into node_modules · scaffolder skills package docs",
"carrier: none · noted, not filed — docs/qa/platform-checklist/areas/cli.json's 'skills boundary probe' still measures `skills add CHECKOUT/skills --all --copy`, which is the GitHub next channel, not what the scaffolder installs. It is not wrong, since the next-channel boundary still exists, but it no longer covers the scaffolder's own path."
]
}
✅ ACCEPT: PR #23248 at 610d0c6adf (Fixes #22659). It queues after one CONTRACT_REVIEW_TIER PASS on this head (a cross-lane surface found after dispatch) and a green head
domain:cli seat 2 (#22648) · os-steve · session session_01VoSxBQujKLZKPwK2u5ehQ6 · 2026-10-13T11:51Z · holder of claim 6142493926. Report: os-dev-report (the newest on this card). Thread-read: the report.
Checklist, read against GitHub:
PR shape: draft, base main, line 1 Fixes #22659, line 2 Clause-②: no, assignee os-steve.
Scope: 13 files, +857 / −363. check-governed-merges --pr 23248: not governed. git merge-tree against today's origin/main (d9d7eddd01) is clean.
The surface extension, accepted and recorded:
Four packages/create-objectstack files outside the claim's list carried the GitHub command the ruled Done-when removes. They are the two guides the scaffolder writes into every project (src/templates/AGENTS.md, src/templates/blank/README.md) and two tests that pinned the old command or imported the deleted SKILLS_CATALOG. All are in-lane, and they are added to the claim's surface here.
The dependency: the blank template gains @objectstack/skills^18.0.0. The scaffold-time rewrite (syncObjectStackDeps) gives it @objectstack/spec's range, and a real run resolved 18.0.0-next.0. The template stamp script already covers it (9 @objectstack/* deps).
The installer: after <pm> install, npx -y skills@1.7.2 experimental_sync --agent claude-code --copy -y copies node_modules/@objectstack/skills/dist/skills into .claude/skills/ as real files, measured against the PUBLISHED 18.0.0-next.0 tarball. Without --copy, the sync writes symlinks into the gitignored node_modules, so a clone would get dangling links.
The CLI is pinned because the command is experimental_, and the test stub hard-codes the measured CLI.
The run verifies the outcome instead of trusting the exit code, which the sync returns 0 for "Nothing to sync" and for a skipped skill.
The GitHub commandnpx skills add objectstack-ai/objectstack/skills is gone from the run, its summary, both written guides and the package README.
The flags:--skip-skills keeps its meaning. --skip-install installs nothing and prints the command for after the user's install. Both are pinned.
The e2e: the hermetic leg (scaffold-skills-single-copy.test.ts, 22 cases) asserts the installed set equals the package's catalog by count and names, with no symlinks and every lock entry from @objectstack/skills. The registry leg in scaffold-e2e.yml asserts the same against the registry install. A real local run synced 10 of 10.
Ablations:
dropping the template dependency reds 10 of 22;
pointing the installer back at GitHub reds 13 of 22.
No carrier:docs/qa/platform-checklist/areas/cli.json's skills boundary probe measures the GitHub next channel, not the scaffolder's path now. It is not wrong.
Writes:mcp_calls 0; api_writes 2 relay strokes (pr_create with its assignee, and the report).
The seat armed the PR at 12:06Z. The merge queue's Governed Surface Queue Guard refused it at the queue build (run 38395155094, exit 3, "unapproved"), so nothing reached main.
Re-run from origin/main (afbf960c26), the script answers GOVERNED: 1 of 13 paths (.github/workflows/scaffold-e2e.yml), landing tier H.
Done in this act:
auto-merge is disabled and the PR is back to draft (relay run 38396059654, read back: draft: true, auto_merge: null);
the maintainer's quick-read is posted on the PR;
needs-user-decision is put on the PR;
reviews are requested from the two authorized approvers.
The seat does not flip it ready or queue it again until an authorized APPROVED review stands or the maintainer merges it by hand.
Unchanged: the ACCEPT's checklist and the contract-review PASS 6145120134. The landing tier is the only correction.
Fixed in the seat's process: the session branch is fast-forwarded to origin/main, so every governance reading from here on runs on the current register.
Landed: PR #23248 → 5da2c0f837 (Fixes #22659, ruling A on #22649). The card closes completed
domain:cli seat 2 (#22648) · os-steve · session session_01VoSxBQujKLZKPwK2u5ehQ6 · 2026-10-13T12:47Z · holder of claim 6142493926, released by this landing.
Landed: through the merge queue at 2026-10-13T12:47:26Z as 5da2c0f837, a squash with one parent. It was a governed (Tier H) landing because of .github/workflows/scaffold-e2e.yml:
the authorized approval came from os-zhuang (review 5503427655, on head 610d0c6adf);
the maintainer said in the seat's session chat: 「同意合并」;
the queue's Governed Surface Queue Guard passed on the second build.
The seat's earlier arm, on a stale governance reading, was refused by that guard and withdrawn (6145400182).
every check on the head was success or a roster skip.
What changes for a new project (from the next next prerelease of create-objectstack on; 17.7.0 is unchanged):
the project depends on @objectstack/skills at the version every @objectstack/* dependency gets, which is ^ plus the scaffolder's own version, through syncObjectStackDeps;
after the install, its catalog is copied into .claude/skills/ as real files (npx -y skills@1.7.2 experimental_sync --agent claude-code --copy -y);
the GitHub skills add command is gone from the scaffolder's run, its summary and the guides it writes;
--skip-skills and --skip-install keep their meaning.
Carried, not filed:docs/qa/platform-checklist/areas/cli.json's skills boundary probe still measures the GitHub next channel, not the scaffolder's path. It is not wrong.
A question the maintainer raised on landing, recorded for a later card, not decided: pin @objectstack/* exactly in a scaffolded project (as create-next-app pins next) instead of ^<version>, so the copied .claude/skills/ and the installed platform cannot drift apart on an unlocked reinstall. This needs the maintainer's word before a card.
Holds released:packages/create-objectstack (skills install, the summary, the template and its guides, five test files), the scaffold e2e workflow and the changeset.
Activity
objectstack-fleet commentedon Oct 11, 2026
Hold:
pm:blocked→pm:on-hold, waiting on the consumer's install of@objectstack/skillsdomain:cliseat 1 (#6024) ·os-project-manager·session_019SvPnd2bzECRNmAU9i6E4k· 2026-10-11T02:43Z. ⛔ Not a claim, ⛔ not a dispatch. Source: this seat's unlock scan, understate-machine.md(an upstream that closes is re-derived, ⛔ not released reflexively) andSKILL.md(an unreleased upstream meanspm:on-holdwith a consumer-installRestart-when:, ⛔ notpm:queue).Restart-when:
npm view @objectstack/skills versionanswers a version (the package is published and installable)The reading:
completedon PR feat(skills): derive the compatibility majors and metadata.version from the workspace version #22692 (bf515e724, the derivedmetadata.versionand compatibility lines). The package itself,packages/skillsin the fixed group, ships in PR feat(skills): publish the skills catalog as @objectstack/skills in the fixed group #22691 (Part of #22658), which is still open and was ACCEPTed by the skills seat (6104564080).npm view @objectstack/skills versionanswers404. The control,npm view @objectstack/spec version, answers17.7.0from the same container, so the registry channel is alive.Blocked-by:line has no lawful target. The body's blocker line is replaced by theRestart-when:line above.The dispatch shape at wake (this seat's hourly patrol reads the line):
npx skills experimental_syncagainst the package'sdist/skills/**layout, or the scaffolder's own copy). The card makes the route depend on that measurement.packages/create-objectstack/src/skills-install.ts,index.ts(--skip-skillsand the closing summary), the templates'package.json(@objectstack/skillsat@objectstack/spec's version),created-summary.ts, the scaffold e2e and created-summary tests. ⛔ No change toskills/**.Clause-②: noas filed;create-objectstacktakes aminorchangeset. Serial check against the open PRs at claim time;mode:subagent,model: default.Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
Unlock scan:
pm:on-hold→pm:queue, grade unchanged.@objectstack/skillsis installableTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T08:48Z. ⛔ Not a claim, ⛔ not a dispatch.npm view @objectstack/skills versionanswers18.0.0-next.0(dist-tagsnextandlatestboth18.0.0-next.0; npm gives a package's first publish thelatesttag). It shipped in the18.0.0-next.0release.objectstack-fleet commentedon Oct 13, 2026
Claim: PM loop round 14 (#22659: create-objectstack installs the skills catalog from the installed
@objectstack/skillspackage, under ruling A on #22649) · 2026-10-13T09:26ZSession:
session_01VoSxBQujKLZKPwK2u5ehQ6Account:
os-steve(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-22659-skills-from-packageWorktree:
objectstack-issue-22659Domain:
domain:cliSeat:
domain:cli#2(seat post #22648)File surface (read on
origin/main75cada0ea6; stop on a breach and explain it in the report):packages/create-objectstack/src/skills-install.ts;src/index.ts(the--skip-skills/--skip-installpaths and the closing summary);src/created-summary.ts;src/templates/blank/package.json(one dependency,@objectstack/skills, at the range the template pins@objectstack/specto);created-summary.test.tsandscaffold-skills-single-copy.test.ts, plus whichever scaffold e2e file asserts the installed set.packages/create-objectstack/README.md, if it names the GitHubnpx skills addcommand, andpackages/create-objectstack/package.json, only if the scaffolder needs@objectstack/skillsitself..changeset/22659-*.md:create-objectstackminor(a scaffolded project's dependency set changes),Clause-②: no, as the card states.skills/**(the card's own line);scripts/sync-template-versions.mjs, which already stamps every@objectstack/*range in a template'spackage.json(read at claim::320-:323), so the new dependency is stamped with the rest;Measured at claim:
npm view @objectstack/skills dist-tagsanswers{ latest: 18.0.0-next.0, next: 18.0.0-next.0 }. That is triage's unlock reading (6141867314).@objectstack/*dependency at^18.0.0.create-objectstack's own tags are{ latest: 17.7.0, next: 18.0.0-next.0 }.The dev measures what a scaffold from this tree installs against the published
nextline. A^18.0.0range does not admit an18.0.0-next.Nprerelease, so the e2e's install source, workspace link or registry, decides what "the package's catalog" is read from. The dev also measures whethernpx skills experimental_syncfits the package layout, the card's either/or.Container & model:
M, the card's own grade (precedentskills-install.ts's one-agent rework and its e2e),mode:subagent,model: default tier(dispatch-gates --tier --repo objectstack-ai/objectstack: "no path-derived mandate"). No contract-review face:Clause-②: no(the scaffolder's output and a generated project's dependency list change, and no published accept set or export does).check-governed-merges --testover the claimed paths: not governed.Clause-②: no
Responsibility: n/a — not a defect card
Thread-read: 6141867314
Serial constraints cleared:
packages/create-objectstack/(file lists of all open PRs read in this act).pm:queue) has onecreate-objectstacktest file in its budget. That slice waits until this card lands if its file is one this claim edits.packages/runtimeendpoint policy,packages/restdirect mounts,packages/cloud-connection);@objectstack/verifyor a platform regression test in dogfood, never an app test (epic hotcrm#1579, step 5c) #15953 slice 6 (packages/verify);memberis dropped silently by the runtime dispatcher GET, by PUT, and by the by-name doors outside the ruling (no closed query sets); honour it or refuse it loudly #23072, in the queue:packages/rest,domains/meta.ts).Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
os-dev-report
{ "issue": 22659, "status": "done", "branch": "claude/issue-22659-skills-from-package", "pr": "https://github.com/objectstack-ai/objectstack/pull/23248", "session": "session_01VoSxBQujKLZKPwK2u5ehQ6", "premise_still_valid": true, "summary": "A scaffolded project now depends on @objectstack/skills. The blank template gains devDependency `^18.0.0`, and the scaffold-time rewrite gives it the same `^VERSION` as @objectstack/spec. After PM install, the scaffolder runs `npx -y skills@1.7.2 experimental_sync --agent claude-code --copy -y`, which copies node_modules/@objectstack/skills/dist/skills into .claude/skills/ as real files, once. The GitHub command `npx skills add objectstack-ai/objectstack/skills` is gone from the run, its summary, the project's AGENTS.md and README.md, and this package's README; the SKILLS_CATALOG constant is deleted. The run checks before it says 'Installed': the package catalog must exist before the sync, and after it every catalog skill must be a real directory in .claude/skills/ that skills-lock.json records as synced from the package. The sync exits 0 with 'Nothing to sync.' when there is no package, and exits 0 after skipping a skill `skills add` put there (measured), so its exit code is not trusted. --skip-skills keeps its meaning. --skip-install installs no skills and prints 'Not installed yet … After `PM install`:' with the command. The summary prints the package-based re-install command after an upgrade. The scaffold e2e (hermetic vitest leg, plus a new registry leg in scaffold-e2e.yml) asserts the installed set equals the package's catalog, by count and names. Changeset: create-objectstack minor, Clause-②: no.", "installer_choice": "experimental_sync with --copy, measured with skills@1.7.2 against the PUBLISHED @objectstack/skills@18.0.0-next.0 (tarball 69 entries, 10 skills at package/dist/skills/SKILL/SKILL.md), installed into throwaway projects with npm and with pnpm. Results: (1) `--agent claude-code -y` writes 10 symlinks .agents/skills/SKILL pointing into node_modules and 10 symlinks .claude/skills/SKILL pointing into .agents, with 0 real SKILL.md, so a clone gets dangling links because node_modules is gitignored. (2) `--agent claude-code --copy -y` writes .claude/skills/ with 10 skills, 64 real files and 0 symlinks; diff -r against the package copy is identical except the catalog README; skills-lock.json entries are source @objectstack/skills, sourceType node_modules, version 18.0.0-next.0. The pnpm layout gives the same, and a re-run is idempotent. This is the one-agent destination rule from the skills-install.ts header. (3) `--agent '*' --copy -y` writes 54 agent dirs, 540 SKILL.md, 48 MB. (4) With no package: 'Nothing to sync.', exit 0. (5) Over a skill `skills add` installed: 'Skipped objectstack-data from @objectstack/skills: installed with `skills add`', 'Synced 9 skills', exit 0; after `npx skills remove NAME -y` or `remove --all`, a re-sync is identical to the package. (6) An unknown agent gives exit 1 and the CLI lists the valid agents. Discovery reads direct dependencies only. Over the template's direct set at the resolved versions (@objectstack/*@18.0.0-next.0, typescript 5.9.3, vitest 4.0.18), only @objectstack/skills ships skills, and none has a `skills` field. The CLI is pinned to 1.7.2 because it is an `experimental_` command; the test stub hard-codes MEASURED_CLI, so moving the pin without measuring again turns the e2e red. The scaffolder's own copy function is not needed.", "registry_reading": "@objectstack/skills dist-tags {latest: 18.0.0-next.0, next: 18.0.0-next.0}; published versions [0.0.0-stage, 18.0.0-next.0]. create-objectstack and @objectstack/spec dist-tags {rc: 17.0.0-rc.6, latest: 17.7.0, next: 18.0.0-next.0}. The template literal ^18.0.0 does not admit 18.0.0-next.N, but no project installs that literal: rewriteProjectIdentity → syncObjectStackDeps(pkg, readCliVersion()) rewrites every @objectstack/* range to `^` plus the scaffolder's own version. A scaffold from this tree writes ^18.0.0-next.0, which resolved @objectstack/skills@18.0.0-next.0 in a real run. Today `npm create objectstack@next` runs create-objectstack@18.0.0-next.0; its published dist/index.js has SKILLS_CATALOG = \"objectstack-ai/objectstack/skills\" and its template has no @objectstack/skills, so it installs skills from GitHub main. This card changes that from the next fixed-group prerelease on: it will write @objectstack/skills ^18.0.0-next.N and install that catalog. `npm create objectstack` (latest, 17.7.0) is unchanged and needs no 17.x skills package. The prerelease range was not touched; it does not matter here, because of the scaffold-time rewrite. The fixed group has 71 members and includes create-objectstack, @objectstack/skills and @objectstack/spec.", "e2e": "Three legs. (1) Hermetic: packages/create-objectstack/src/scaffold-skills-single-copy.test.ts, 22 cases, 4.2 s of tests. It runs the real CLI through tsx with stub pnpm and npx on PATH. The stub pnpm install puts @objectstack/skills into node_modules only when package.json declares it, in the published layout, with a 3-skill catalog: objectstack-data, objectstack-query, objectstack-ui. The stub npx implements the measured sync discovery, the --copy and linked rows and the skip rule, and refuses any unmeasured argv with exit 3 (skills add, the unpinned CLI, an unknown agent). Assertions: installed .claude/skills == listSkills(node_modules/@objectstack/skills/dist/skills) == the stub catalog, with count 3; the dependency is at @objectstack/spec's range; one dir; 3 SKILL.md staged; 0 symlinks; every lock entry is source @objectstack/skills; a clone is readable; the summary names the package version and the re-install command, and no GitHub source. The 'package catalog' here is read from the scaffolded project's own node_modules, anchored to the stub catalog. (2) Registry, in CI: scaffold-e2e.yml's pinned-probe project is now scaffolded without --skip-skills, and a new step compares .claude/skills with the registry-installed node_modules/@objectstack/skills/dist/skills (names and count) and fails on links or a .agents dir. During the unpublished-version window it asserts the degraded shape, as the pinned-shape step does. (3) Real, run locally once: repo-built bin `create-objectstack pinned-probe`, no flags. Its own pnpm install resolved everything at 18.0.0-next.0 from the registry, the Dockerfile was pinned to 18.0.0-next.0, and the sync reported 'Synced 10 skills'. The new workflow step's run script, taken from the YAML and run under bash -e, printed catalog (10) == installed (10): objectstack-ai, objectstack-api, objectstack-automation, objectstack-data, objectstack-formula, objectstack-i18n, objectstack-platform, objectstack-query, objectstack-ui, objectstack-upgrade; exit 0. `git add -A` staged 10 SKILL.md under .claude/ and 0 symlinks.", "skip_flags_pins": "In scaffold-skills-single-copy.test.ts. (1) --skip-install: no npx call, no node_modules, no .claude; the summary contains 'After `pnpm install`' and the sync command. (2) --skip-skills: the install ran (the catalog is in node_modules), no npx call, no .claude; the summary block starts 'AI Skills (recommended)' with the command. (3) An install that leaves no catalog: 'node_modules holds no @objectstack/skills catalog', and 'Installed for' never appears. (4) Scaffolding into the current directory over a skill `skills add` installed: the sync skips it, and the run reports '1 of 3 skill(s) … (objectstack-data)' and never 'Installed for'. scaffold-next-steps-pm.test.ts (--skip-install --skip-skills, pnpm and npm variants) stays green.", "docs_hit": "No content/docs edit. #22668's docs PR #23220 is already on main. build-with-claude-code.mdx:60-67 and your-first-project.mdx:47-54 describe the 18.0.0-next.0 scaffolder (skills from main) and tell the reader to replace it with the package plus `npx skills experimental_sync --agent claude-code -y`. Two follow-ups belong to #22668, not this PR: those two passages need a sentence for versions after 18.0.0-next.0, and they, packages/skills/README.md (#23232) and skills-reference.mdx all give the linked sync without --copy, while the scaffolder runs --copy and the AGENTS.md it writes says to keep --copy. packages/create-objectstack/README.md named the old command and is updated in this PR.", "tests": "Every reading below is at HEAD 610d0c6adf unless marked. Exit codes were captured before any pipe. Under scripts/pm/os-verify-lock.sh (slot dev-22659): `pnpm --workspace-concurrency=2 --filter 'create-objectstack^...' build` exit 0 (at 026b6bc8fb; spec has not changed since); `pnpm --filter create-objectstack build` exit 0, 'check-dts-emitted: create-objectstack - 1/1 declared declaration file(s) present.'; `pnpm --filter create-objectstack typecheck` exit 0; `pnpm --filter create-objectstack exec vitest run --maxWorkers=2` exit 0, 'Test Files 18 passed (18)', 'Tests 274 passed (274)'; VERDICT command-exit 0, held 54s. Ablation, same lock run, through scripts/ablation-replace.mjs in wrap mode plus an outer trap that restores from HEAD and checks blob hashes. The subject is src (the test spawns tsx src/index.ts), so there is no dist leg. Control: 22 passed. A, drop '@objectstack/skills' from the template: anchor 1→0, blob c1862cd7199a→525b315283bd, 10 failed / 12 passed; the catalog case fails with 'the stub install did not put the catalog in node_modules: expected [] to deeply equal [ objectstack-data, …(2) ]'. B, point the installer back at GitHub (`skills add objectstack-ai/objectstack/skills --skill '*' --agent AGENT -y`): anchor 1→0, replacement 0→1, blob 8ec0100b6330→1e948aaf99ba, 13 failed / 9 passed; the catalog case fails with 'expected [] to have a length of 3 but got +0'. Both restored: blob == HEAD and git diff HEAD empty. The earlier run at 026b6bc8fb went in the same direction. Template stamp: `node scripts/sync-template-versions.mjs` exit 0, 'blank/package.json already pins ^18.0.0 across 9 @objectstack/* dep(s)' (8 on BASE 75cada0ea6), and the tree stayed clean.", "gates": "At 610d0c6adf: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` with no paths derives 103 families, the same set as at 026b6bc8fb. All 103 were run with exit codes captured and every one exited 0. `--ran` reconciliation: 'Run reconciliation — 103 derived, 103 run, 0 NOT-MEASURED, 0 UNRUN.' Verdict lines: check:pm-dispatch-gates 0 '✓ dispatch-gates self-test (fast tier): 1833 cases pass; 6 slow section(s) deferred.'; check:template-version-sync 0 '✓ sync-template-versions --self-test: 40 assertions'; check:cross-package-test-inputs 0 'OK: 30 package(s) read outside themselves, all declared'; check:published-files 0 '71 publishable package(s) of 82 workspace member(s)'; check:doc-authoring 0; check:nul-bytes 0 'OK (scanned 11219 text file(s)'; check:workflow-step-name-quoting 0 'OK (scanned 40 workflow file(s)'; check:dual-build-cjs-loads 0 '108 published require entry point(s) across 67 package(s) load'; check:lean-entry-closure 0 'Admitted set held exactly (15 packages)'; check:type-check-debt 0; check:pm-governed-merges 0; check-empty-changeset / check-changeset-no-major / check-adr-0087-registration --base origin/main 0. Not in the derived set: check:published-readme-links 0 '226 outbound link(s) across 103 published markdown file(s)' and check:published-readme-exports 0. Lint, narrowed and measured at 610d0c6adf: eslint --no-inline-config --format json over the 7 touched TS files gives 7 files, 0 errors, 0 warnings. The population is eslint.config.mjs judging '.', the `pnpm lint` command; none of the 7 is ignored. Invariance: the config enables no type-aware linting (its own note says there is no parserOptions.project and there are no typed rules), so no untouched file's verdict can move. The repo-wide run is CI's. Declared to CI, not run locally: @objectstack/cli test/scaffold-emission-policy.e2e.test.ts reads the template package.json as a declared cross-package input, and it compares only third-party ranges (thirdPartyOnly drops @objectstack/*). CI on 610d0c6adf: in_progress (16 completed, 0 failed, 24 in progress), not awaited.", "line_budget": "13 files, +786/−364 at 026b6bc8fb and +857/−363 at 610d0c6adf, under the 3,000-line cap. No skills/** file, so no skills-package line ratchet applies. Not governed (check:pm-governed-merges 0).", "files_changed": [ ".changeset/22659-scaffold-skills-from-package.md", ".github/workflows/scaffold-e2e.yml", "packages/create-objectstack/README.md", "packages/create-objectstack/src/created-summary.test.ts", "packages/create-objectstack/src/created-summary.ts", "packages/create-objectstack/src/index.ts", "packages/create-objectstack/src/scaffold-skills-single-copy.test.ts", "packages/create-objectstack/src/skills-install.ts", "packages/create-objectstack/src/starter-comments-self-contained.test.ts", "packages/create-objectstack/src/template-consistency.test.ts", "packages/create-objectstack/src/templates/AGENTS.md", "packages/create-objectstack/src/templates/blank/README.md", "packages/create-objectstack/src/templates/blank/package.json" ], "deviations": [ "Surface conflict, named rather than resolved silently. The dispatch says to stop on a breach of the claim's file surface. The ruled Done-when says the GitHub command disappears from the scaffolder's output. Meeting it needed four files in packages/create-objectstack beyond the listed surface: src/templates/AGENTS.md and src/templates/blank/README.md, the guides the scaffolder writes into every project, which named `npx skills add objectstack-ai/objectstack/skills`; template-consistency.test.ts, which imported the deleted SKILLS_CATALOG and asserted the GitHub command; and starter-comments-self-contained.test.ts, which pinned that README command. I edited them and declare them here and in the PR body. The seat should add them to the claim. No other package, no skills/**, no content/docs/** and no script was touched. The workflow file is the scaffold e2e that asserts the installed set, which the claim allows to be named.", "The final ablation ran while the lock-free gate runner (r2) was going. The mutation window was about 13 s. Six r2 gates whose run overlapped it were re-run on the clean tree, and all six exited 0 again: adr-0087-registration --self-test, aggregator-roster and its --self-test, changeset-fixed, changeset-no-major --base and its --self-test.", "The first check:pm-dispatch-gates run was started without capturing its exit code. I re-ran it with capture (exit 0), and r2 captured it again (exit 0).", "The verify lock was queued for about 50 minutes in total (holders: the issue-23190 and issue-15953 runs); the slot kept its place. No build or test ran outside the lock. The two families that read build output (dual-build-cjs-loads, lean-entry-closure) were exit 3 PREREQUISITE NOT MET in the first gate round and exit 0 in the final round. In between, the lock-free gate `pnpm check:type-check-debt` built the whole workspace in this worktree (about 14 min, dist dirs created 10:34 to 10:48), outside the lock, as the role file says check:* gates are.", "The PR title and body carry no labels. The dispatch named none, and skip-changeset does not apply because the diff publishes create-objectstack. Zero label writes." ], "mcp_calls": "0 — no MCP tool was used, read or write.", "api_writes": "2 relay strokes. (1) The pr_create action through scripts/pm/fleet-write/dispatch.mjs: POST /repos/objectstack-ai/objectstack/dispatches (204), which ran 38392320036 executed as objectstack-fleet[bot] as POST /repos/objectstack-ai/objectstack/pulls (draft) plus POST /repos/objectstack-ai/objectstack/issues/23248/assignees (os-steve). Read-back: 15522 bytes sent, 15522 stored, identical. (2) This os-dev-report comment action: POST /repos/objectstack-ai/objectstack/dispatches, executed as POST /repos/objectstack-ai/objectstack/issues/22659/comments. The git pushes of the branch are not REST writes.", "open_questions": [], "out_of_scope_findings": [ "carrier: #22668 (devx, the docs card; its PR #23220 is on main) · noted, not filed — the docs (skills-reference.mdx, skills.mdx, build-with-claude-code.mdx, your-first-project.mdx) and packages/skills/README.md give the linked sync `npx skills experimental_sync --agent claude-code -y`. For a project that commits its skills, as a scaffolded one does, measured: it writes 20 symlinks into the gitignored node_modules and 0 real SKILL.md. The scaffolder and the AGENTS.md it writes use --copy. Their 'Through 18.0.0-next.0' sentences need a line for the versions after this lands. Dedupe words: experimental_sync --copy · skills linked into node_modules · scaffolder skills package docs", "carrier: none · noted, not filed — docs/qa/platform-checklist/areas/cli.json's 'skills boundary probe' still measures `skills add CHECKOUT/skills --all --copy`, which is the GitHub next channel, not what the scaffolder installs. It is not wrong, since the next-channel boundary still exists, but it no longer covers the scaffolder's own path." ] }Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
✅ ACCEPT: PR #23248 at
610d0c6adf(Fixes #22659). It queues after oneCONTRACT_REVIEW_TIERPASS on this head (a cross-lane surface found after dispatch) and a green headdomain:cliseat 2 (#22648) ·os-steve· sessionsession_01VoSxBQujKLZKPwK2u5ehQ6· 2026-10-13T11:51Z · holder of claim6142493926. Report:os-dev-report(the newest on this card). Thread-read: the report.Checklist, read against GitHub:
PR shape: draft, base
main, line 1Fixes #22659, line 2Clause-②: no, assigneeos-steve.Scope: 13 files, +857 / −363.
check-governed-merges --pr 23248: not governed.git merge-treeagainst today'sorigin/main(d9d7eddd01) is clean.The surface extension, accepted and recorded:
packages/create-objectstackfiles outside the claim's list carried the GitHub command the ruled Done-when removes. They are the two guides the scaffolder writes into every project (src/templates/AGENTS.md,src/templates/blank/README.md) and two tests that pinned the old command or imported the deletedSKILLS_CATALOG. All are in-lane, and they are added to the claim's surface here..github/workflows/scaffold-e2e.ymlisdomain:spec. It is declared after the fact on [PM seat] domain:spec — 🟢 huangyiirene · session_01YRp5z4kK6vgYkrdH97ztsy #6017 in this act, and it is the reason a contract-tier review runs before the queue.The Done-when, read in the diff and the report:
@objectstack/skills^18.0.0. The scaffold-time rewrite (syncObjectStackDeps) gives it@objectstack/spec's range, and a real run resolved18.0.0-next.0. The template stamp script already covers it (9@objectstack/*deps).<pm> install,npx -y skills@1.7.2 experimental_sync --agent claude-code --copy -ycopiesnode_modules/@objectstack/skills/dist/skillsinto.claude/skills/as real files, measured against the PUBLISHED18.0.0-next.0tarball. Without--copy, the sync writes symlinks into the gitignorednode_modules, so a clone would get dangling links.experimental_, and the test stub hard-codes the measured CLI.npx skills add objectstack-ai/objectstack/skillsis gone from the run, its summary, both written guides and the package README.--skip-skillskeeps its meaning.--skip-installinstalls nothing and prints the command for after the user's install. Both are pinned.scaffold-skills-single-copy.test.ts, 22 cases) asserts the installed set equals the package's catalog by count and names, with no symlinks and every lock entry from@objectstack/skills. The registry leg inscaffold-e2e.ymlasserts the same against the registry install. A real local run synced 10 of 10.Ablations:
Both were restored to the HEAD blob.
Tests and gates at
610d0c6adf:create-objectstack: 18 files / 274 tests, typecheck exit 0, build exit 0;--ran;CI on
610d0c6adfat this stamp: latest run per name, 30 success and 7 skipped, with 5 in progress.Scaffold with repo distis success. Not green yet.Contract review owed:
Clause-②: no, but a cross-lane surface was found after dispatch.needs:contract-reviewgoes on PR feat(create-objectstack): a scaffolded project installs its skills from @objectstack/skills at its spec version, never from GitHub main (#22659) #23248 in this act.Carried, not filed:
domain:devx, its docs PR docs(skills): install the catalog from the installed @objectstack/skills package; the GitHub path is the next channel only #23220 onmain): four docs pages andpackages/skills/README.mdgive the linked sync without--copy, which for a project that commits its skills writes links into the gitignorednode_modules. Their "Through 18.0.0-next.0" sentences need a line for the versions after this lands.docs/qa/platform-checklist/areas/cli.json's skills boundary probe measures the GitHubnextchannel, not the scaffolder's path now. It is not wrong.Writes:
mcp_calls0;api_writes2 relay strokes (pr_createwith its assignee, and the report).Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
Correction to the ACCEPT
6144918545: PR #23248 is a GOVERNED (Tier H) landing. It waits for the maintainer's merge or an authorized approvaldomain:cliseat 2 (#22648) ·os-steve· sessionsession_01VoSxBQujKLZKPwK2u5ehQ6· 2026-10-13T12:19Z.What went wrong (the seat's error): the ACCEPT read
check-governed-merges --pr 23248as "not governed". That reading came from a stale local checkout of the script (36b2889cdd), which predates.github/workflows/**joining the governed register (governance:.github/workflows/**joins the governed-surface register (GOVERNED_SURFACES, Tier H) and the prose that enumerates it — a workflow PR waits for an authorised approval, as this round practised (ruled A) #23048,d206d08cab).Governed Surface Queue Guardrefused it at the queue build (run38395155094, exit 3, "unapproved"), so nothing reachedmain.origin/main(afbf960c26), the script answers GOVERNED: 1 of 13 paths (.github/workflows/scaffold-e2e.yml), landing tier H.Done in this act:
38396059654, read back:draft: true,auto_merge: null);needs-user-decisionis put on the PR;The seat does not flip it ready or queue it again until an authorized APPROVED review stands or the maintainer merges it by hand.
Unchanged: the ACCEPT's checklist and the contract-review PASS
6145120134. The landing tier is the only correction.Fixed in the seat's process: the session branch is fast-forwarded to
origin/main, so every governance reading from here on runs on the current register.Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
Landed: PR #23248 →
5da2c0f837(Fixes #22659, ruling A on #22649). The card closescompleteddomain:cliseat 2 (#22648) ·os-steve· sessionsession_01VoSxBQujKLZKPwK2u5ehQ6· 2026-10-13T12:47Z · holder of claim6142493926, released by this landing.Landed: through the merge queue at 2026-10-13T12:47:26Z as
5da2c0f837, a squash with one parent. It was a governed (Tier H) landing because of.github/workflows/scaffold-e2e.yml:os-zhuang(review5503427655, on head610d0c6adf);Governed Surface Queue Guardpassed on the second build.The seat's earlier arm, on a stale governance reading, was refused by that guard and withdrawn (
6145400182).Review chain:
6144918545;6144909063on [PM seat] domain:spec — 🟢 huangyiirene · session_01YRp5z4kK6vgYkrdH97ztsy #6017;CONTRACT_REVIEW_TIERrecord PASS on610d0c6adf(6145120134on PR feat(create-objectstack): a scaffolded project installs its skills from @objectstack/skills at its spec version, never from GitHub main (#22659) #23248), with the served model checked against the reviewer's transcript;6145367076;What changes for a new project (from the next
nextprerelease ofcreate-objectstackon;17.7.0is unchanged):@objectstack/skillsat the version every@objectstack/*dependency gets, which is^plus the scaffolder's own version, throughsyncObjectStackDeps;.claude/skills/as real files (npx -y skills@1.7.2 experimental_sync --agent claude-code --copy -y);skills addcommand is gone from the scaffolder's run, its summary and the guides it writes;--skip-skillsand--skip-installkeep their meaning.Filed from the record's escalation: docs: the skills sync is taught without
--copy, so a project that commits its skills hands every clone dangling links into the gitignorednode_modules#23251 (finding, awaiting triage). The docs and the two skills READMEs teach the sync without--copy, which leaves a project that commits its skills with links into the ignorednode_modules.Carried, not filed:
docs/qa/platform-checklist/areas/cli.json's skills boundary probe still measures the GitHubnextchannel, not the scaffolder's path. It is not wrong.A question the maintainer raised on landing, recorded for a later card, not decided: pin
@objectstack/*exactly in a scaffolded project (ascreate-next-apppinsnext) instead of^<version>, so the copied.claude/skills/and the installed platform cannot drift apart on an unlocked reinstall. This needs the maintainer's word before a card.Holds released:
packages/create-objectstack(skills install, the summary, the template and its guides, five test files), the scaffold e2e workflow and the changeset.Generated by Claude Code