Skip to content

docs: skills/README.md:9 — the catalog's own front door still recommends --all, which writes the bundle to three directories #16768

Closed

Description

@os-zhuang

Split off #16400 by the triage seat, not because the finding differs but because the landing path does.

The finding (same as #16400's second half)

origin/main:

skills/README.md:9:npx skills add objectstack-ai/objectstack/skills --all

--all is the skills CLI's shorthand for --skill '*' --agent '*' -y. Measured on #16400 against skills@1.5.23 with this catalog (11 skills), in an empty directory:

npx skills add objectstack-ai/objectstack/skills --all
  .agents/   46 real files   604,102 B
  agent/     46 real files   602,682 B   (same bodies, re-serialised frontmatter)
  .claude/   11 symlinks into .agents/

npx skills add objectstack-ai/objectstack/skills --skill '*' --agent claude-code -y
  .claude/   46 real files   604,102 B   and nothing else

A reader who follows this line inside a git repository and commits stages 22 SKILL.md paths plus 11 symlinks instead of 11 — the exact defect #16331 was filed about, reproduced by following the catalog's own README. #16331 is closed (PR #16401, merged 2026-09-06T20:36:10Z) and fixed only packages/create-objectstack/**; this line is untouched by it.

Why this is a separate card from #16400

skills/** is a governed surface — a PR touching it takes the terminal four-step (maintainer approval), while content/docs/** alone does not. Riding this one line along with #16400's four content/docs/** pages would convert that whole PR's landing path. That is the same precedent recorded on #16655 (PR #16654's 验收备注): a governed-surface rider is a split, not a convenience.

The two are independent and may land in either order.

The ask

Make the per-agent form the recommended one on line 9 (npx skills add objectstack-ai/objectstack/skills --skill '*' --agent claude-code -y), with --all retained as the explicitly-labelled multi-runtime opt-in and a one-line note that it writes the bundle to three destinations.

Keep the /skills subpath in every spelling — it is the boundary that keeps metadata.internal skills out (packages/create-objectstack/src/template-consistency.test.ts:648-670 ratchets exactly this).

Acceptance

  • skills/README.md recommends a command whose install lands the bundle once.
  • --all still documented, with its three-destination cost stated, not merely mentioned.
  • Governed surface ⇒ draft PR, human merge.

Not in this card

The four content/docs/** surfaces — that is #16400. packages/create-objectstack/** — that is #16331, closed.

https://claude.ai/code/session_01SwJQDFKe8tVit3BXQ9EfR5

Activity

  1. added
    pm:queueReady for the PM dispatch loop
    domain:skillsDomain lane — seat card indexed by label:pm:seat
    on Sep 8, 2026
  2. added theissue type on Sep 8, 2026
  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Sep 8, 2026
  4. self-assigned this
    on Sep 8, 2026
  5. hotlong commented on Sep 8, 2026

    @hotlong
    Contributor

    Claim: PM loop round 1 — flight L: skills/README.md's front door recommends the per-agent install (--skill '*' --agent claude-code -y) that lands the bundle ONCE, keeps --all as the explicitly-labelled multi-runtime opt-in with its three-destination cost stated, and keeps the /skills subpath in every spelling
    Session: session_01P58euzUXCVJNwmhuPC9DXY
    Branch: claude/issue-16768-skills-readme-install-form
    Worktree: objectstack-issue-16768
    Domain: domain:skills
    File surface: skills/README.md — the install block at its line 9 on origin/main b38821d1c and the sentence(s) beside it; nothing else under skills/** (stop on breach; explain in the report)
    Container & model: XS (one command line and one sentence in the catalog's README), mode:subagent, model: opus — --tier output at 04:58Z: "no path-derived mandate … floor sonnet · default opus · ceiling fable"; default judgement tier, this seat's contract-tier review is the compensating control
    Clause-②: no
    Thread-read: the card body (no comments; triage's split rationale is in the body itself)
    Serial constraints cleared: file last touched before the 400-commit deepened window; line 9 on origin/main b38821d1c (06:02Z) reads npx skills add objectstack-ai/objectstack/skills --all; skills/README.md is NOT among the files check-skills-token-ratchet ratchets (0 rows name it), so no token payment is owed — the dev confirms by running it; open objectstack PRs by title at 06:02Z (29 PRs): none on this file; no claude/issue-16768-* ref; not on the H17 trigger-file index; verify lock free at 06:02Z. Related cards read: #16400 (the four content/docs/** carriers, devx's — independent, either order) and #16331 (closed, PR #16401, packages/create-objectstack/** only). Governed (skills/**) ⇒ draft only at the governed terminal.


    Generated by Claude Code

  6. hotlong commented on Sep 8, 2026

    @hotlong
    Contributor

    os-dev-report

    {
      "issue": 16768,
      "status": "done",
      "branch": "claude/issue-16768-skills-readme-install-form",
      "head": "290c258ef",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/16806",
      "premise_still_valid": true,
      "summary": "skills/README.md:9 now recommends `npx skills add objectstack-ai/objectstack/skills --skill '*' --agent claude-code -y` — the per-agent form, byte-for-byte the command packages/create-objectstack already runs — instead of `--all`. `--all` stays on the page as an explicitly-labelled multi-runtime opt-in whose three-destination cost is stated (a full real copy in BOTH .agents/ and agent/, plus .claude/ symlinks into .agents/) rather than merely mentioned. The /skills subpath is kept in the file's one and only catalog spelling. One file, +9/-1; nothing else under skills/**, no content/docs/** (that is another seat's), no packages/create-objectstack/**.",
      "readings": {
        "install_measurement": "RE-MEASURED LIVE in this container, not cited. skills@1.5.23, this catalog (11 skills), two empty scratch directories. `--all` yields .agents/ 46 real files 602,278 B + agent/ 46 real files 600,858 B + .claude/ 11 symlinks (plus skills-lock.json). `--skill '*' --agent claude-code -y` yields .claude/ 46 real files 602,278 B and nothing else (plus skills-lock.json). File counts reproduce the card's recorded shape exactly (46/46/11); byte totals differ from skills-install.ts's 604,102/602,682 only because the catalog's own content has moved since that reading.",
        "cli_semantics": "`skills --help` spells it itself: `--all  Shorthand for --skill '*' --agent '*' -y`. The --agent '*' half is the whole cost.",
        "ratchet": "NOT RATCHETED, measured. check-skills-token-ratchet.mjs puts skills/README.md in population 3 (OUTSIDE — 'not inside any published skill directory'), pinned by its own self-test case 'skills/README.md is outside the population (population 3)'. Running the gate prints no row for the file: '36 authored bundle file(s) within their ceilings'. check-skill-line-ratchet.mjs excludes the published catalog by design (its header states extending coverage there is a policy change).",
        "published_surface": "changed file skills/README.md: 119 to 127 lines (+8), 2,079 to 2,215 tokens (+136). Whole package (11 published SKILL.md summed): 6,853 lines / 79,679 tokens, unchanged (+0/+0) — no SKILL.md was touched."
      },
      "mechanism_assumptions": {
        "1_line9_on_main": "成立 — on origin/main b72226f48, skills/README.md line 9 is exactly `npx skills add objectstack-ai/objectstack/skills --all` inside a bash fence, preceded by 'existing projects add (or update) the bundle with:' and followed by the /skills subpath sentence. (Dispatch cited b38821d1c; origin/main had moved to b72226f48, then a749dcc4b. Branch cut from b72226f48.)",
        "2_not_ratcheted": "成立 — confirmed by RUNNING the gate, not by the seat's earlier print. No skills/README.md row; exit 0, '36 authored bundle file(s) within their ceilings'. Source-level confirmation too: population 3 OUTSIDE, with a self-test pinning it. No headroom question arises, so no wording was shortened.",
        "3_measurable_here": "成立 — the network allowed it. npm and GitHub were both reachable; both installs ran to completion (exit 0) in empty scratch directories. The live figures are in `readings.install_measurement` and reproduce #16400's shape. No uncited figure is presented anywhere.",
        "4_template_consistency_pins_subpath": "成立, and proven LIVE rather than read. packages/create-objectstack/src/template-consistency.test.ts 'no customer-facing surface advertises a repo-root skills install' greps surfaces ['content/docs','skills','packages/create-objectstack'] for `skills add objectstack-ai/objectstack` not followed by `/skills`. It pins the SUBPATH, not the flags — it does not pin the README's command shape, so the --all-to-per-agent swap is free as long as the subpath survives. Ablation: dropping /skills from line 9 turned it RED (exit 1, 1 failed | 36 passed); restoring turned it GREEN (37 passed)."
      },
      "gates": [
        { "cmd": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran ran.txt", "exit": 0, "verdict": "Run reconciliation — 21 derived, 21 run, 0 NOT-MEASURED, 0 UNRUN. Derived list identical to the PM's 21." },
        { "cmd": "node scripts/check-ci-filter-parity.mjs", "exit": 0, "verdict": "clean" },
        { "cmd": "node scripts/check-closing-keyword-parity.mjs", "exit": 0, "verdict": "clean" },
        { "cmd": "node scripts/check-closing-keyword-parity.mjs --self-test", "exit": 0, "verdict": "clean" },
        { "cmd": "node scripts/check-comment-mask-corpus.mjs", "exit": 0, "verdict": "clean" },
        { "cmd": "pnpm --filter @objectstack/lint run check:doc-formula-expressions", "exit": 0, "verdict": "First run exit 3 PREREQUISITE NOT MET (not a reading). After building @objectstack/formula + @objectstack/lint under os-verify-lock.sh: '✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 434 files / 1372 TS blocks judged clean'." },
        { "cmd": "pnpm --filter @objectstack/spec run check:skill-docs", "exit": 0, "verdict": "'✓ skills/README.md' / '✅ Skill docs in sync' — the generated index block is untouched and still in sync." },
        { "cmd": "pnpm check:agent-test-spelling", "exit": 0, "verdict": "clean" },
        { "cmd": "pnpm check:corpus-claim-drift", "exit": 0, "verdict": "clean" },
        { "cmd": "pnpm check:cross-package-test-inputs", "exit": 0, "verdict": "clean" },
        { "cmd": "pnpm check:doc-authoring", "exit": 0, "verdict": "clean" },
        { "cmd": "pnpm check:driver-memory-census", "exit": 0, "verdict": "clean" },
        { "cmd": "pnpm check:merge-driver", "exit": 0, "verdict": "clean" },
        { "cmd": "pnpm check:nul-bytes", "exit": 0, "verdict": "clean" },
        { "cmd": "pnpm check:pm-governed-merges", "exit": 0, "verdict": "self-test, 274 assertions green (checker health, not the PR verdict)" },
        { "cmd": "pnpm check:pm-widening-tells", "exit": 0, "verdict": "clean" },
        { "cmd": "pnpm check:refd-timer-probe", "exit": 0, "verdict": "clean" },
        { "cmd": "pnpm check:role-word", "exit": 0, "verdict": "clean" },
        { "cmd": "pnpm check:skill-compatibility", "exit": 0, "verdict": "clean" },
        { "cmd": "pnpm check:skill-frame-sync", "exit": 0, "verdict": "clean" },
        { "cmd": "pnpm check:skill-identifier-liveness", "exit": 0, "verdict": "clean" },
        { "cmd": "pnpm check:watch-hint-literal", "exit": 0, "verdict": "clean" },
        { "cmd": "node scripts/check-skills-token-ratchet.mjs", "exit": 0, "verdict": "EXTRA, beyond the derived union (the reconciliation names it as the one extra). '✓ 36 authored bundle file(s) within their ceilings; 10 generator-owned file(s) measured, not ratcheted.' No skills/README.md row." },
        { "cmd": "node scripts/pm/check-governed-merges.mjs --test skills/README.md", "exit": 3, "verdict": "GOVERNED (as required): '⛔ GOVERNED — a human merge is the review record for this PR (#9495 regime).' / 'skills/** ×1 — the published skills catalog'." },
        { "cmd": "pnpm --filter create-objectstack test  [under os-verify-lock.sh]", "exit": 0, "verdict": "Test Files 16 passed (16) · Tests 203 passed (203) — includes template-consistency.test.ts, the /skills subpath ratchet." },
        { "cmd": "pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint  [under os-verify-lock.sh]", "exit": 0, "verdict": "prerequisite build, not a gate: 'VERDICT command-exit 0 · held the lock 166s · waited 0s'" }
      ],
      "line_budget": "not ratcheted — measured, not assumed. skills/README.md is population 3 (OUTSIDE) in check-skills-token-ratchet.mjs, pinned by that gate's own self-test, and check-skill-line-ratchet.mjs excludes the published catalog by design. Numbers reported anyway per the skills/** clause: changed file 119 to 127 lines (+8) and 2,079 to 2,215 tokens (+136); whole package (11 SKILL.md summed) 6,853 lines / 79,679 tokens, +0/+0. No ceiling was raised and none needed to be.",
      "files_changed": ["skills/README.md (+9/-1)"],
      "tests": "No test file was added or changed — this is a one-file documentation change on a governed surface. Evidence instead: (a) `pnpm --filter create-objectstack test` under the shared verify lock — 'Test Files 16 passed (16) · Tests 203 passed (203)', which is the suite carrying template-consistency.test.ts. (b) ONE-SHOT ABLATION proving that suite actually reads this file rather than passing vacuously: /skills was removed from line 9 on disk; the mutation was proven on disk by anchored grep -c (removed text 1 to 0, injected 0 to 1) BEFORE reading any result; the targeted run went RED — 'AssertionError: these lines advertise `skills add objectstack-ai/objectstack` without the /skills subpath', Test Files 1 failed (1), Tests 1 failed | 36 passed (37). Restore leg: `git checkout HEAD -- (absolute path)`, post-restore `git hash-object` == HEAD blob e274f0d5bb1178b72daf644f91ccd6914d08f3d3 and `git diff HEAD` empty (restore proven by artefact, not by an exit code); re-run GREEN, Tests 37 passed (37). Script carried `trap restore EXIT INT TERM` with absolute paths. No permanent test file was left behind. No build/dist step was needed — the assertion reads the working tree via git grep. (c) All 21 derived gate families exit 0, reconciled 21/21 with 0 UNRUN at 290c258ef.",
      "deviations": [
        "REST channel: probed once and refused — HTTP 403 'GitHub access is not enabled for this session' on GET /repos/.../issues/16806/labels. Declared switch to MCP for every GitHub read and write, as the dispatch anticipated.",
        "Labels: the additive REST endpoint being unavailable, the fallback was taken — MCP read current set (empty; the tool omits the labels key when empty, and it renders the key once a label exists, which is what makes the empty read trustworthy), union {} + {skip-changeset} = {skip-changeset}, whole-set write via issue_write update, comparative read-back = ['skip-changeset']. Nothing in the union is missing from the read-back; no concurrent label was stripped. Note the read-back proves the write landed, not that any gate reads the label.",
        "issue_read method 'get_labels' does not resolve a PR number in this MCP build ('Could not resolve to an Issue with the number of 16806'); the label reading was taken from pull_request_read get, which does render a labels array.",
        "Repo-scale lint (`pnpm lint`) not run — CI owns it. The narrowing is MEASURED, three pieces: (1) population read from eslint's own configuration, which answers 'File ignored because no matching configuration was supplied.' for this path; (2) count read from --format json: 1 result object, 0 errors, the single warning being that ignore notice rather than a finding; (3) invariance: the diff is one Markdown file eslint's config does not match and no TS/JS file is touched, so no untouched file's verdict can move.",
        "origin/main moved during the run: the dispatch cited b38821d1c, the branch was cut from b72226f48, and origin/main is now a749dcc4b. Assumption 1 was verified against the tree the branch was actually cut from, and the gate derivation uses three-dot merge-base semantics, so the 1-path change set is correct regardless.",
        "The README states the --all cost WITHOUT pinning the counts 46 and 11 (it says 'a full real copy in BOTH .agents/ and agent/, plus .claude/ symlinks'). Those counts track catalog size, would go stale silently, and no gate reads them; the dated numbers live in the PR body instead. This is a judgement inside the ruling's 'a one-line note that it writes the bundle to three destinations', flagged here and put to the maintainer as the single decision in the PR's 维护者速读."
      ],
      "mcp_calls": "9 — create_pull_request 1, pull_request_read get 2, issue_read get_labels 2 (both refused for a PR number), issue_read get 1, issue_write update 1, add_issue_comment 1, plus the comment read-back 1. Card and gate reading went through git and the local tree, not MCP.",
      "open_questions": [],
      "out_of_scope_findings": [
        "noted, not filed: content/docs/** still recommends --all in six places — content/docs/ai/skills-reference.mdx:27 and :30, content/docs/ai/skills.mdx:35, content/docs/getting-started/build-with-claude-code.mdx:57 and :381, content/docs/getting-started/your-first-project.mdx:45 and :286. Explicitly another seat's surface per this dispatch (#16400). Hand-off detail worth having: those skills-reference.mdx sites are HAND-AUTHORED prose, not generator output — the generated block in that file begins at line 38 and packages/spec/scripts/build-skill-docs.ts contains no install command at all, so there is no generator to re-run. Successor: the seat holding #16400.",
        "noted, not filed: skills/objectstack-pm-dispatch/SKILL.md:53 spells `npx skills add objectstack-ai/objectstack/skills --skill objectstack-pm-dispatch` — one named skill, no --agent and no -y, so the CLI prompts for the runtime interactively. Different shape from the --all defect and not obviously wrong; it is simply the one other install spelling left inside skills/**, and this card's surface is one file. Successor: none currently holds it.",
        "noted, not filed: after this change the scaffolder's own surfaces (packages/create-objectstack/README.md:60, src/templates/AGENTS.md:82, src/templates/blank/README.md:148) and skills/README.md all agree on the per-agent form, so the only remaining --all recommendations in the repo are the content/docs/** ones above. Successor: as above."
      ]
    }

    Generated by Claude Code

  7. hotlong commented on Sep 8, 2026

    @hotlong
    Contributor

    ACCEPT — flight L (skills seat, session session_01P58euzUXCVJNwmhuPC9DXY, 2026-09-08T06:31Z)

    PR #16806, head 290c258ef, one file (skills/README.md, +9/−1, no code). Governed surface (skills/**): check-governed-merges --test exits 3 GOVERNED — the PR stays a draft at the terminal; the four pieces (this ACCEPT · needs-user-decision + assignee on the PR · 速读终稿 · review request to os-zhuang) are placed this minute and read back.

    Review of the report against GitHub and the tree, not against itself:

    • Line 9 before/after, read from the refs: origin/main line 9 is npx skills add objectstack-ai/objectstack/skills --all; the branch's line 9 is the per-agent form --skill '*' --agent claude-code -y. The file carries exactly one catalog spelling and it keeps the /skills subpath — what the ruling required in every spelling. 127 lines.
    • --all stays as a labelled multi-runtime opt-in whose cost is stated as three destinations (a full real copy in both .agents/ and agent/, plus .claude/ symlinks into .agents/) — read in the diff. The remaining --all hits under skills/** on the branch are unrelated (os migrate --all and a prose line in the pm-dispatch skill).
    • The subpath guard is live, not assumed: packages/create-objectstack/src/template-consistency.test.ts line 680 ("no customer-facing surface advertises a repo-root skills install") exists on origin/main; the dev's one-shot ablation (subpath removed → 1 failed / 36 passed; restored by blob hash e274f0d5b… → 37 passed) proves it reads this file.
    • The measurement was re-run in this container (skills@1.5.23, 11 skills): --all → 46 + 46 real files plus 11 symlinks; the per-agent form → 46 files in one directory. Reproduces the card's shape exactly.
    • Not ratcheted, measured: check-skills-token-ratchet places skills/README.md in population 3 (outside), pinned by its own self-test; no ceiling moved. Reported anyway: 119 → 127 lines, 2,079 → 2,215 tokens; the 11 published SKILL.md unchanged.
    • Gates: 21 derived, 21 run, 0 unrun, plus the token ratchet beyond the union; check:skill-docs reports the generated index block untouched and in sync; pnpm --filter create-objectstack test 203/203 under the verify lock. skip-changeset measured (70 manifests, zero files[] toward skills/; edit-unique marker 0 hits, positive control 2).
    • CI on 290c258ef at 06:30Z: 35 check runs success/skipped, 3 in progress (Lint & Repo Gates, Type Check · workspace, Test Core 1/6), none red. The seat reads them again on the merge path.

    The one judgement inside the ruling, put to the maintainer in the 速读: the README states the cost without pinning the counts 46 / 11. The seat agrees — the counts track catalog size, no gate reads them, and pinning them is the next silent staleness; the load-bearing facts (three destinations, two of them full copies) do not drift. The dated numbers live in the PR body.

    Dispatch assumptions: all four held as measured (line 9 on main; not ratcheted — confirmed by running the gate, not by the seat's earlier print; the install measurable in this container; the consistency test pins the subpath, not the flags). Base moved b38821d1c → b72226f48 between dispatch and pickup; verified against the tree the branch was cut from.

    Out of scope, carried: (1) content/docs/** still recommends --all at six sites (ai/skills-reference.mdx 27 and 30, ai/skills.mdx 35, getting-started/build-with-claude-code.mdx 57 and 381, getting-started/your-first-project.mdx 45 and 286) — #16400's surface, another seat's; the hand-off detail (those skills-reference.mdx sites are hand-authored, the generated block starts at line 38, and build-skill-docs.ts emits no install command, so there is no generator to re-run) goes onto #16400 as a pointer from this seat. (2) skills/objectstack-pm-dispatch/SKILL.md line 53 spells a one-skill install with no --agent and no -y, so the CLI prompts interactively — a different shape, not obviously wrong, outside the three finding classes; recorded here, no card.

    Landing: a human merge is the review record. On an authorized APPROVED review, the seat reads the PR's event log first, then arms auto-merge (SQUASH) once every check run is green; on the merge, the landing record here with pm:dispatched and the assignee cleared. skills/README.md then frees.


    Generated by Claude Code

  8. github-actions commented on Sep 8, 2026

    @github-actions
    Contributor

    os-closed-card-sweep — machine-findable marker for this generated comment.

    Removed the pm-loop state label(s) this closed card no longer claims: pm:dispatched.

    A state label claims work is in flight. This card is closed on a merged delivery, so the claim
    is stale; every other label is left exactly as it was found. Nothing here is a judgement about
    the card, and no verdict-bearing label is ever touched by this sweep.

    posted by half-state-patrol run 34200831142 · trigger schedule

    Generated by Claude Code

  9. hotlong commented on Sep 8, 2026

    @hotlong
    Contributor

    Landed (skills seat, 2026-09-08T08:45Z; late record — the seat's GitHub channel was down 06:32–08:38Z). PR #16806 (governed skills/**) merged through the merge queue at 07:08Z under os-zhuang's APPROVED review 5138174610 on the PR head 290c258ef (06:32:06Z); the ready flip, the auto-merge arm (06:32:10–14Z) and the enqueue (06:41:45Z) were os-zhuang's own acts — the seat touched neither the draft bit nor the queue. Landing reading: origin/main carries 56ee7aef1 = "docs(skills): recommend the per-agent install that lands the bundle once (#16806)" as the last touch of skills/README.md; line 9 on main reads the per-agent form. ⚠️ Instrument note: a list_pull_requests head-filter read at 08:40Z still answered state: open for this PR 90 minutes after the merge event — the tree reading above is the landing reading, not that field (n=1, carried to #16779). pm:dispatched was removed by the patrol's closed-card sweep at 07:50Z; the seat clears the assignee now; domain:skills, priority:p3 stay. The docs-side remainder is #16400's (pointer left there).


    Generated by Claude Code

  10. removed their assignment
    on Sep 8, 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:skillsDomain lane — seat card indexed by label:pm:seatpriority:p3

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions