Skip to content

skills(platform): optimization flight — orphan and pointer files removed, hooks reference linked directly, requires/engines/onEnable taught (net −3,608 tokens) - #14351

Merged
os-zhuang merged 7 commits into
mainfrom
claude/issue-14299-skills-platform-optimization
Sep 2, 2026
Merged

skills(platform): optimization flight — orphan and pointer files removed, hooks reference linked directly, requires/engines/onEnable taught (net −3,608 tokens)#14351
os-zhuang merged 7 commits into
mainfrom
claude/issue-14299-skills-platform-optimization

Conversation

@os-litant

@os-litant os-litant commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Part of #14299

Skills catalog optimization flight for skills/objectstack-platform (program #14292, maintainer mandate 2026-09-02 「审核所有的 skills,进行全面的优化。」). The 50-finding audit record is posted verbatim on the card. Governed face — stays draft; needs:contract-review on both carriers.

Why Part of and not a closing keyword: only the implementable half of the card landed. PLAT-H-01 is deferred to decision card #14296 item 2 and PLAT-G-02 to the catalog follow-up below, so merging this must not close the card while its deferred half is still undecided. The card stays open; pm:dispatched is stripped by hand at merge.

Per-file token delta

Token unit is the ratchet's own: ceil(utf8 bytes / 4).

File before after ceiling note
SKILL.md 12984 12871 12984 −113; every addition paid in-file. Review round 1 spent 175 of the freed headroom on the corrected requires: table
references/plugin-hooks.md 2628 2413 2628 −215; absorbed the deleted pointer's DO/DON'T, plus the cross-flight link repair
rules/plugin-lifecycle.md 2404 1777 2408 −627
rules/service-registry.md 2329 1754 2331 −575
rules/bootstrap-patterns.md 1093 deleted row dropped orphan, zero inbound links
rules/plugin-hooks-events.md 985 deleted row dropped self-declared pointer that restated its target
evals/README.md 514 514 514 untouched — DEFERRED per #14296 item 2
references/_index.md 1344 1344 generated untouched

Package 24,281 → 20,673 = −3,608 (−14.9%). Bundle total 187,854 → 184,246. No ceiling was raised; no file grew; scripts/check-skills-token-ratchet.mjs was touched only to drop the two deleted files' rows.

The audit's package total of 24,278 is 3 tokens off — the measured base is 24,281 (sum of the eight rows above).

Why −3,608 and not the projected −5,970

Four of the projected reductions were withdrawn by evidence or by ruling, not skipped:

The five funded additions also cost more than the projected +355, because they were written against the measured facts (the requires: table carries all 20 provider-backed tokens plus the five rules that change what an author writes) rather than against the projection.

Per-item: 落点 | before | after

Deleted files

id 落点 before after
PLAT-B-01 rules/bootstrap-patterns.md 1,093 tokens with zero inbound links repo-wide — the only mention of its path was its own ceiling row. Content already carried by SKILL.md (driver table, HTTP-layer table, the "no driver: key, refused at load" block, manifest required fields); its own last line pointed back at SKILL.md deleted, with its ceiling row
PLAT-B-02 rules/plugin-hooks-events.md + SKILL.md:717,865 The file opened "This document is a compact pointer. Complete documentation lives in the canonical reference" and then reproduced it. SKILL.md linked only the pointer, so the 2,628-token canonical file sat two hops from the entry file deleted; SKILL.md links references/plugin-hooks.md directly at both sites. Path unchanged on purposeskills/objectstack-data/rules/hooks.md:202 links to it across packages; verified still resolving

Checked before deleting the pointer: it carried no fact absent from the canonical reference or SKILL.md. Its one non-hooks item ("no circular dependencies between plugins, both kernels throw") is already the Dependency resolution row of the ObjectKernel-vs-LiteKernel table.

references/plugin-hooks.md

id 落点 before after
PLAT-D-04 :312-327 7-item "Best Practices", every item restating a span of the same file replaced by the compact DO/DON'T folded in from the deleted pointer
PLAT-D-05 :238-251 "Hook Naming Conventions", 4 good / 2 bad names; the convention was already given at :80-82 and demonstrated at :225-232 deleted; its only new rule (lower-case) folded into the Custom Hooks convention line
PLAT-D-06 :252-311 two near-identical 25-line vitest blocks; the second differed only by asserting receivedData instead of hookCalled second block deleted

rules/plugin-lifecycle.md and rules/service-registry.md

id 落点 before after
PLAT-B-07 service-registry.md:145-158 the same table as SKILL.md:1008-1024 with inverted columns and only 6 of its 13 rows; both then repeated "the REST plugin registers no service" one table, in SKILL.md; the rules file points at it
PLAT-D-03 service-registry.md:270-319 "Service Naming Conventions" (generic: "use descriptive names", "avoid abbreviations") + a test block asserting only toBeDefined()/toThrow() + a 10-item Best Practices restating the file's own sections deleted
PLAT-D-08 plugin-lifecycle.md:201-230 the same ❌/✅ lesson as service-registry.md:193-223, differing only in names, closing on the same null-placeholder paragraph replaced by the rule plus a link to the one worked pair
PLAT-D-02 plugin-lifecycle.md:293-340 10-item Best Practices (1-7 restate the file's own Phase headings; 8-10 generic: "version your plugin", "use reverse domain names") + two vitest blocks asserting only toBeDefined()/isConnected() deleted
PLAT-C-05 plugin-lifecycle.md:110-113, SKILL.md:944-948 the data:* boundary was stated five times in-package in-package statements down to three; SKILL.md keeps exactly one (the one explaining the silent registration), per the anchor ruling; canonical statement stays in references/plugin-hooks.md

SKILL.md — structure

id 落点 before after
PLAT-B-05 section order 1,441 tokens preceded defineStack() — the core construct sat 12% down the file defineStack() (with the Manifest Reference it needs) is the first section after the title
PLAT-B-03 :39-49, :699-708 "When to Use This Skill" appeared twice, 650 lines apart, both restating the frontmatter both deleted — a loaded package is already selected
PLAT-B-06 :25-35 narrated the package's own edit history ("the original 'quickstart' skill", "which is why they live in one skill") one sentence naming the two concerns
PLAT-D-07 :142-158 "CRM Blueprint": rows 2-3 restated the directory tree 18 lines above; rows 5-6 pointed at data / i18n territory deleted; its only platform-specific row (requires:) is now taught properly under the Boot Sequence
PLAT-D-01 :735-758 ASCII "Decision Guide" restating the table two lines above; its gloss changed no branch deleted, table survives
PLAT-B-04 :1277-1279 "see Health Monitoring earlier in this skill" — that section documents an in-process TS API and contains no HTTP route cross-reference dropped

SKILL.md — truthfulness

id 落点 before after
PLAT-F-06 :347-381 driver-as-a-plugins:-entry taught as the canonical bootstrap. Zero example configs do it: app-showcase and the blank template list connector plugins, app-crm and app-todo have no plugins: key, and the CLI wires the driver itself from the resolved DB URL (serve.ts:2687-2745) selection table kept; the code reframed as embedding/tests only, with "pick a driver by setting the DB URL, not by writing code"
PLAT-F-05 :498-522 composeStacks() had a section plus a 3-row strategies table and zero usages outside packages/spec and its own tests reduced to a pointer at stack.zod.ts. Live surface with zero measured usage ⇒ one row, never delete the last mention
PLAT-C-01 :548-576 taught a raw data: [{ object: 'task', … }] literal — writing object: by hand, which objectstack-data/SKILL.md:1036 forbids verbatim ("Auto-set from objectDef.name — never write manually"); 24 real defineSeed( sites, 0 raw literals literal deleted, defineSeed() pointer added, mode table kept (see premise_false) and given the ⚠️ Data-loss flag on replace it was missing
PLAT-C-02 :626-663 re-taught field types in a shape 0 of 7 real object files use (export default {} vs ObjectSchema.create({…})) one line pointing at objectstack-data and the scaffolder's own note.object.ts
PLAT-G-01 :303,319,322-323,1035 five spans used the retired v5.0 word for the runtime workspace ("project runtime", "Project revisions", "isolated project kernel") against skills/README.md:88 and the os environments CLI surface all five now environment. Uses of "project" for the local source tree left alone — those are correct
imprecision :79-80 the blank template "ships One example object, in-memory driver, Hono server" — the template config has neither; its plugins: array holds three connector executors and both arrive from CLI auto-registration states what is in the file, and that the driver and server come from the CLI
PLAT-A-01 :5,9-10,20 and the section heading frontmatter sold "drivers, adapters" while :394-397 answers "There are no @objectstack/adapter-* packages" — promise and truth 385 lines apart description and heading now name the Hono HTTP layer
PLAT-G-03 :307-310 vs :1109 the os / objectstack alias was declared 800 lines after first use stated at first use
PLAT-C-04 :1299 a 60-token restatement of the very rule it delegates to objectstack-data symptom plus the one-line cause

SKILL.md — examples that could not compile

id 落点 before after
PLAT-E-01 :527-542 "Host Pattern" read as a complete config file but had ≥4 errors on paste: defineStack and SqlDriver used un-imported, CrmApp/TodoApp undefined, and new SqlDriver({ ... }) is TS1109 folded into the Multi-App Composition prose; no un-compilable block
PLAT-E-02 :1059-1073 typed the literal as a Plugin intersection then read this.pool.query(...) (TS2339) and err.message on a catch binding (TS18046); PluginHealthStatus never imported the opt-in contract in prose plus the three real kernel call sites
PLAT-E-03 :954-969 kernel.getService with a type argument naming a non-exported class from a different fence (TS2304) type argument dropped
PLAT-E-04 :296-298 defineStack({ ... }, { strict: false }) — TS1109 by construction defineStack(config, { strict: false })

The funded additions — each paid by a deletion in the same file

id 落点 before after
PLAT-F-01 Manifest Reference manifest.engines: { protocol: '^17' } has 4 real usages including every project the scaffolder emits, and grep engines skills/objectstack-platform/ returned 0 one manifest row plus why the runtime checks it before it loads anything
PLAT-F-02 Boot Sequence requires: [...] decides which service plugins boot; taught as one CRM-blueprint cell and one bare word, while the Boot Sequence narrated a fixed auto-register list and never said requires: drives it all 20 provider-backed tokens against their real pkg values, the two other resolution mechanisms kept separate from them, and five rules that change what you write: precedence, declaring-is-a-demand (declared-but-absent is a hard boot error, auto-injected-but-absent stays best-effort), auth implies email, keep automation whenever plugins: lists a connector, and pair triggers with job
PLAT-F-03 Boot Sequence the onEnable export — the seam where an app binds runtime code — has 4 real sites and was documented only in objectstack-data its own subsection with the AppPlugin invocation and a worked export
PLAT-F-04 Part 3 plugin authoring stopped at kernel.use(plugin) with no path to a distributable plugin; the ADR-0025 §3.4 pipeline was mentioned nowhere in skills/ a 3-row `os plugin build
PLAT-F-07 kernel decision the guide offered two answers and routed serverless/edge to LiteKernel, while the repo's own example for that shape uses neither kernel a third branch naming @objectstack/objectql/core and examples/embed-objectql (ADR-0076)
PLAT-A-02 frontmatter the description never named capabilities / requires:, the key that decides which service plugins boot one clause added, paid by A-01

Facts re-read against source before writing, per the card's assumption 5: blank/objectstack.config.ts:22,30; serve.ts CAPABILITY_PROVIDERS and the auth ⇒ email implication at :2281-2321; onEnable at app-showcase :283, app-crm :127, app-todo :33; PLATFORM_CAPABILITY_TOKENS in packages/spec/src/kernel/platform-capabilities.ts.

CAPABILITY_PROVIDERS holds 20 entries — the audit's "~20" was right. An earlier revision of this PR claimed 14 and offered that as a correction to the audit; that claim was itself wrong and is retracted. See Review round 1.

premise_false

  • PLAT-E-05 — premise false; not implemented. The audit proposed adding an os:check marker to the Complete Plugin Example so plugin/kernel examples would finally be type-checked. Measured: the gate's "skills + docs" surface resolves from packages/spec only (SURFACES in packages/spec/scripts/check-skill-examples.ts, resolutionDir: SPEC_DIR, selfPackages: [SPEC_DIR]), and @objectstack/core is not a dependency of packages/spec — that package's node_modules has no @objectstack scope at all. Marking the block produced skills/objectstack-platform/SKILL.md:804:44 error TS2307: Cannot find module '@objectstack/core'. Every plugin/kernel example in this package imports Plugin / PluginContext / ObjectKernel / LiteKernel from there, so no such example can be gated without a new SURFACES entry — another package, which this flight may not edit. The marker was reverted; check:skill-examples is green with 258 marked blocks. Filed as follow-up below.
  • PLAT-C-01 — premise partly false. "DELETE the mode table → one pointer line" is not available: check:skill-identifier-liveness registers ## Seed Data as exhaustive over SeedMode, and deleting the table turned five live members (insert, update, upsert, replace, ignore) into capabilities no AI author reading the catalog can reach. The gate caught it. Fixed the author's way — the table stays, and gained the ⚠️ Data-loss flag on replace the audit noted was missing. The shrink-only gap ledger is maintainer-only and was not touched.
  • PLAT-C-03 — not applied, by ruling. The card's ANCHOR RULINGS keep SKILL.md:59-70 because the pm-dispatch flight points there. The overlap the audit identified is real but is the anchor's to settle.
  • PLAT-G-02 — not applied, by ruling. Moving references/plugin-hooks.md to rules/ is exactly what the card forbids (the path is pinned stable for objectstack-data's inbound link). The catalog-wide drift it names is real and is listed as follow-up.

Card assumptions verified rather than assumed: (1) skills/objectstack-platform/** is byte-identical at a59f78d, d63c8a25 and this branch's actual base 909a4417git diff --stat empty for both; note origin/main had moved past the d63c8a25 named in the card. (2) bootstrap-patterns has zero inbound links, with plugin-lifecycle as a positive control that hits abundantly. (3) check:skill-docs is the drift gate, it is in the derived family, and the frontmatter edit did force regeneration — of two files, not one (below). (4) the ratchet reds on a deleted file whose row remains — probed directly: re-adding the row gave exit 1 and "cannot read … — red, not a skip (#4690)", then the script was restored and the restore confirmed by hash match.

Files outside the card's literal list

  • skills/README.md — regenerated, as the card anticipated for a frontmatter edit.
  • content/docs/ai/skills-reference.mdxalso regenerated, because one generator writes both and check:skill-docs fails on both. Not anticipated by the card; flagged here. Both diffs are frontmatter-derived only, confined to this package's row. Not content/docs/releases/.

follow-up for packages/spec

  • Extend SURFACES in packages/spec/scripts/check-skill-examples.ts with a resolution root that can see @objectstack/core, so plugin / kernel / service examples across the catalog become type-checkable. Today 78 of this package's 80 TypeScript fences are unchecked and the two checked ones both teach data authoring — the least proprietary content in the package. This is PLAT-E-05's real blocker.

follow-up for the catalog

  • PLAT-G-02: hand-authored per-topic files live under the generated references/ directory, which skills/README.md:55-58 reserves for generated pointers. This package and objectstack-data (references/data-hooks.md) both do it — a catalog-wide placement decision, not a lone slip, and one this flight is explicitly forbidden to settle by moving the file.

Review round 1

Contract review failed one span — the requires: table added for PLAT-F-02. Three defects, all from reading a bounded slice of CAPABILITY_PROVIDERS instead of reading it to its closing brace. Fixed in 224d5d9a; the cross-flight link repair below landed in 25012189:

# defect truth at source fix
1 audit row named @objectstack/service-audit @objectstack/plugin-audit (AuditPlugin), serve.ts:1473-1475 row corrected
2 triggers row named @objectstack/service-triggers, which does not exist @objectstack/trigger-record-change (RecordChangeTriggerPlugin), extras @objectstack/trigger-schedule (ScheduleTriggerPlugin, TimeRelativeTriggerPlugin) and @objectstack/trigger-api (ApiTriggerPlugin), serve.ts:1506-1537 row corrected; the entry's own comment ("so pair triggers with job") became a row note and the fifth rule
3 "the remaining vocabulary … resolve the same way", and the claim that the map holds 14 entries the map holds 20; the other eight tokens resolve by two different mechanisms table lists all 20 against their real pkg; the eight are split into tier-gated (no map entry, opened by dedicated run() blocks per the CAPABILITY_TO_TIER docblock at serve.ts:1166-1171) and enterprise/cloud (no open-edition provider: hierarchy-security ships in @objectstack/security-enterprise via plugins[], ai-seat and governance are cloud-runtime only, platform-capabilities.ts:57-66)

20 + 5 + 3 = the 28 tokens in PLATFORM_CAPABILITY_TOKENS, counted from the frozen array rather than asserted. Defect 3 is the one worth naming plainly: the "14 entries" figure was published as a correction to the audit when the audit was right and the correction was the error — a truncated read reported as a finding.

Cross-flight link repair

references/plugin-hooks.md routed readers to objectstack-data's rules/hooks.md for per-record validation, defaults and audit trails. The data flight (PR #14427, head 061e5f4c, delivered) DELETES that file and consolidates hooks into objectstack-data/references/data-hooks.md, so the reference was repointed before it could dangle — now a real relative link, ../../objectstack-data/references/data-hooks.md, verified to resolve from references/. The old text named both the doomed rules/hooks.md and the surviving references/data-hooks.md; naming only the survivor makes the span 22 bytes shorter. git grep rules/hooks.md over this package returns nothing further, so that was the only site.

The PR title still carries the pre-patch figure (−3,778); the accurate net is −3,608. Left alone deliberately — the patch instruction was not to retitle.

Gates

Head sha 25012189. Command list derived from the real change set by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (9 paths; re-derived after regeneration added the two generated files, which pulled in 20 further docs-family gates). The full 46 were run on 15b4ac79: 45 exit 0, 1 NOT MEASURED. Review round 1 touched only SKILL.md and references/plugin-hooks.md, so the change set and therefore the derived family are unchanged; the card-named gates were re-run on 25012189 and are listed below.

The one non-green in that full run is NOT MEASURED by its own verdict text — node scripts/check-test-completeness.mjs exits 3, not 1: "PREREQUISITE NOT MET — this gate grades a saved turbo run test log, and no log was named… the local reading for this gate is NOT MEASURED." CI tees the log and passes the path, so this branch is unreachable there. Not a finding, and not read as green.

Card-named gates on 25012189, every exit captured before any pipe, all exit 0:

gate verdict line
check-skills-token-ratchet "36 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted" — SKILL.md 12871 / 12984, plugin-hooks.md 2413 / 2628
check:skill-examples "258 marked example(s) across 100 file(s), 3 surface(s)"
check:skill-identifier-liveness "OK — Leg 1: 493 citation(s) over 46 published file(s) … Leg 2: 9 registered exhaustive section(s), 0 ledgered gap(s)" — 493, up from 491: the corrected package names are themselves live-checked citations
check:skill-docs exit 0 with no regeneration needed (round 1 touched no frontmatter)
check:skill-compatibility "11 SKILL.md file(s) reconciled against 78 workspace packages"
check:published-readme-links exit 0 — run additionally to prove the repointed cross-package link resolves

Two gates initially reported exit 3 for missing local build prerequisites and were re-run properly rather than recorded as failures: check:doc-formula-expressions (needed @objectstack/formula built) and check:skill-examples (needed @objectstack/client-react built — it refuses rather than false-greening, #7122). Both green afterwards.

Control bytes: node scripts/check-nul-bytes.mjs green, plus a direct scan of all changed files for the wider control-byte range — no hits.

skip-changeset applies and is on the PR: this diff releases nothing from any package. skills/ is named in the changeset gate's own release-nothing enumeration (scripts/check-empty-changeset.mjs), which pins a "skills/**-only PR carrying NO changeset" as a green fixture, and scripts/check-skills-token-ratchet.mjs is a CI-internal gate script — the workflow calls that the textbook case.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1

…-B-01)

`rules/bootstrap-patterns.md` had ZERO inbound links repo-wide — the only
reference to its path anywhere in the tree was its own ceiling row in
`scripts/check-skills-token-ratchet.mjs`. `SKILL.md:715-717` links only
lifecycle / service-registry / hooks-events, so nothing ever routed a reader
to it; verified with `git grep -n bootstrap-patterns` against a positive
control (`git grep -n plugin-lifecycle` hits abundantly).

Its content was already carried by SKILL.md: the driver table (:66-74 =
SKILL.md:351-357), the HTTP-layer table (:76-83 = :389-397), the "no `driver:`
key, refused at load" block plus the `defineStack validation failed` sample
(:7-31,87-105 = :209-234), and manifest required fields (:29-31,107-130 =
:327-339). Its own last line pointed back at SKILL.md.

1,093 tokens of the published bundle that no customer agent could reach.
The ceiling row goes with the file: the gate treats an unreadable ratcheted
path as RED, not as a skip (#4690) — verified by a controlled probe that
re-added the row (exit 1, "cannot read ... — red, not a skip"), then restored
the script and confirmed the restore by hash match.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
… the pointer file (PLAT-B-02, D-04, D-05, D-06)

`rules/plugin-hooks-events.md` opened by declaring itself "a compact pointer.
Complete documentation lives in the canonical reference" and then reproduced
that reference: the event table, the `data:*` warning, the custom-hook
convention, execution order, and a DO/DON'T list. SKILL.md linked only the
pointer, so the 2,628-token canonical file sat TWO hops from the entry file
behind 985 tokens that restated it.

SKILL.md now links `references/plugin-hooks.md` directly at both sites
(`:717` and `:865`) and the pointer file is deleted with its ceiling row.
Checked before deleting: the pointer carried no fact absent from the
canonical reference or from SKILL.md — its one non-hooks item ("no circular
dependencies between plugins, both kernels throw") is already the
`Dependency resolution` row of the ObjectKernel-vs-LiteKernel table. So the
merge is a relink plus a deletion, and the compact DO/DON'T shape it had is
what now closes the canonical file.

`references/plugin-hooks.md` PATH IS UNCHANGED on purpose:
`skills/objectstack-data/rules/hooks.md:202` links to it across packages, and
that link is verified still resolving.

Paid inside `references/plugin-hooks.md`, per the shrink-only ratchet:
  - PLAT-D-04 — the 7-item "Best Practices" list, every item of which
    restated a span of the same file, is replaced by the compact DO/DON'T
    rules-of-thumb folded in from the deleted pointer.
  - PLAT-D-05 — "Hook Naming Conventions" deleted; its only new rule
    (lower-case) folded into the Custom Hooks convention line.
  - PLAT-D-06 — the second of two near-identical vitest blocks deleted; it
    differed only in asserting `receivedData` instead of `hookCalled`.

Token deltas: references/plugin-hooks.md 2628 -> 2418 (ceiling 2628);
SKILL.md 12984 -> 12982 (ceiling 12984 — the relinked paths are shorter than
the deleted ones); rules/plugin-hooks-events.md 985 -> deleted with its row.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…07, C-05)

`rules/service-registry.md` 2329 -> 1754 tokens (ceiling 2331):
  - PLAT-B-07 — "Well-Known Service Keys" was the SAME table as
    `SKILL.md:1008-1024` with the columns inverted and only 6 of its 13 rows,
    and both then repeated "the REST plugin registers no service". One table
    now, in SKILL.md; this file points at it.
  - PLAT-D-03 — deleted "Service Naming Conventions" (generic advice: "use
    descriptive names", "avoid abbreviations"), a "Testing Service
    Registration" block whose only assertions were `toBeDefined()` and
    `toThrow()`, and a 10-item "Best Practices" list restating this file's own
    Registration Patterns section and its `null`-placeholder paragraph.

`rules/plugin-lifecycle.md` 2404 -> 1777 tokens (ceiling 2408):
  - PLAT-D-08 — the ❌/✅ "getService() in init() without a declared
    dependency" lesson was already in `service-registry.md:193-223`,
    differing only in the names used (CachePlugin/db-pool vs
    AnalyticsPlugin/objectql) and closing on the SAME paragraph about never
    registering `null`. Replaced with the rule plus a link to the one worked
    pair.
  - PLAT-D-02 — deleted a 10-item "Best Practices" list (items 1-7 restate
    this file's own Phase 1/2/3 headings; 8-10 are generic: "version your
    plugin", "use reverse domain names") and a "Testing Lifecycle" section of
    two vitest blocks whose only assertions were `toBeDefined()` and
    `isConnected()`.
  - PLAT-C-05 — dropped this file's copy of the `data:*`-boundary warning.
    The boundary was stated five times in-package; the canonical statement
    stays in `references/plugin-hooks.md` and SKILL.md keeps exactly one.

No content was moved to another package: each deletion either had a surviving
in-package statement or was generic advice that changed no decision.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…B/C/D/E/F/G)

Deletions and rewrites (SKILL.md 12984 -> 12696 tokens, ceiling 12984):
  - PLAT-B-05 — `defineStack()` was 12% down the file behind 1,441 tokens of
    preamble. It (with the Manifest Reference it needs) is now the first
    section after the title.
  - PLAT-B-03 — "When to Use This Skill" appeared TWICE, 650 lines apart,
    both restating the frontmatter. A loaded package is already selected.
  - PLAT-B-06 — the package narrated its own edit history ("the original
    'quickstart' skill"). A customer agent never chose between two former
    skills.
  - PLAT-D-07 — the CRM Blueprint restated the directory tree 18 lines above
    and pointed at data / i18n territory; only its `requires:` row was
    platform-specific, and that is now taught properly (F-02).
  - PLAT-D-01 — the ASCII Decision Guide restated the table two lines above.
  - PLAT-F-05 — `composeStacks()` had a section plus a strategies table and
    ZERO usages outside `packages/spec` and its own tests; real multi-app
    composition is AppPlugin registration. Reduced to a pointer at the schema,
    not deleted (live surface, zero measured usage).
  - PLAT-F-06 — driver-as-a-`plugins:`-entry was taught as THE canonical
    bootstrap; no example config does it and the CLI wires the driver itself
    from the resolved DB URL. Reframed as embedding/tests only.
  - PLAT-C-01 — seeds are objectstack-data's; the copy here taught a raw
    literal writing `object:` by hand, which that skill forbids verbatim.
    Now a pointer PLUS the `mode` table (see below).
  - PLAT-C-02 — the example object file re-taught field types in a spelling
    7 of 7 real object files do not use (`export default {}` vs
    `ObjectSchema.create({...})`).
  - PLAT-C-04, B-04 — a restatement of the rule it delegates, and a
    cross-reference to a section that documents an in-process TS API and
    contains no HTTP route.
  - PLAT-C-05 — SKILL.md stated the `data:*` boundary twice; one statement
    remains (the one that explains the silent registration).
  - PLAT-E-01, E-02, E-03, E-04 — four blocks that could not compile:
    `defineStack`/`SqlDriver` used un-imported with `CrmApp`/`TodoApp`
    undefined; `this.pool` on a plain object literal plus `err.message` on a
    `catch` binding; a type argument naming a non-exported class from another
    fence; and `{ ... }` / `{ … }` ellipsis placeholders (TS1109).
  - PLAT-G-01 — v5.0 vocabulary: the runtime workspace is `environment`, not
    `project`, in all five spans (skills/README.md:88; the CLI surface is
    `os environments`).
  - PLAT-G-03 — the `os` / `objectstack` binary alias is now stated at first
    use instead of 800 lines later.
  - PLAT-A-01 — the frontmatter sold "adapters" and the body refutes it 385
    lines in ("There are no `@objectstack/adapter-*` packages"). Both the
    description and the section heading now name the Hono HTTP layer.
  - The `blank` template's "in-memory driver, Hono server" was true of the
    RUNNING APP and false of the file a reader opens: the template config has
    neither; both arrive from CLI auto-registration.

Additions, each paid by a deletion in this same file:
  - PLAT-F-01 — `manifest.engines.protocol`, stamped into every project
    `create-objectstack` emits and carried by all three example apps, was
    mentioned NOWHERE in this package. One manifest row + why it is checked
    before anything loads.
  - PLAT-F-02 — `requires: [...]` decides which service plugins boot and was
    taught as one blueprint cell and one bare word. Now a token table plus the
    four rules that change what you write: precedence, declaring-is-a-demand
    (hard boot error vs best-effort), `auth` implies `email`, and keep
    `automation` whenever `plugins:` lists a connector.
  - PLAT-F-03 — the `onEnable` export, the seam where an app binds runtime
    code, used by all three example apps and documented only in
    objectstack-data.
  - PLAT-F-04 — `os plugin build|sign|publish`: authoring stopped at
    `kernel.use(plugin)` with no path to a distributable plugin.
  - PLAT-F-07 — a third answer to the kernel question: `examples/embed-objectql`
    uses NEITHER kernel (`@objectstack/objectql/core`, ADR-0076).
  - PLAT-A-02 — the description now names the capability key.

Generated files regenerated because the frontmatter changed, as the drift gate
demands: `skills/README.md` AND `content/docs/ai/skills-reference.mdx` (one
generator writes both; `pnpm --filter @objectstack/spec gen:skill-docs`). Both
diffs are frontmatter-derived only.

`## Seed Data` keeps its `mode` table: `check:skill-identifier-liveness`
registers that section as exhaustive over `SeedMode`, and deleting the table
made five live members unreachable (caught by the gate, fixed the author's
way — the shrink-only gap ledger is maintainer-only and was not touched). The
table now also carries the Data-loss flag on `replace` that it was missing.

PLAT-E-05 is NOT implemented — its premise is false; see the PR body.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…al registry (review round 1)

Contract review round 1 failed the `requires:` table I added in the previous
commit. Three defects, all mine, all from reading a bounded slice of
`CAPABILITY_PROVIDERS` instead of reading it to its closing brace:

1. `audit` named `@objectstack/service-audit`. The real entry is
   `@objectstack/plugin-audit` (`AuditPlugin`), serve.ts:1473-1475.
2. `triggers` named `@objectstack/service-triggers`, which does not exist. The
   entry is `@objectstack/trigger-record-change` (`RecordChangeTriggerPlugin`)
   with extras `@objectstack/trigger-schedule` (`ScheduleTriggerPlugin`,
   `TimeRelativeTriggerPlugin`) and `@objectstack/trigger-api`
   (`ApiTriggerPlugin`), serve.ts:1506-1537.
3. "the remaining vocabulary resolves the same way" was false, and so was the
   claim that the map holds 14 entries. It holds TWENTY — I bounded an `awk`
   range by guess and stopped at `sms`, then reported the truncation as a
   correction to the audit. The audit's "~20" was right and my correction was
   the error.

The table now lists all 20 provider-backed tokens against their real `pkg`
values, and the eight remaining tokens are separated into the two mechanisms
that actually resolve them: five tier-gated tokens with NO map entry, opened by
dedicated blocks in `serve.ts` `run()` (CAPABILITY_TO_TIER docblock,
serve.ts:1166-1171), and three enterprise/cloud tokens with no open-edition
provider at all — `hierarchy-security` ships in
`@objectstack/security-enterprise` via `plugins[]`, `ai-seat` and `governance`
are cloud-runtime only (platform-capabilities.ts:57-66). 20 + 5 + 3 = the 28
tokens in `PLATFORM_CAPABILITY_TOKENS`, counted from the frozen array rather
than asserted.

The `triggers` entry's own comment carries a rule an author needs — schedule
triggers run on the job service, "so pair `triggers` with `job`" — so that is
now both a row note and the fifth rule: `triggers` alone arms record-change
triggers, and autolaunched scheduled flows stay silent without `job`.

SKILL.md 12696 -> 12871 tokens, ceiling 12984 unchanged and not raised; the
growth is paid from the headroom this flight's own deletions created.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…ht's consolidation

`references/plugin-hooks.md` sent readers chasing per-record validation,
defaults and audit trails to `objectstack-data`'s `rules/hooks.md`. The data
flight (PR #14427, head 061e5f4) DELETES that file and consolidates hooks into
`objectstack-data/references/data-hooks.md`, so the reference is repointed
before it can dangle.

Now a real relative link rather than two bare file names:
`../../objectstack-data/references/data-hooks.md`, verified to resolve from
`references/` to skills/objectstack-data/references/data-hooks.md. The old text
named both `rules/hooks.md` and `references/data-hooks.md`; only the surviving
one is named now, so the span is 22 bytes SHORTER — references/plugin-hooks.md
2418 -> 2413 tokens (ceiling 2628, untouched).

`git grep rules/hooks.md` over this package returns nothing further, so this
was the only site.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@os-litant os-litant changed the title skills(platform): optimization flight — orphan and pointer files removed, hooks reference linked directly, requires/engines/onEnable taught (net −3,778 tokens) skills(platform): optimization flight — orphan and pointer files removed, hooks reference linked directly, requires/engines/onEnable taught (net −3,608 tokens) Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 06:53
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 2, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Sep 2, 2026
@os-zhuang
os-zhuang enabled auto-merge September 2, 2026 14:01
@os-zhuang
os-zhuang disabled auto-merge September 2, 2026 14:01
Nine sibling skills flights landed on main after this branch's base. Both
conflicts fell inside the BEGIN/END GENERATED: skills region of the two mixed
generated files (skills/README.md, content/docs/ai/skills-reference.mdx);
resolved by clearing the markers in place — preserving main's text-merged prose
outside the region — and regenerating both wholesale with
`pnpm --filter @objectstack/spec gen:skill-docs` on the merged tree.
scripts/check-skills-token-ratchet.mjs auto-merged (each flight edited its own
package's ceiling rows). No behaviour or content change to the platform package.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01489YWhZEoHT9oXshiyywQy
@claude
claude Bot requested a review from os-zhuang September 2, 2026 14:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xl skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants