… corrected
Flight 10 of the published-skills factual sweep. Every corrected claim was
settled against the implementing code (packages/spec ai + ui schemas,
packages/runtime action-execution, packages/mcp skill-prompts, the platform
tool/object-name registries and the liveness ledgers), never against another
document, with executed parse probes where the claim is behaviour-bearing.
Net: -15 tokens, -10 lines across the package; both ratcheted files stay under
their existing ceilings (no ceiling touched).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EnE7G31tqbxN1rqpQmzurT
Fixes #13841
Part of #13658 — flight ⑩ of the published-skills factual sweep (
skills/objectstack-ai, 3 files, 691 lines).Every corrected claim was settled against the implementing code, never against another document, with executed parse probes wherever the claim is behaviour-bearing. Governed surface: this PR stays DRAFT for human merge.
Result
11 distinct false facts across 21 landing sites. (The branch's single commit message says 9 — the count as it stood mid-sweep, before F9 / F10 / F11 were settled. This body carries the final tally; the branch is not force-pushed to repair a message.) Package inventory: ~255 behavioral claims across the three files (
SKILL.md602 ·references/_index.md45, generator-owned ·evals/README.md44) — 4.3% distinct / 8.2% by landing site, inside the 1.5–10% working range set after flight ⑧.~59 claims recorded NOT MEASURABLE (the flight-④
ai:routesclass — the whole in-product AI runtime is out-of-repo:git ls-files | grep -ic service-aireturns 0 in this repo). None silently skipped; they are listed at the bottom.Net: −15 tokens, −10 lines. Both ratcheted files stay under their existing ceilings; no ceiling touched.
The three standing probe classes all fired: enumeration-vs-schema-member-set (F1, F2, F7), cross-file contradiction (F5 — the document contradicted itself 12 lines apart, and the implementation settled it), and the wrong-default class (F6). One correction has a spec-side twin, filed rather than fixed here (see Spin-off).
Per-item: landing site | before | after
skill.zod.ts—triggerPhrasesis aretiredKeytombstone`triggerPhrases`— "Natural language phrases that activate the skill"triggerConditions…"defineSkill— trigger phrases + trigger conditions + bounded toolset"defineSkill—instructions+ trigger conditions + bounded toolset"evals/README.mdplanned structureskills/test-trigger-phrases.mdskills/test-trigger-conditions.md`tools`— "Direct tool references — legacy fallback"agent.zod.ts—retiredKey; probe rejectstools[](legacy)"AIToolSchemaas the live shape of that slotAIToolSchemawas removed withagent.tools(#3894); zero live references in the treepermissionscalloutpackages/spec/CHANGELOG.md, under the17.0.0heading: "removeSkillSchema.permissions— it never gated anything (#3686)". It istool.requiresConfirmationthat went in the 16.x lineEditioncolumnschema_reader/data_explorer/actions_executormarked OSSPLATFORM_TOOLS_BY_PACKAGEputs every one of those tools in a cloud package (service-ai,service-ai-studio)askagent… abuild-intent turn on OSS degrades gracefully"service-aipackage)… what a skill DOES serve on the open edition is itsinstructions, projected onto the MCPpromptsprimitive"packages/mcp/src/skill-prompts.tsActionyou attach … is auto-exposed as a tool"ai.exposed: true(defaultfalse) plus anai.descriptionof at least 40 chars"ActionAiSchema.exposedis.default(false); ADR-0011 §2 "opt-in gate. Skips unlessai.exposed === true"aiExposed: false)"aiExposedboolean is removed" (clean break). Probe rejects it at both the action and theaiblock. The liveaiExposedis onKnowledgeSourceonly — untouchedconfirmTextset,mode: 'delete',variant: 'danger')"mode: 'delete'/variant: 'danger'only (confirmTextis dialog copy, not a destructive signal;ai.requiresConfirmationoverrides either way)"actionLooksDestructiveinpackages/runtime/src/action-execution.ts— maintainer ruling #7828, Option A; probe both directionsaction.ai.category— a live, enforced surface)"action.ai.category— live, but listing-only: carried onto the tool, never sent to the model)"AIToolDefinition.categoryinpackages/spec/src/contracts/ai-service.ts: "Surfaced by tool-listing routes. Not sent to the model."guardrails/structuredOutput/memorypresented as working config[EXPERIMENTAL — not enforced] Parsed but no runtime consumer yet;packages/spec/liveness/agent.jsonrecords "no runtime reader" for each// token budget per invocation·// wall-clock cap per invocation(asserting caps)// declared only — nothing reads these yetblockedTopics(plus the token / time budgets) in agentguardrails" — prescribing an unenforced control as the remedyguardrailsfor a gate.guardrails/memory/structuredOutputare declared only — no runtime reads them, and real limits come from the quota service." The three enforced gates it already listed are keptguardrails' own describe: "real limits come from the quota service"evals/README.mdplanned structuretools/test-requires-confirmation.md— an eval planned for a key that no longer parsestools/test-strict-unknown-keys.mdtool.requiresConfirmationis inTOOL_RETIRED_KEY_GUIDANCE; probe rejects itZero out-of-list changes. The diff is exactly these sites.
Executed evidence
Two probe files, run against the built
dist(spec + runtime dependency closure rebuilt first, so nothing was read off a stale.d.ts).Probe 1 — both error directions through the published schemas (27 assertions)
Non-vacuity controls first — the three happy paths must PARSE, and did:
Then the retired-key direction — every key this document taught as authorable:
And the defaults / member sets the document asserts:
Probe 2 — the action-exposure and destructive-signal claims (12 assertions, 12 pass / 0 fail)
Both enum member-set assertions are read by parsing each candidate, not by introspecting a Zod internal — a first pass that reached into
.def.entriesreturnedundefinedthrough thelazySchemaproxy and would have read as a finding. That was an instrument fault, corrected, not a result.Probe 3 — the capability F5b adds, proven by execution (open edition, in-repo)
including
keeps the skill name, label and description,drops the tool-binding half — it is cloud-runtime-only,does not project an inactive skill, anddoes not project a skill without instructions— the four facts the new callout states.Gates
Families derived from the real diff by
node scripts/pm/dispatch-gates.mjs(no path argument — the script takes its own change set from the merge base; exit 0; it names the tree it answered for,objectstack-ai/objectstackat6e6d02bd1). 14 families, harvested with--commandsso neither spelling is dropped. Exit code captured with a redirect before any pipe.node scripts/check-ci-filter-parity.mjsnode scripts/check-cross-package-test-inputs.mjsnode scripts/check-shard-attestation.mjsnode scripts/check-skills-token-ratchet.mjsnode scripts/check-test-completeness.mjsturbo run testlog that only CI producespnpm --filter @objectstack/lint run check:doc-formula-expressionspnpm check:agent-test-spellingpnpm check:corpus-claim-driftpnpm check:cross-package-test-inputspnpm check:doc-authoringpnpm check:pm-governed-mergespnpm check:role-wordpnpm check:skill-compatibilitypnpm check:skill-frame-syncRun beyond the derived list, because the diff edits prose inside an
os:checkfence (the agent example) and the flight-③ calibration makes the population rule binding:pnpm --filter @objectstack/spec run check:skill-examplesnode scripts/check-nul-bytes.mjscheck:skill-examplespopulation control (the rule from #13658 comment 5476328676): the population is non-empty for this surface — the gate reportsskills + docs (@objectstack/spec): 227 block(s)of 260 total, and this package contributes 4os:checkfences to it. Not an empty-population reading. The first invocation exited 1 with "packages/client-react/dist holds no .d.ts declarations — the package is not built"; that is a refused verdict, not a finding, and it was cleared by building the workspace (turbo run build --concurrency=2, 70/70 successful) and re-running.Ratchet, before and after
references/_index.md(796 tokens) is generator-owned — measured, not ratcheted, and not hand-edited;check:skill-frame-syncis green, so it is in sync withgen:skill-refs. Package delta −15 tokens / −10 lines; net line budget satisfied (≤ 0). Ceilings are the maintainer's and none was moved — the same posture the eight preceding flights landed with.Repo-wide ESLint: a declared narrowing, with the measurement
pnpm lint(eslint . --no-inline-config) is CI's run. Locally the check was narrowed to the changed files, and the narrowing is measured, not assumed — all three legs:npx eslint --no-inline-config --format jsonon both changed paths returns, for each,File ignored because no matching configuration was supplied..mdat all, so a Markdown-only diff cannot move any judgment on any file eslint does lint. No type-aware linting is reachable for a file with no matching config.skip-changesetapplies and the label is attached at creation: the diff is twoskills/**Markdown files and publishes nothing from any package — the same shape as the eight preceding sweep PRs, none of which carried a changeset.NOT MEASURABLE — recorded, not skipped
The in-product AI runtime is out of this repo.
git ls-files | grep -ic service-aireturns 0;packages/services/holds 16 members and none of them isservice-ai; everyagent/skillliveness-ledger consumer is attributedcloud: packages/service-ai/…. So ~59 claims about that runtime are recorded NOT MEASURABLE rather than false — the flight-④ai:routesboundary. Grouped:ask/buildruntime behaviour: surface binding, the resolution chain throughapp.defaultAgent, "no per-turn intent classifier", the decline-and-redirect, thedata_chat/metadata_assistantalias resolution, and the identifierASK_AGENT_NAME(zero code references in this tree; its only in-repo mention is an unchecked follow-up item in ADR-0063, so absence here is not evidence about cloud).resolveActiveSkillsraising a fast load error on an incompatible binding, and the tool-set union with no global fall-through. Corroborated one level down —packages/lint/src/validate-ai-surface-affinity.tssets ERROR severity becauseresolveActiveSkills()throws — but the runtime half is not readable here.PLATFORM_TOOLS_BY_PACKAGE; the skill-to-tool assignment lives in cloud. Worth a note for a later flight:search_knowledgeis in that registry and is referenced by this document's Knowledge section, yet no row of the built-in-skills table claims it. Not correctable from here without inventing an owner.visualize_datacallout (auto-registered only when anIAnalyticsServiceis wired).AI_DAILY_USER_MESSAGES, theai_usage_dailyobject,GET /api/v1/ai/status. All three have zero references anywhere in this tree — but so doesai_pending_actions, which the open repo's ownIAIServicecontract does describe, so absence from the object-name registries is not evidence either way.registerActionsAsTools,AIServicePluginoptions,enableActionApproval, the pending-actions REST endpoints,actionSkipReason/actionRequiresApproval. TheIAIServicehalf is verified here —proposePendingAction/approvePendingAction/rejectPendingAction/listPendingActionsall exist and are all optional, exactly as stated.Verified-and-unchanged, worth naming because they are the claims most likely to be assumed stale: the whole KnowledgeSource table and its three source kinds (complete against the schema's member set — 9 rows covering all 10 members,
labelanddescriptionsharing one), both model-provider enums, the trigger-condition operator set, every structured-output default,defineStack's AI collections (agents/tools/skills, with no knowledge-source collection), theagentmetadata type'sallowRuntimeCreate: false, allowOrgOverride: false,action.requiredPermissions(ADR-0066),IKnowledgeService.registerSource/registerAdapterwith thememoryandragflowadapter ids, thetype:'api'body-assembly order, and the frontmatter'sRequires @objectstack/spec 17.x(this tree is 17.2.0 on Zod ^4.4.3).Spin-off
#13865 —
ActionAiSchema.requiresConfirmation's JSDoc inpackages/spec/src/ui/action.zod.tsstill namesconfirmTextas a destructive signal, contradictingactionLooksDestructiveand ruling #7828. This is the spec-side twin of F8: fixing only the skill would leave the same false fact published one surface over. Filed unassigned, single-site drift (the two other in-repo carriers already state the corrected rule).needs:contract-reviewis attached to this PR and to card #13841 in the same stroke as creation (clause ② CONTENT limb, 批 #12); this seat does not self-clear it.Generated by Claude Code
Generated by Claude Code