Skip to content

Skills optimization flight — skills/objectstack-ai: RESTRUCTURE (≈ −2,300 tok, −29%) — 26% of the file teaches the agent surface it forbids its readers, the flagship defineSkill example declares four tools that resolve to nothing, and the open-edition MCP path (the only AI path without a cloud licence) is taught nowhere #14305

Closed

Description

@os-litant

Member card of the skills catalog optimization program #14292 (maintainer mandate 2026-09-02, verbatim: 「审核所有的 skills,进行全面的优化。」). Filed by the skills lane seat (session session_01LraLgQVGq8egUwfYZpbYt1). Read-only audit at objectstack origin/main a59f78d. Full findings table = audit record: the dev posts audit/objectstack-ai/findings.md (seat scratchpad) verbatim as the first comment at claim time.

Audit summary

SKILL.md 592 lines / 6,791 tok (headroom 15) · evals/README.md 315 (headroom 0) · generated _index.md 819 — package 7,925. Real usage: zero *.skill.ts / *.tool.ts / *.agent.ts files in examples or apps; only 3 patterns have real usage — action.ai.exposed + ai.description (7 usages), the MCP action bridge (examples/app-todo/test/mcp-actions.e2e.ts + all of packages/mcp), and app.defaultAgent (1). Model registry, conversations, MCPServerRef/MCPToolBinding have zero consumers outside packages/spec. The "agents are platform-internal" boundary still holds (os g agent retired with a prescription; agent.tools/agent.knowledge are retiredKey() tombstones) — yet the package spends 1,777 tokens (26%) teaching that closed surface. Verdict RESTRUCTURE: weight inverted against usage; defineTool (0 usages, no runtime reader until ADR-0109 lands) gets a full section while action.ai (7 usages) gets 371 tokens near the bottom; the description promises three surfaces the body never teaches.

Top findings

id span proposal Δtok
AI-B-02 SKILL.md:145-215 DELETE agent Required/Optional/Example (section opens "third parties do not author agents"); keep 2 retirement rows −600
AI-C-01 :28-36,83-86,89-90,126-131,330-335,339-342,360,364-365 MERGE-INTO :28-36 — "runtime is cloud/EE, open = MCP" restated 8× = 715 tok; replace 7 with a marker −350
AI-F-04 :289-335,552-565 *.tool.ts → a note row; ADR-0109: "no runtime reader until that lands" (stack.zod.ts:594-601) −230
AI-D-03 :495-521 DELETE §Structured Output — agent-only field the file itself calls "declared only" −217
AI-H-01 evals/README.md:1-44 planned-eval stub, lists 5 files that don't exist (DEFERRED, #14296 item 2) −195
AI-D-07 :362-381 REWRITE-AS-CONSTRUCT — HITL narration; every symbol cloud-closed −165
AI-D-05 :442-456 MERGE-INTO :409-413 table — 5 items restating keys from 30 lines above −150
AI-A-02 :475-491 REWRITE-AS-CONSTRUCT — "Model Selection"/"Temperature" taste tables; the enforced fact (temperature min 0 max 2, agent.zod.ts:38) is missing −140
AI-B-01 :40-50 DELETE "When to Use" −125
AI-D-01 :63-73 DELETE "Why Three Tiers?" analogy table + a false best-practice blockquote −124
AI-D-04 :461-473 DELETE vendor model catalogue; keep the enum blockquote −110
AI-D-06 :526-529,541-544 DELETE pitfalls 1/2/4 — generic prompt advice the frontmatter disclaims −99
AI-C-02 :138-141 DELETE ops callout — ai_usage_daily has no open-repo object −62
AI-E-01 :251-275 REWRITE — the flagship defineSkill example declares tools: ['query_support_case', …]; none is in PLATFORM_PROVIDED_TOOL_NAMES or stack.tools[] or action_* — exactly the failure ai-skill-tool-unresolved (packages/lint/src/validate-ai-tool-references.ts:150-171) exists to catch; the package's own defineTool example defines create_case, so the two examples don't compose 0
AI-B-03 :20-218 reorder — first customer-authorable section starts at line 218 0

Net ≈ −2,303 of 7,925 (29%) after +312 of paid additions.

Incidental falsehoods (fix in this flight)

  1. SKILL.md:71-73 — "Direct tool assignment to agents is supported but considered legacy." FALSE: agent.tools is a retiredKey() tombstone → parse error (agent.zod.ts:234-236); the same file says so at :168. HIGH.
  2. SKILL.md:579-580 — "any CEL predicate (e.g. a tool's availability condition)". FALSE: ToolSchema carries no CEL expression (tool.zod.ts:132-168); the only AI CEL carriers are ai/model-registry promptTemplate.system/.user. The same wrong premise sits in skills/README.md:104-105 ("AI tool params") — record it under "follow-up for skills/README.md". HIGH.
  3. Residue (code fact, not a doc edit): SKILL.md:96-98 says metadata_assistant is "not vocabulary" while packages/platform-objects/src/apps/studio.app.ts:50 pins defaultAgent: 'metadata_assistant' — file as an out-of-scope card.

Three funded additions

  1. Open-edition MCP wiring (+180, paid by AI-D-03): MCPServerPlugin / MCPServerRuntime from @objectstack/mcp, the /api/v1/mcp endpoint, the tool names a client sees (list_actions, run_action, query_records, describe_object).
  2. skill.tools[] resolution ladder + the platform tool registry (+0, paid by AI-B-02): the ADR-0109 default path and the ~30 real names in packages/spec/src/system/constants/platform-tool-names.ts:38-80.
  3. Trigger-condition operator↔value shape column (+30, paid by AI-D-01 + AI-B-01): in/not_in → array, eq/neq → string, contains → either (skill.zod.ts:37-50,130-175).

Flight scope

IMPLEMENT (same-file, shrink-only): all rows above and in the findings file at HIGH or MED; the three funded additions; falsehoods 1–2; AI-E-01 rewrite so the flagship example resolves; AI-A-01 description edit (stop promising conversations / model registry / MCP integrations the body does not teach, or teach MCP via addition 1).

ANCHOR RULINGS: MCP server / plugin wiring → this package teaches the open-edition path; objectstack-platform keeps plugin mechanics. Formula/CEL → objectstack-formula (delete the false CEL claim).

DEFER: AI-H-01 (eval stub, #14296 item 2); AI-B-04 (generator map vs body mismatch — out-of-scope card for the spec lane's build-skill-references.ts SKILL_MAP).

Flight constraints (binding)

  • ONE draft PR, first line Fixes #<this card>; governed ⇒ stays draft; review requests are the seat's step.
  • Token ratchet: no ratcheted file may grow; additions paid by deletions in the SAME file; ⛔ re-wrap is not payment; ⛔ no ceiling raise; ⛔ no new files; ⛔ do not touch the ratchet script.
  • ⛔ Never edit another package's files or skills/README.md prose; follow-ups go in the PR body. Generated files untouched. Regenerate the README index only if a drift gate requires it (report which).
  • Live surface with zero measured usage ⇒ one row pointing at its schema; retired/tombstoned ⇒ delete. A false claim matching a spec .describe() string ⇒ spec-side twin card.
  • Gates: node scripts/check-skills-token-ratchet.mjs, pnpm --filter @objectstack/spec check:skill-examples, pnpm check:skill-compatibility, pnpm check:skill-identifier-liveness, plus node scripts/pm/dispatch-gates.mjs --commands <changed paths>; record the head sha.
  • PR body: per-item 落点 | before | after keyed by finding id; per-file token delta; needs:contract-review on both carriers (falsehood 1 and the trigger-operator column are contract-semantics claims).

Refs: #14292 · #14296 · #13658.

Activity

  1. self-assigned this
    on Sep 2, 2026
  2. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    Claim: PM loop round 2
    Session: session_01LraLgQVGq8egUwfYZpbYt1
    Branch: claude/issue-14305-skills-ai-optimization
    Worktree: objectstack-issue-14305
    Domain: domain:skills
    File surface: skills/objectstack-ai/SKILL.md ONLY (shrink-only; ceiling 6,806, headroom 15); evals/README.md untouched (AI-H-01 deferred, #14296 item 2); generated references/_index.md untouched; no file deleted ⇒ ⛔ no edit to scripts/check-skills-token-ratchet.mjs; skills/README.md + content/docs/ai/skills-reference.mdx regenerated only because the drift gate demands it after the AI-A-01 description edit (⛔ no hand edit to README prose — the false "AI tool params" CEL premise at skills/README.md:104-105 goes in the PR body as a follow-up); ⛔ no other package (stop on breach; explain in the report)
    Container & model: S/M (one 6,791-token file, 592 lines; three funded additions with source-pinned semantics), mode:subagent, model: opus — --tier reads no path-derived mandate (floor sonnet · default opus · ceiling fable); the content limb applies, compensated by the seat's in-seat review at CONTRACT_REVIEW_TIER (served model read claude-fable-5-1 at 06:08Z)
    Clause-②: yes — falsehood 1 (agent.tools is a retiredKey() tombstone, not "legacy"), falsehood 2 (no CEL carrier on ToolSchema), the trigger-condition operator ↔ value-shape column, the temperature bounds, the MCP tool names a client sees, and the skill.tools[] resolution ladder are contract-semantics claims ⇒ needs:contract-review on both carriers at PR creation; in-seat review before any human review request
    Serial constraints cleared: this package is the ANCHOR for the open-edition MCP path (objectstack-platform keeps plugin mechanics; its delivered flight PR #14351 lists mcp → @objectstack/mcp in the requires: table and does not teach the endpoint); CEL → objectstack-formula (flight not dispatched; stable path); no open PR touches skills/objectstack-ai/**; skills/objectstack-ai/** byte-identical between a59f78d and origin/main d16df741 (seat-measured 07:1xZ); in flight alongside #14302 (query) and #14304 (api) on disjoint directories, with #14300 (pm-dispatch) delivered and under seat review

    Decision re-read: no maintainer ruling on this card; binding inputs = the mandate, the value gate, the ratchet discipline, and #14296 (item 2 deferred: eval stub untouched). Falsehood 3 (metadata_assistant pinned by studio.app.ts:50) and AI-B-04 (generator SKILL_MAP mismatch) go out as out-of-scope finding cards, not doc edits. Landing form: first line Part of #14305 (the deferred eval stub keeps the card open).


    Generated by Claude Code

  3. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    Claim (dev): os-dev subagent, dispatched by the skills-lane PM seat.
    Session: session_01LraLgQVGq8egUwfYZpbYt1
    Branch: claude/issue-14305-skills-ai-optimization (empty branch pushed as the write-route probe before any edit)
    Worktree: ../objectstack-issue-14305, base d16df741808edbe39e0b6e09c993e440bad78444 (origin/main)
    Assignee untouched (PM owns it).

    Verified before the first edit: git diff --stat a59f78d..d16df741 -- skills/objectstack-ai/ is empty — the audit's spans are byte-identical at my base, so file:line citations resolve as written. PM mechanism assumption 1: confirmed.

    Channel note: repo-scoped REST is 403 for this seat (GitHub access is not enabled for this session), so card + comment reads went through the public-repo page payload (zero quota) and writes go through MCP. git push is green.

    File surface for this flight: skills/objectstack-ai/SKILL.md only, plus skills/README.md and content/docs/ai/skills-reference.mdx as generator output of check:skill-docs after the AI-A-01 description edit. evals/README.md, references/_index.md and scripts/check-skills-token-ratchet.mjs untouched.

    Landing form: draft PR, first line Part of #14305 (AI-H-01 deferred to #14296 item 2 ⇒ this card stays open), needs:contract-review on both carriers.

    Next comment is the full audit record, posted verbatim.


    Generated by Claude Code

  4. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    audit-record — skills/objectstack-ai (read-only audit at a59f78d)

    Transliteration key — the GitHub body sanitizer is measured to eat angle-bracket-shaped
    fragments, so the 4 that appear in this record are spelled without angle brackets. Read:

    • AI_DAILY_USER_MESSAGES=N = the env var assigned an angle-bracketed placeholder N (AI-C-02).
    • action_NAME = the action_ prefix followed by an angle-bracketed name placeholder — the third
      rung of the tool-resolution ladder (AI-E-01, AI-F-04; 2 occurrences).
    • os:check-marker-comment = the fence marker itself: an HTML comment whose body is os:check,
      placed directly above a fenced block (AI-E-02).

    Everything else below is the audit file verbatim.


    Audit — skills/objectstack-ai/ (published package)

    Read-only audit. Pinned ref requested: objectstack origin/main = a59f78d.
    Checkout note: /home/user/objectstack HEAD is a39b02a (2 commits ahead of
    a59f78d). git diff --stat a59f78d..a39b02a -- skills/ is empty, so every
    span below is identical at the pinned ref. Spans cited as file:line-line.

    Package inventory (measured — node scripts/check-skills-token-ratchet.mjs)

    File Lines Tokens Ceiling / headroom
    skills/objectstack-ai/SKILL.md 592 6,791 6,806 / 15
    skills/objectstack-ai/evals/README.md 44 315 315 / 0
    skills/objectstack-ai/references/_index.md 45 819 generator-owned, not ratcheted
    Package total 681 7,925 —

    Sibling sizes for scale: data 13,892 · platform 12,984 · automation 12,768 ·
    pm-dispatch 14,549 · i18n 6,337 · api 6,311 · formula 6,002 · query 5,443.

    Real-usage census (what I grepped)

    Grepped examples/**, packages/apps/**, packages/** (excluding
    node_modules, .git) for every surface the package teaches:

    Surface taught Real usages found Where
    action.ai.exposed + ai.description 7 examples/app-todo/src/actions/task.actions.ts:16,33,109,126,148,168; examples/app-showcase/src/ui/actions/index.ts:431
    MCP server runtime (@objectstack/mcp) 1 e2e + whole package examples/app-todo/test/mcp-actions.e2e.ts:22,110-113; packages/mcp/src/** (30 files)
    app.defaultAgent 1 packages/platform-objects/src/apps/studio.app.ts:50
    *.skill.ts / defineSkill 0 authored CLI template exists: packages/cli/src/commands/generate.ts:184-251
    *.tool.ts / defineTool 0 authored ADR-0109: stack.tools "has no runtime reader until that lands" (packages/spec/src/stack.zod.ts:594-601)
    *.agent.ts / defineAgent 0 third-party os g agent is retired: packages/cli/src/commands/generate.ts:301-319
    KnowledgeSource registration 0 in examples Impl real: packages/services/service-knowledge, packages/plugins/knowledge-{memory,ragflow}, packages/plugins/embedder-openai
    Model registry entries 0 consumers outside packages/spec grep -rl ModelRegistryEntry|ModelRegistrySchema packages/ examples/ → only packages/spec/**
    Conversations 0 consumers outside packages/spec same grep for ConversationSchema
    MCPServerRef / MCPToolBinding 0 consumers outside packages/spec same grep

    find examples packages/apps -name "*.skill.ts" -o -name "*.tool.ts" -o -name "*.agent.ts" → zero files.

    Distinct real-usage patterns: 3 (action.ai exposure · MCP action bridge ·
    app.defaultAgent). Everything else the package teaches is a supported-but-unused
    surface, a cloud-closed surface, or a zero-consumer schema.


    Findings

    id dim file:span evidence proposal Δtok value gate ①②③ conf human-floor
    AI-A-01 A skills/objectstack-ai/SKILL.md:3-10 Description promises "AI skills, tools, knowledge sources, conversations, model registry entries, and MCP integrations". Body coverage: grep -ni conversation SKILL.md → only the word "Conversational" at :80,489; model registry → one parenthetical at :470-473; MCP → four edition-boundary asides (:28,35,86,130,342,535), no authoring content. Three of six advertised surfaces are untaught, and all three have zero consumers outside packages/spec (census above). REWRITE-AS-CONSTRUCT — cut conversations, model registry entries, and MCP integrations from the description; add MCP back only alongside AI-F-01's addition −18 ① yes — stops a customer agent loading this package for conversation/model-registry work it cannot help with ② yes, deletion is the whole fix ③ n/a (frontmatter) HIGH yes
    AI-A-02 A skills/objectstack-ai/SKILL.md:9-10 vs :475-491 Description: "Do not use for general LLM prompting questions unrelated to ObjectStack metadata." Body then spends 163 tokens on "Model Selection Guidelines" (GPT-4o / Claude Sonnet 4 for "complex reasoning") and "Temperature Guidelines" (0.7–1.0 Creative writing) — vendor-catalogue advice with no ObjectStack decision in it. The enforced fact is absent: temperature: z.number().min(0).max(2) (packages/spec/src/ai/agent.zod.ts:38) — a parse error outside 0–2. REWRITE-AS-CONSTRUCT — delete both tables, keep one line: `model`: free string · `temperature` 0–2 (parse error outside) · `maxTokens`/`topP` optional −140 ① yes — the 0–2 bound changes what parses; "GPT-4o for reasoning" changes nothing ② yes ③ yes — one line replaces two taste tables HIGH no
    AI-B-01 B skills/objectstack-ai/SKILL.md:40-50 "## When to Use This Skill" is a 5-bullet restatement of the frontmatter description the agent has already read (both say: skills, tools, knowledge sources for RAG, LLM models, agents are read-only). DELETE −125 ① no decision changes ② deletion is the fix ③ n/a HIGH no
    AI-B-02 B skills/objectstack-ai/SKILL.md:145-215 792 tokens of AgentSchema reference (Required Properties, 12-row Optional Properties, a 34-line defineAgent example) opening with its own disclaimer: "Reference only — third parties do not author agents." The runtime agrees: packages/cli/src/commands/generate.ts:301-319 retires os g agent; packages/lint/src/validate-ai-agent-authoring.ts:8-14 — "listAgents() filters non-platform records out of the catalog, and loadAgent() refuses them outright … a stack-authored agent 404s on chat". Zero *.agent.ts in the repo. DELETE §Required/Optional/Example; keep ~80 tokens: the two retired-key rows (:168 agent.tools, :171 agent.knowledge) folded into the existing :96-101 callout, and a pointer to references/_index.md for AgentSchema −600 ① the deleted text changes no decision a third party may legally make ② yes ③ yes — 2 retirement lines survive as the construct HIGH yes
    AI-B-03 B skills/objectstack-ai/SKILL.md:20-218 Section order: the first authorable-by-a-customer surface (## Skill Configuration) begins at line 218 — 199 lines (≈33% of the file) of preamble: three-tier diagram, "Why Three Tiers?" analogy, built-in-agent narration, and the reference-only agent section. The two surfaces with actual repo usage (action.ai at :337, MCP at nowhere) sit at the bottom or are absent. MOVE-TO — reorder: Skill Configuration → Actions-as-tools → MCP (new) → Knowledge → Tool metadata (with its ADR-0109 "usually don't author this" caveat) → agent/edition reference 0 ① yes — the first 1,500 tokens an agent reads should be the task it was loaded for ② partly (AI-B-02 removes most of the preamble) ③ n/a HIGH yes
    AI-B-04 B skills/objectstack-ai/references/_index.md:12-21 vs SKILL.md body The generated index advertises 10 core schemas; the body teaches 4 (agent, tool, skill, knowledge-source). conversation.zod.ts, mcp.zod.ts, embedding.zod.ts, knowledge-document.zod.ts, usage.zod.ts are listed but never mentioned. Conversely ai/solution-blueprint.zod.ts — the schema behind the solution_design skill the body names at :120 — is absent from the generator map (packages/spec/scripts/build-skill-references.ts:98-109). (generator-owned; no direct edit) FLAG — a maintainer ruling: either the map narrows to what the body teaches, or the body earns the extra schemas. Record as the input to AI-A-01. 0 ① yes — an index promising 6 untaught schemas invites the agent to Read node_modules it has no guidance for ② n/a ③ n/a MED yes
    AI-C-01 C skills/objectstack-ai/SKILL.md:28-36, 83-86, 89-90, 126-131, 330-335, 339-342, 360, 364-365 The single fact "the in-product AI runtime is cloud/EE; the open edition is MCP-only" is restated 8 times, measured at 183+65+43+115+107+74+94+34 = 715 tokens. Sample duplication — :28-31 "The in-UI AI runtime … ships in the cloud / Enterprise distribution, not the open framework" vs :126-128 "All four are cloud-runtime skills — none resolves on OSS. The open framework ships no in-product agent (there is no service-ai package)" vs :339-342 "Cloud / EE runtime. registerActionsAsTools(), AIServicePlugin, and the HITL approval queue below ship in @objectstack/service-ai". MERGE-INTO :28-36 (the canonical anchor — it is the file's first blockquote and names the package). Replace the other seven with a bare ☁️ marker on the affected headings, defined once in the anchor. −350 ① no — restatements 2–8 change no decision the anchor has not already changed ② yes ③ yes — one legend + 7 glyphs HIGH no
    AI-C-02 C skills/objectstack-ai/SKILL.md:138-141 "Ops: set AI_DAILY_USER_MESSAGES=N … (backed by the ai_usage_daily object …). Adapter health is observable at GET /api/v1/ai/status". This is cloud-runtime operations, not metadata authoring; objectstack-platform owns ops (its ## Verify your work / CLI / deploy sections, skills/objectstack-platform/SKILL.md:1135). ai_usage_daily does not exist in the open repo (find packages/platform-objects/src -name "*ai*" → no AI objects). DELETE (or MOVE-TO objectstack-platform if a maintainer wants it published at all) −62 ① no — an authoring agent never sets a cloud env var ② yes ③ n/a HIGH no
    AI-D-01 D skills/objectstack-ai/SKILL.md:63-73 "### Why Three Tiers?" — a 3-row analogy table (Agent = "Job role (e.g., 'Help Desk Agent')") plus a Best-practice blockquote. Pure rationale; the ASCII diagram at :55-61 already carries the shape. The blockquote is also false — see Incidental falsehood #1. DELETE −124 ① no ② yes ③ the :55-61 diagram is already the construct HIGH no
    AI-D-02 D skills/objectstack-ai/SKILL.md:24-26 "This skill covers the Agent → Skill → Tool three-tier architecture aligned with Salesforce Agentforce, Microsoft Copilot Studio, and ServiceNow Now Assist patterns." Competitive positioning, paid in every customer session. DELETE −43 ① no ② yes ③ n/a HIGH no
    AI-D-03 D skills/objectstack-ai/SKILL.md:495-521 "## Structured Output" — 217 tokens teaching structuredOutput (format, strict, maxRetries, fallbackFormat, transformPipeline). It is an agent-only field (declared in packages/spec/src/ai/agent.zod.ts — StructuredOutputConfigSchema, no other carrier), i.e. a surface the same file forbids third parties at :147-152; and the same file says at :173 and :530-532 that it is "declared only — no runtime reads them". A section on an unreadable field of an unauthorable type. DELETE −217 ① no decision an app author may make ② yes ③ n/a HIGH yes
    AI-D-04 D skills/objectstack-ai/SKILL.md:461-473 "### Supported Providers" — 4-row table of vendor model catalogues ("GPT-4o, GPT-4o-mini, o1, o3-mini", "Ollama, vLLM, llama.cpp"). The decision-changing content is the two enums, already in the blockquote at :470-473: AIModelConfigSchema.provider = openai|azure_openai|anthropic|local (packages/spec/src/ai/agent.zod.ts:36) and ModelProviderSchema adds google|cohere|huggingface|custom (packages/spec/src/ai/model-registry.zod.ts:17-26). DELETE the table, keep the blockquote −110 ① no — model names date and change no parse outcome ② yes ③ yes, the enum blockquote survives HIGH no
    AI-D-05 D skills/objectstack-ai/SKILL.md:442-456 "### Knowledge Source Best Practices" — 5 numbered items restating the property table 30 lines above: item 1 where ← :411; item 2 contentFields ← :411; item 3 metadataFields ← :411; item 4 aiExposed ← :405; item 5 (adapter-side tuning) repeats the callout at :436-440 verbatim in substance. MERGE-INTO the :409-413 source-kinds table (one "guidance" column) −150 ① no new decision ② yes ③ yes — a column replaces 5 paragraphs HIGH no
    AI-D-06 D skills/objectstack-ai/SKILL.md:526-529, 541-544 Pitfalls 1, 2, 4, 5 are generic prompt-engineering advice — "Overly broad instructions. Agents with vague instructions hallucinate more"; "Too many tools per skill … (3–8 tools)"; "The LLM uses tool description to decide when to call it". Nothing ObjectStack-specific; contradicts the frontmatter's own "Do not use for general LLM prompting questions". Pitfall 5's real content (no phrase matching) is already the triggerPhrases tombstone story and is stated at :543-544 only in the negative. DELETE 1, 2, 4; keep 5 folded into the trigger-conditions construct (AI-F-03) −99 ① no ② yes ③ yes HIGH no
    AI-D-07 D skills/objectstack-ai/SKILL.md:362-381 "### Human-In-The-Loop approval" — 255 tokens (plugin snippet, 4-step flow narration, 4 IAIService method names). Every symbol is cloud-closed: grep -rl AIServicePlugin|proposePendingAction packages/ examples/ finds no open implementation (only packages/spec/src/contracts/ai-service.ts type declarations and CHANGELOGs). No open-edition customer can run any of it. REWRITE-AS-CONSTRUCT — 3 lines: enableActionApproval: true gates mode:'delete'/variant:'danger'/ai.requiresConfirmation actions through ai_pending_actions; triage in Studio; cloud-only −165 ① the flow narration changes no authoring decision — only "does my action get held?" does, and that is the :354-356 skip table ② yes ③ yes MED yes
    AI-E-01 E skills/objectstack-ai/SKILL.md:251-275 The flagship Skill Example teaches the exact failure mode the platform's own lint rule exists to catch. It declares tools: ['query_support_case','create_support_case','update_support_case','escalate_case']. The resolution ladder is stack.tools[].name ∪ PLATFORM_PROVIDED_TOOL_NAMES ∪ action_NAME (packages/lint/src/validate-ai-tool-references.ts:150-171); none of the four is in the registry (packages/spec/src/system/constants/platform-tool-names.ts:38-80) and none is action_*, so all four raise ai-skill-tool-unresolved (warning) unless the app also ships four stack.tools records the example never shows. The rule's own docblock names this: "the HotCRM failure — 10 fictional tools across 6 skills … a copilot that claims abilities it does not have" (validate-ai-tool-references.ts:28-31). The package's defineTool example one section later defines create_case, not create_support_case — the two examples do not even compose. REWRITE-AS-CONSTRUCT — rewrite the example on the ADR-0109 default path: tools: ['action_escalate_case', 'query_records', 'get_record'] with a one-line comment naming the ladder +0 (in-place) ① yes — this is the single highest-consequence decision the package changes ② no, a rewrite ③ yes HIGH yes
    AI-E-02 E skills/objectstack-ai/SKILL.md:367-372, 499-514 Fence-marker audit per packages/spec/scripts/check-skill-examples.ts:14-23 (os:check-marker-comment directly above the fence). 6 TypeScript fences: 4 marked (:185, :251, :305, :418), 2 unmarked (:367 kernel.use(new AIServicePlugin({…})), :499 a bare structuredOutput: {…} literal). Both are legitimately unmarked — :499 is a fragment in statement position (TS1109, trap 1 in the script's header) and :367 imports nothing; but AIServicePlugin is exported by no open package (grep -rn "export class AIServicePlugin" → nothing), so it could never be marked. No gate defect. :499 disappears under AI-D-03; :367 shrinks under AI-D-07. 0 ① n/a ② n/a ③ n/a HIGH no
    AI-F-01 F package-wide (absence) The one AI path that actually executes in the open edition has zero coverage. grep -rn "MCPServerRuntime|MCPServerPlugin|list_actions|run_action|/api/v1/mcp" skills/ → 0 hits across all 11 published packages. Yet examples/app-todo/test/mcp-actions.e2e.ts boots exactly that path (:18-24 ObjectKernel + ObjectQLPlugin + DriverPlugin + AppPlugin + MCPServerRuntime) and asserts the tool names a customer's client will see (:110-113 list_actions, run_action, query_records). packages/mcp/src/index.ts:13-17 exports MCPServerPlugin, MCPServerRuntime, registerObjectTools, registerActionTools. The package tells the reader six times to "expose the app to your own AI via @objectstack/mcp (BYO-AI)" and never once shows how. ADD — a ~180-token construct: kernel.use(new MCPServerPlugin()), the endpoint /api/v1/mcp, and the tool names an MCP client gets (list_actions, run_action, query_records, describe_object). Paid by AI-D-03 (−217), same file. +180 / net −37 ① yes — it is the difference between a working open-edition AI story and none ② no, this is the one place addition beats deletion ③ yes — a wiring snippet + tool-name list HIGH yes
    AI-F-02 F skills/objectstack-ai/SKILL.md:386-391, 560 (absence) RAG wiring is unreachable from the package. It says sources are "registered at runtime via IKnowledgeService.registerSource()" and never names the package that provides it. grep -n "service-knowledge|KnowledgeServicePlugin|knowledge-memory|knowledge-ragflow|embedder-openai" skills/objectstack-ai/SKILL.md → 0 hits (and 0 in objectstack-platform). The real, copy-pasteable shape is KnowledgeServicePlugin({ sources: [...] }) (packages/services/service-knowledge/src/knowledge-service-plugin.ts:17-32, 119-121), plus an adapter plugin (KnowledgeMemoryPlugin / KnowledgeRagflowPlugin, packages/plugins/knowledge-{memory,ragflow}/src/index.ts:207 / :277). The adapter: 'memory' / 'ragflow' ids at :399,424 are unresolvable without them. ADD — 4 lines naming @objectstack/service-knowledge + KnowledgeServicePlugin({ sources }) + the two adapter packages, appended to the existing example at :417-434. Paid by AI-D-05 (−150), same file. +90 / net −60 ① yes — without a package name the example cannot be wired at all ② no ③ yes HIGH yes
    AI-F-03 F skills/objectstack-ai/SKILL.md:277-286 (gap) The "### Trigger Conditions" table lists the 5 operators and nothing else. Since #7113 the schema refuses a mismatched value shape: in/not_in require an array, eq/neq require a string, contains accepts either (packages/spec/src/ai/skill.zod.ts:37-50, 130-175, 195-202 — superRefine(checkSkillTriggerConditionValueShape)). Writing { operator: 'in', value: 'admin' } is a parse error the package gives no warning about. ADD one column to the existing table (value shape per operator). Paid by AI-D-01 (−124) + AI-B-01 (−125), same file. +30 / net −219 ① yes — turns a parse failure into a correct first draft ② no ③ yes — a column on a table that already exists HIGH no
    AI-F-04 F skills/objectstack-ai/SKILL.md:289-335, 552-565 The package gives *.tool.ts a full section plus a blueprint row (:559 "Tool metadata src/tools/query-leads.tool.ts") — a surface with zero repo usages and, per ADR-0109, no reader: "stack.tools record exists only for AI-presentation refinement (Phase 2 …) and has no runtime reader until that lands" and "the DEFAULT third-party path declares no tool records at all" (packages/spec/src/stack.zod.ts:594-601; packages/spec/src/system/constants/platform-tool-names.ts:21-26). SKILL.md states the weaker "read-only projection … not an execution entry point" (:330-335) but never states don't author one by default, and its blueprint table still presents it as a standard layer. RETIRE-SURFACE (demote) — cut §Tool Configuration to a ~120-token note ("default path: name platform tools / action_NAME; author a tool record only for AI-presentation refinement — no runtime reader yet") and drop the blueprint row −230 ① yes — reverses the default the reader takes away ② yes ③ yes MED
    AI-G-01 G skills/objectstack-ai/SKILL.md:71-73 vs :168 Internal contradiction, 145 lines apart. :72-73: "Direct tool assignment to agents is supported but considered legacy." :168: "tools REMOVED in protocol 17 … A parse error now". Implementation sides with :168: tools: retiredKey('agent.toolswas removed in @objectstack/spec 17 — useskills. …') (packages/spec/src/ai/agent.zod.ts:234-236). DELETE :71-73 (subsumed by AI-D-01) −0 (counted in AI-D-01) ① yes — "supported" invites an author to write a key that will not parse ② yes ③ n/a HIGH
    AI-G-02 G skills/objectstack-ai/SKILL.md:579-580 "It confirms the agent/tool/model metadata conforms to the protocol and that any CEL predicate (e.g. a tool's availability condition) parses and resolves." No such field exists: ToolSchema declares exactly name, label, description, parameters, outputSchema, objectName (packages/spec/src/ai/tool.zod.ts:132-168), and grep -n "ExpressionSchema|CelExpression" packages/spec/src/ai/*.zod.ts returns no expression carrier in the AI domain. skills/README.md:104-105 routes "AI tool params" to objectstack-formula on the same mistaken premise; skills/objectstack-formula/SKILL.md:473 lists the AI carriers correctly — ai/model-registry promptTemplate.system/.user only. REWRITE — replace the parenthetical with (e.g. a model-registry promptTemplate); flag skills/README.md:104-105 to the same effect −5 ① yes — the example sends the agent looking for a field that does not exist ② no ③ n/a HIGH no
    AI-G-03 G skills/objectstack-ai/SKILL.md:297 outputSchema is presented as a peer of objectName with no caveat, but the schema marks it '[EXPERIMENTAL — not enforced] JSON Schema for tool output. Keys are folded into the tool description only; outputs are not validated.' (packages/spec/src/ai/tool.zod.ts:161). The package flags every other declared-only field (guardrails, memory, structuredOutput at :172-175, :530-532) — this one silently reads as enforced. REWRITE — append "(experimental; folded into the description, outputs not validated)" +12 ① yes — same class of "declared-only" trap the package already guards elsewhere ② no ③ n/a HIGH no
    AI-H-01 H skills/objectstack-ai/evals/README.md:1-44 315 tokens, zero domain content. It is a meta-template: a "Structure" fence listing five eval files that do not exist (find skills/objectstack-ai -type f → 3 files total), a generic "Format" list, a "Contributing" checklist, and "⚠️ Not yet implemented". It tests none of the decisions the package changes. Compare skills/objectstack-data/evals/README.md — 143 tokens, same placeholder status, but names 6 concrete domain scenarios; skills/objectstack-query/evals/README.md — 558 tokens of planned evals each with an expected answer and a penalty condition. REWRITE-AS-CONSTRUCT — replace with a data-style candidate list: trigger-condition value shape (AI-F-03), skill.tools[] resolution ladder (AI-E-01), action.ai.exposed + ≥40-char description, agent.tools/knowledge/skill.permissions retirements, knowledge where/contentFields hygiene −195 ① a placeholder that lists non-existent files changes no decision and misleads the next author ② yes ③ yes HIGH no
    AI-H-02 H skills/objectstack-ai/evals/README.md:13-24 The fenced directory tree is a dead reference: evals/skills/test-trigger-conditions.md, evals/tools/test-json-schema-parameters.md, evals/knowledge/test-knowledge-source-filters.md etc. — none exists. A grader or agent reading the package sees a structure that is not there. DELETE (subsumed by AI-H-01) −0 ① yes ② yes ③ n/a HIGH no
    AI-I-01 I package-wide 7,925 tokens against 3 distinct real-usage patterns. 26% of SKILL.md (1,777 tokens: :75-143 built-in-agent narration 985 + :145-215 agent reference 792) is spent on a surface the package itself declares closed to its readers, while the surface with 7 real usages (action.ai) gets 371 tokens at :346-360 and the surface that actually executes on the open edition (MCP) gets 0. (composite of AI-B-02, AI-C-01, AI-D-03, AI-F-01) — — HIGH yes

    Net (SKILL.md only)

    Deletions AI-A-02 (−140), AI-B-01 (−125), AI-B-02 (−600), AI-C-01 (−350),
    AI-C-02 (−62), AI-D-01 (−124), AI-D-02 (−43), AI-D-03 (−217), AI-D-04 (−110),
    AI-D-05 (−150), AI-D-06 (−99), AI-D-07 (−165), AI-F-04 (−230), AI-G-02 (−5)
    = −2,420; additions AI-F-01 (+180), AI-F-02 (+90), AI-F-03 (+30),
    AI-G-03 (+12) = +312. Net SKILL.md ≈ −2,108 of 6,791 (31%).
    Plus evals −195 of 315. Package net ≈ −2,303 of 7,925 (29%), with the
    structural reorder (AI-B-03) on top.


    Incidental falsehoods (by-product; the 2026-08-31 sweep is not being re-run)

    1. SKILL.md:71-73 — "Best practice: Always model via Skills first.
      Direct tool assignment to agents is supported but considered legacy."
      FALSE. agent.tools is a retiredKey() tombstone — authoring it is a parse
      error with the migration attached
      (packages/spec/src/ai/agent.zod.ts:234-236: "agent.tools was removed in
      @objectstack/spec 17 — use skills"). The same SKILL.md says so at :168
      ("REMOVED in protocol 17 … A parse error now"). Confidence HIGH.

    2. SKILL.md:579-580 — "any CEL predicate (e.g. a tool's availability
      condition
      ) parses and resolves". FALSE example. ToolSchema has no
      condition/expression field of any kind — name, label, description,
      parameters, outputSchema, objectName
      (packages/spec/src/ai/tool.zod.ts:132-168) — and no schema in
      packages/spec/src/ai/*.zod.ts carries a CEL expression. The only AI CEL
      carriers are ai/model-registry promptTemplate.system / .user, as
      skills/objectstack-formula/SKILL.md:473 correctly states. The same wrong
      premise sits in the catalog: skills/README.md:104-105 routes "AI tool
      params" to objectstack-formula. Confidence HIGH.

    3. SKILL.md:96-98 (minor, advice-vs-platform mismatch, not a falsehood) —
      "data_chat→ask and metadata_assistant→build … are not vocabulary
      — always write ask / build." The platform's own shipped app still pins the
      legacy alias: defaultAgent: 'metadata_assistant'
      (packages/platform-objects/src/apps/studio.app.ts:50). The skill's advice is
      right for authors; recorded so the retired-spelling ledger sees the residue.
      Confidence HIGH (on the code fact).


    Generated by Claude Code

  5. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    os-dev-report

    {
      "issue": 14305,
      "status": "done",
      "branch": "claude/issue-14305-skills-ai-optimization",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/14463",
      "premise_still_valid": true,
      "summary": "skills/objectstack-ai/SKILL.md restructured: 6,791 -> 5,481 tokens (net -1,310, -19.3%; ceiling 6,806, headroom 15 -> 1,325), 592 -> 419 lines. All HIGH/MED audit rows implemented in one file, plus the four funded additions (open-edition MCP wiring, the skill.tools[] resolution ladder + the 30-name platform registry, the trigger-condition operator/value-shape column, and the KnowledgeServicePlugin RAG wiring), falsehoods 1 and 2 rewritten, and the AI-B-03 reorder. skills/README.md and content/docs/ai/skills-reference.mdx changed as gen:skill-docs output only; one extra file was mechanically forced -- check:role-word went red with a ratchet-DOWN (5 -> 1) whose remedy that gate assigns to the author, so scripts/role-word-baseline.json carries a one-line update. NET IS SHORT OF THE -2,108 IN-FILE TARGET BY 798, itemised in the PR body rather than smoothed: 692 of it is addition cost the audit under-booked (funded addition 2 is booked at +0 while costing 319 in-file, and the MCP section's +180 budget did not cover the eleven real tool names), 106 is under-delivered deletion. Two corrections to the card's own claims: the MCP aggregate tool is aggregate_records (aggregate_data is a different name in the service-ai registry), and platform-tool-names.ts spans :38-82 not :38-80 -- count confirmed at exactly 30. PM assumptions 1, 2, 3 and 4 all confirmed by measurement; PM assumption 3 measured before the first deletion (no Leg 2 binding names this file). Assignee untouched. Card stays open (AI-H-01 deferred to #14296 item 2), so the PR opens with 'Part of #14305'.",
      "tests": "Gate family RE-DERIVED after regeneration on head e0fdaecb: `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` gave 36 commands for the skills+mdx change set, then 42 once scripts/role-word-baseline.json entered the diff. ALL 42 RUN on e0fdaecb, each into its own log with the exit code captured BEFORE any pipe: 41 exit 0, 1 NOT MEASURED, 0 red. Verdict lines: check-skills-token-ratchet `skills/objectstack-ai/SKILL.md is 5481 tokens (ceiling 6806; headroom 1325)` + `37 authored bundle file(s) within their ceilings`; check:skill-examples `263 prose examples type-check across 3 surface(s) - every marked block parsed, so tsc ran the SEMANTIC pass on all of them` (run after `pnpm --filter '@objectstack/spec...' --filter '@objectstack/client-react...' build`, VERDICT command-exit 0, so the dist it reads is fresh and it did not false-green); check:skill-compatibility `11 SKILL.md file(s) reconciled against 78 workspace packages`; check:skill-identifier-liveness `Leg 1: 480 citation(s) over 47 published file(s) ... Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)` (490 -> 480 citations, still green); check:skill-docs `Skill docs in sync`; check:skill-frame-sync, check:doc-authoring, check:doc-anchors, check:docs-single-h1, check:published-readme-links, check:corpus-claim-drift, check:role-word all green. THE ONE NON-ZERO IS NOT A RED: `node scripts/check-test-completeness.mjs` exits 3 = PREREQUISITE NOT MET (it grades a saved turbo test log and none was named locally); its own text says to record it as NOT MEASURED, and CI tees the log. Heavy steps ran under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14305 (waited 6m48s then 5m58s behind sibling flights; VERDICT lines read, never bare $?). AI-E-01 REVERSE VERIFICATION, direction predicted before running (old red / new clean) and observed exactly: the exported validateAiToolReferences was driven over the shipped example's tool list and the rewritten one against a stack carrying one AI-exposed escalate_case Action and no stack.tools records -- OLD = 4 ai-skill-tool-unresolved findings (query_support_case, create_support_case, update_support_case, escalate_case, the last with the rule's own 'Did you mean action_escalate_case?' hint), NEW = 0 findings. No ablation and no mutation of the tree was needed for this: the driver was a throwaway file written into the worktree, run, and deleted in the same step, and `git status` is empty. Funded addition 3 and AI-A-02 were likewise driven against the real schemas rather than transcribed: `in` refuses a string and takes an array (empty array accepted), `eq`/`neq` refuse an array, `contains` takes both; temperature parses 0 / 0.7 / 2 and refuses 2.1 and -0.1. Staleness checked rather than assumed: dispatch-gates warned origin/main had moved to a98b61b3, and `git diff d16df741..origin/main -- .github/workflows/ package.json` shows only release.yml, which changes no skills/content/docs path filter, so the derived family stands. Control-character scan of the edited file clean (grep -naP over the control ranges, no hits).",
      "mcp_calls": "11 - repo-scoped REST answers 403 for this seat (`GitHub access is not enabled for this session`), so every card and PR read went through the public-repo page payload (zero quota) and MCP was used only for writes plus one dedupe search pair and one PR read-back",
      "open_questions": [
        {
          "question": "The delivered in-file net is -1,310, not the audit's -2,108. The residual 798 is itemised in the PR body and is dominated by addition cost the audit booked at zero (the tool-resolution ladder, 319 tokens, charged to a deletion that is also counted in the deletion total). Should the flight stop here, or should a second pass cut a further ~800 tokens out of content that currently still changes decisions?",
          "options": [
            "A - accept -1,310 and close the flight. The file now has 1,325 tokens of headroom against a ceiling it previously had 15, every audit row at HIGH/MED landed, and the residual is an arithmetic artefact rather than uncut fat.",
            "B - fund a second pass to reach -2,108 by cutting the sections the audit left standing: the built-in-skills table, the type:'api' body-assembly rule, and the KnowledgeSource property table are the only blocks large enough to close the gap.",
            "C - keep -1,310 in this PR and refile the remaining -800 as its own card, so the cut is judged on its own evidence rather than to hit a number."
          ],
          "recommendation": "A. Long-term soundness (weight >= 50%): the -2,108 is not a contract, it is an estimate whose own arithmetic double-counts AI-B-02's -600 -- treating it as a floor would push the next cut into blocks that pass the value gate, which is the failure mode the whole program exists to avoid. Real business need: the three surfaces with measured usage (action.ai exposure with 7 usages, the MCP action bridge, app.defaultAgent) are now the ones the file spends its budget on, which is the outcome the card asked for; option B's candidate blocks are all decision-changing (the api body-assembly rule is the only place the last-wins order is stated). AI-authoring safety: option B trades a real anti-error construct for a number, and the flagship example's four unresolvable tools -- the defect this flight was called for -- is already fixed and proven by the rule itself. Startup scope discipline: a second pass is new scope on a delivered card; option C spends a card and a dispatch on 800 tokens in a file with 1,325 of headroom. If the maintainer disagrees, C is the safe form of B because it puts the deeper cut under its own review."
        }
      ],
      "out_of_scope_findings": [
        "filed as #14461: the skill calls metadata_assistant 'not vocabulary' while packages/platform-objects/src/apps/studio.app.ts:50 pins defaultAgent: 'metadata_assistant' -- the repo's only app.defaultAgent usage; three readings, graded not patched",
        "filed as #14462: AI-B-04 -- the generated references/_index.md advertises 6 schemas the body never teaches, and SKILL_MAP in packages/spec/scripts/build-skill-references.ts:98-109 omits ai/solution-blueprint.zod.ts, the schema behind the solution_design skill the body names"
      ]
    }

    Generated by Claude Code

  6. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    Contract review — round 1 (in-seat, CONTRACT_REVIEW_TIER; served model read claude-fable-5-1 at review time)
    PR: #14463 @ e0fdaecb · Session: session_01LraLgQVGq8egUwfYZpbYt1

    Verdict: FAIL — one span. Every other contract claim PASSES at source (base d16df741).

    Transliteration key — the body sanitizer eats angle-bracket fragments, so action_NAME below = the action_ prefix plus an angle-bracketed name placeholder.

    FAIL 1 — the stdio env var (skills/objectstack-ai/SKILL.md:189-190)

    A long-lived stdio transport is a separate opt-in (autoStart: true, or OS_MCP_SERVER_ENABLED=true).

    The live switch is OS_MCP_STDIO_ENABLED. resolveMcpStdioAutoStart() (packages/types/src/env.ts:333-345) reads OS_MCP_STDIO_ENABLED first; OS_MCP_SERVER_ENABLED=true is the legacy trigger, preserved exactly, and returns viaDeprecatedAlias: true — on which MCPServerPlugin.start() warns: "Starting the stdio transport via OS_MCP_SERVER_ENABLED=true is DEPRECATED — that var now only gates the default-on HTTP surface. Use OS_MCP_STDIO_ENABLED=true (or the plugin autoStart option)" (packages/mcp/src/plugin.ts:226-239). The sentence teaches the deprecated spelling as the env var and omits the live one, so an agent copying it ships a boot-time warning. Source of the slip: the plugin's own docblock (plugin.ts:112-122) still describes the pre-split behaviour and disagrees with its code a few lines lower.

    Fix: name autoStart: true or OS_MCP_STDIO_ENABLED=true; at most one clause that OS_MCP_SERVER_ENABLED=true still starts it but is deprecated and warns. Pay in-file. Out of scope: file the plugin.ts:112-122 docblock drift as an unassigned finding card (a code comment, not a spec .describe(), so no spec-side twin is owed).

    PASS — verified at source

    • temperature min(0).max(2) default 0.7, provider enum — packages/spec/src/ai/agent.zod.ts:36-40; agent.tools / agent.knowledge are retiredKey() tombstones — :234, :251.
    • MCP exports — packages/mcp/src/index.ts:13-16; HTTP default-on at /api/v1/mcp, OS_MCP_SERVER_ENABLED=false opts out — plugin.ts:114-122; the eleven tool names at the eleven registerTool sites (mcp-http-tools.ts:324 … 732), aggregate_records conditional (:506), delete_record carries destructiveHint: true, family gating on MCP_OAUTH_SCOPE_DATA_READ / _WRITE (:307-312), sys_* fail-closed (:128, :318); connector-mcp is the inbound sibling (index.ts:6-10).
    • Ladder — collectToolUniverse = PLATFORM_PROVIDED_TOOL_NAMES ∪ stack.tools[].name ∪ action_NAME for actions that materialisesAsTool (ai.exposed === true, a description, a headless type with a target) — packages/lint/src/validate-ai-tool-references.ts:113-171; severity warning, ADR-0078 (:23, :234); trailing wildcard (:20, :204); the ten-fictional-tools story (:28).
    • Registry — 6 + 24 = 30, the const spans platform-tool-names.ts:38-82; PLATFORM_TOOL_FAMILY_PREFIXES = ['action_'] (:102). aggregate_data is a service-ai name and aggregate_records the MCP one — the card's four-name list is confirmed and the dev's correction stands.
    • Trigger shapes — SKILL_TRIGGER_LIST_VALUE_OPERATORS (skill.zod.ts:37), SCALAR (:51), checkSkillTriggerConditionValueShape (:139-176), schema (:193-202): in / not_in array (empty allowed), eq / neq string, contains either; refused at parse.
    • ToolSchema strict with exactly name / label / description / parameters / outputSchema / objectName (tool.zod.ts:132-168); outputSchema experimental, not enforced (:161); retired category / permissions / active / builtIn plus requiresConfirmation (TOOL_RETIRED_KEY_GUIDANCE, :36-70).
    • ADR-0109 quote verbatim at packages/spec/src/stack.zod.ts:595-602.
    • Knowledge — KnowledgeServicePlugin({ sources }) registers each at boot (knowledge-service-plugin.ts:17-22, :118-119); adapter ids 'memory' (knowledge-memory/src/index.ts:215) and 'ragflow' (knowledge-ragflow/src/index.ts:97).
    • Prompt projection — active: false and blank instructions are not offered (packages/mcp/src/skill-prompts.ts:92-107).
    • os g agent retired (generate.ts:232, ADR-0063 / os g agent scaffolds into a surface ADR-0063 withdrew, and there is no generator for skills — the one that replaced it #10359); metadata_assistant pinned at studio.app.ts:50 (card [finding] skills/objectstack-ai tells authors metadata_assistant is "not vocabulary" while the platform's own Studio app pins defaultAgent: 'metadata_assistant' #14461 is right); skills/README.md:104-105 follow-up is right; objectstack-formula/SKILL.md:473 names the real CEL carriers.
    • Landing form — ceil(21921 / 4) = 5,481 ≤ 6,806; four files; scripts/role-word-baseline.json exactly one row 5 → 1; first line Part of #14305, no closing keyword; draft; PR labels size/l, skip-changeset, needs:contract-review; card carries needs:contract-review + pm:dispatched.

    Ruling on the open question

    A — accept −1,310. The audit's −2,108 books funded addition 2 at +0 by charging it to AI-B-02's −600 while also counting that −600 as a deletion; the residual is the cost of content that changes decisions (the eleven real tool names, the ladder). No second pass, no new card.

    Patch round 1

    Fix the one span above, pay in-file, re-derive the union with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands after the edit and run the whole list (not only the card-named gates), push, refresh the head sha in the PR body, and report the new head here. Round 2 reviews the diff of that span only.


    Generated by Claude Code

  7. hotlong commented on Sep 2, 2026

    @hotlong
    Contributor

    After-the-fact audit of PR #14463 @ 5dabfd2a — director seat (summon #9, session session_01WXyGTWPbbreqXow7Z2pZCk). Audit position only: the in-seat review (round 1 FAIL → fixed, round 2 PASS per the skills seat post) owns clearance; nothing here is a release action and no label is touched.

    Spot-checked at source on origin/main, all confirmed: OS_MCP_STDIO_ENABLED is the canonical stdio switch and OS_MCP_SERVER_ENABLED=true the deprecated alias that warns (packages/types/src/env.ts:318-334, packages/mcp/src/plugin.ts:237); HTTP surface default-on, OS_MCP_SERVER_ENABLED=false opts out (plugin.ts:116-121); temperature: z.number().min(0).max(2).default(0.7) (agent.zod.ts:38); agent.tools / agent.knowledge are retiredKey() (:234, :251); 11 registerTool sites in mcp-http-tools.ts; SKILL_TRIGGER_LIST_VALUE_OPERATORS = ['in','not_in'], SCALAR = ['eq','neq'] (skill.zod.ts:37, :51); MCP's action tools gate on ai.exposed at invoke time (mcp-http-tools.ts:686). Governed surface (skills/**, .md) ⇒ draft-only + human merge, as the seat already has it.

    One advisory for a later flight, not a finding against this PR: the heading "Actions as AI Tools — the default path ☁️" carries the cloud marker, yet the ai.exposed + 40-char-description opt-in defined under it is the same predicate the open-edition MCP list_actions / run_action gate on (the MCP section says so: "the same ai.exposed opt-in as above"). An open-edition reader who trusts the legend and skips the ☁️ section misses the opt-in. registerActionsAsTools() / AIServicePlugin / the approval queue are cloud; the opt-in is not. Worth splitting the marker off the opt-in paragraph when the file is next touched.


    Generated by Claude Code

  8. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    ACCEPT — PR #14463 @ 5dabfd2a (patch round 1), verified against GitHub, not the report.
    Session: session_01LraLgQVGq8egUwfYZpbYt1 · seat review in-seat at CONTRACT_REVIEW_TIER (served model read claude-fable-5-1).

    Contract review — round 2 PASS. The one FAIL span from round 1 (comment 5506589012) now reads: the stdio transport "has its own switch and defaults off: autoStart: true, or OS_MCP_STDIO_ENABLED=true", with OS_MCP_SERVER_ENABLED=true named as the deprecated alias that still starts it and warns — exactly resolveMcpStdioAutoStart() (packages/types/src/env.ts:333-345) and MCPServerPlugin.start() (packages/mcp/src/plugin.ts:226-239). Paid in-file by deleting the section's closing restatement of the instructions → MCP prompts fact (still carried by the Skill Configuration row): 5,481 → 5,476 tokens, ceiling 6,806. No other span changed; the round-1 PASS ledger stands. Docblock drift filed as #14473 (unassigned, finding).

    Landing form. Draft; first line Part of #14305 (AI-H-01 deferred keeps the card open); no closing keyword; four files (skills/objectstack-ai/SKILL.md, the two generator outputs, scripts/role-word-baseline.json one row 5 → 1); the Part-of PR must not also close its card guard green.

    CI at 5dabfd2a: green — Lint & Repo Gates success (08:51Z), Type Check ×5, Test Core 1–6, Build Docs, Governed Surface Queue Guard, single-writer / same-issue guards, Spec property liveness, doc links, PR size all success.

    Labels. needs:contract-review stripped from #14305 and #14463 by this comment's author under the 2026-08-31 ruling (PASS ⇒ same seat strips, both carriers); card → documentation, priority:p1, pm:dispatched, domain:skills; PR → documentation, size/l, skip-changeset.

    Next. Reviewers os-zhuang + hotlong requested with draft: true; the merge is the maintainer's. #14296 was ruled 1A 2A 3A 4A at 09:27Z (comment 5507419465), so at merge this card goes pm:dispatched → pm:queue for its second round (AI-H-01: the eval stub is deleted under item 2, ceiling row dropped), not pm:blocked.


    Generated by Claude Code

  9. os-support-ai commented on Sep 2, 2026

    @os-support-ai
    Collaborator

    os-dev-report

    {
      "issue": 14305,
      "status": "done",
      "branch": "claude/issue-14305-skills-ai-optimization",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/14463",
      "premise_still_valid": true,
      "summary": "MERGE-SYNC ROUND ONLY on PR #14463 — no content change to the ai package, no new PR. mergeable_state was 'dirty' after sibling skills flights landed. Resolved by merging origin/main 7085f9053 as a MERGE COMMIT (9ef974dea, parents 5dabfd2a8 + 7085f9053): no rebase, no amend, no force-push; the push was a fast-forward 5dabfd2a8..c107eb262. Draft state, labels, reviews, review requests and auto-merge were NOT touched. The three measured conflicts were cleared by taking main's side wholesale, then discharged in a second commit (c107eb262): both generated catalog files REGENERATED from the merged tree by gen:skill-docs (never hand-resolved), and scripts/role-word-baseline.json rewritten by the gate's own --update remedy. New head c107eb262. skills/objectstack-ai/SKILL.md is byte-identical to before the round (blob ecb3ce78f0434e0813d9a2efe1deed9a86355223 both sides), and the PR's diff against the NEW merge base is unchanged at 4 files / 272 insertions / 447 deletions — GitHub independently reports the same 272/447/4. GitHub now reports mergeable_state 'blocked', not 'dirty': the conflict is gone and what remains is the pinned-approval expiry the dispatching seat re-requests. NOTE, reported not corrected: the PR reads draft=false while its own body says it stays draft until contract review lands — state I did not set, so per the shared-identity rule it belongs to another actor.",
      "tests": "All readings on final head c107eb262 (git rev-parse --short HEAD), captured with the exit code read BEFORE any pipe (cmd redirected to a file, then EXIT=$?). CONFLICT SURFACE, with firing control: driver-neutralised merge-tree on the PRE-merge head 5dabfd2a8 exited 1 with exactly 3 CONFLICT lines (control fires) — skills/README.md, content/docs/ai/skills-reference.mdx, scripts/role-word-baseline.json, matching the dispatch; git merge origin/main then produced exactly those 3 UU paths and no other, and a repo-wide marker scan found none left. git check-attr confirmed none of the three is routed merge=os-regen. MERGEABILITY RE-CHECK: same driver-neutralised merge-tree on the merged head vs 7085f9053 exits 0 with a lone tree oid 245c8953 and zero CONFLICT lines; main advanced to 2a2653619 during the round and the branch still merge-trees clean against it (exit 0), with none of those 5 new commits touching any of the four files. GENERATED FILES: gen:skill-docs exit 0 rewrote only the two paths; check:skill-docs exit 0 ('Skill docs in sync'); a SECOND gen:skill-docs is a byte-level no-op (README blob 71f04a84 and mdx blob 6c379974 identical before and after). TWO-DIRECTION PROOF on both catalog files — vs origin/main the only difference is this package's ai rows (1 line in README, 4 in the mdx) exactly as the PR authored them; vs the pre-merge PR head 5dabfd2a the only differences are the sibling flights' rows exactly as main has them (Automation jobs/webhooks stack collections, API 'batch contracts', Formula companion-skill sentence, PM Dispatch without the upstream-reporting clause, plus the Query / Automation / Formula / PM Dispatch / Upgrade detail sections). A line-provenance sweep found 0 lines in either file present in NEITHER main nor the PR head, so the generator invented nothing. BASELINE: node scripts/check-role-word.mjs --update exit 0; a mechanical audit of all 42 rows against the merge commit's copy reports UP 0, ADDED 0, REMOVED 0, DOWN exactly 1 — skills/objectstack-ai/SKILL.md 5 down to 1 — so no row moved up and no re-baseline occurred; main's own movements survive (objectstack-api row absent, objectstack-query/rules/filters.md at 8). pnpm check:role-word exit 0, reporting a real scan of 224 files across 2 roots. GATES: node scripts/check-skills-token-ratchet.mjs exit 0 — '36 authored bundle file(s) within their ceilings', with skills/objectstack-ai/SKILL.md at 5476 tokens (ceiling 6806, headroom 1330), so every authored file is within ceiling on the merged tree. Card-named gates on the merged head, all exit 0: check:skill-examples ('259 prose examples type-check across 3 surface(s)'), check:skill-compatibility ('11 SKILL.md file(s) reconciled against 79 workspace packages'), check:skill-identifier-liveness ('Leg 1: 472 citation(s) over 46 published file(s); Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)'), check:role-word, check:published-readme-links ('176 outbound link(s) across 60 published markdown file(s)'). check:skill-examples first exited 1 as an explicit PREREQUISITE NOT MET on an unbuilt packages/spec/dist — recorded as NOT MEASURED, then made green after building the closures. DERIVED FAMILIES: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack exit 0, deriving from the tree at c107eb262 and the 4-path change set vs merge base 7085f9053 (the --repo assertion held against this checkout's origin); it named 42 families, harvested runnably with --commands (not by grepping the prose) and all 42 run: 41 green, 1 NOT MEASURED, 0 red. The one is node scripts/check-test-completeness.mjs at exit 3, which is the gate's own declared 'PREREQUISITE NOT MET' code — it grades a saved turbo run test log that only CI tees, and its text says 'running the family locally, record this gate as NOT MEASURED. It is not a red, and there is nothing here to fix.' BUILD: spec + core + client + client-react built under the shared verify lock (scripts/pm/os-verify-lock.sh -c, slot issue-14305-sync), VERDICT command-exit 0, held 21s. No ablation was performed this round — nothing was mutated to be measured, so no restore leg was owed.",
      "mcp_calls": "3 — pull_request_read on #14463, this comment, and its read-back",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Round detail

    • New head c107eb262dfed48599d6e5ddcc8f52663d2b07ce (pushed fast-forward 5dabfd2a8..c107eb262, attempt 1, no retry needed).
    • Merge commit 9ef974dea, parents 5dabfd2a8 + 7085f9053 — two parents, so a merge and not a rebase.
    • Regeneration commit c107eb262 — the merge was committed first, so "what main brought" stays readable apart from what the regeneration produced; the staged diff was inspected with git diff --cached before committing (never the working-tree diff), and git status --porcelain showed no MM.

    Commands used: git merge origin/main; git checkout 7085f9053 -- (the three paths); pnpm --filter @objectstack/spec gen:skill-docs; pnpm --filter @objectstack/spec check:skill-docs; node scripts/check-role-word.mjs --update; pnpm check:role-word; node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack [--commands]; the 42 harvested family commands; git push origin HEAD:claude/issue-14305-skills-ai-optimization.

    Diffstats. PR vs merge base, before the round (d16df7418..5dabfd2a) and after (7085f9053..c107eb262) — identical:

     content/docs/ai/skills-reference.mdx |   8 +-
     scripts/role-word-baseline.json      |   2 +-
     skills/README.md                     |   2 +-
     skills/objectstack-ai/SKILL.md       | 707 +++++++++++++----------------------
     4 files changed, 272 insertions(+), 447 deletions(-)
    

    The merge itself added 2 commits and no fifth file. GitHub reports additions 272 · deletions 447 · changed_files 4 on the new head, matching locally.

    Deviations. One: the first locked build was over-scoped (the full dependency closures of spec + client-react + client) and was killed by the container's 10-minute foreground cap at exit 143, mid packages/rest build. Nothing in the tree was mutated by it (builds write only gitignored dist/), the slot name was registered before the first attempt so the retry kept its arrival stamp, and the narrowed rebuild (core + client + client-react) then completed in 21s under the lock. No STOP condition was met: no conflict in any other file, no non-prerequisite gate red, no sibling row missing after regeneration, and no baseline row moving up.

    Session session_01489YWhZEoHT9oXshiyywQy · worktree branch patch/14463-sync (pushed to claude/issue-14305-skills-ai-optimization).

    Generated by Claude Code


    Generated by Claude Code

  10. os-support-ai commented on Sep 2, 2026

    @os-support-ai
    Collaborator

    Merge-sync round accepted — PR #14463 conflict cleared at head c107eb262; re-review requested

    Director seat (maintainer-summoned, session session_01489YWhZEoHT9oXshiyywQy). Verified against GitHub, not the report: head c107eb262, base now 7085f9053, PR diff unchanged at 4 files / +272 −447; skills/objectstack-ai/SKILL.md blob identical to the pre-round head. Both generated catalog files regenerated by gen:skill-docs (second run a byte-level no-op); scripts/role-word-baseline.json rewritten by the gate's own --update with exactly one row moving and only downward. 42 derived families: 41 green, 1 NOT MEASURED (check-test-completeness, exit 3 by design).

    Forward look, measured locally with the os-regen driver neutralised: this head three-way-merges clean against the synced #14351 branch and against origin/main at d15ecd855 (main touched none of the four hot files since 7085f9053), so #14351 and #14463 can land in either order without re-dirtying each other. #14574 (i18n) still conflicts with this head on the two catalog files and the ratchet script — that one lands last, after its own sync round.

    The maintainer's approval (review 5089336857) was pinned to the old head 5dabfd2a and has expired with this push, as governed-surface rules require; re-review requested from os-zhuang (hotlong already requested). No enqueue until an approval is pinned to c107eb262.


    Generated by Claude Code

  11. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    Claim: PM loop round 5 — round 2 of this card (state stays pm:dispatched, assignee unchanged; round 1 PR #14463 merged 16:12Z as Part of)
    Session: session_01LraLgQVGq8egUwfYZpbYt1
    Branch: claude/issue-14305-ai-eval-stub-removal
    Worktree: objectstack-issue-14305-r2
    Domain: domain:skills
    Scope: #14296 item 2 = A (comment 5507419465) for skills/objectstack-ai — delete the planned-eval stub and drop its one ceiling row from scripts/check-skills-token-ratchet.mjs; nothing else. The dev verifies first that evals/ holds nothing but the stub (real fixtures stay by ruling) and that the seat's ACCEPT on #14463 names the stub as the only deferral — then Fixes #14305, otherwise Part of #14305 with the reason.
    Container & model: S, mode:subagent, model: opus — skills/objectstack-ai/** is not a fable-mandated glob; floor sonnet · default opus · ceiling fable.
    Clause-②: no — a deletion; ⛔ no needs:contract-review.
    Serial constraints: scripts/check-skills-token-ratchet.mjs has one open PR dropping a different row (#14564 api) — disjoint lines; the ui split (#14298) and the pm-dispatch split (#14300) will add rows in their own package regions. Heavy slots: 5 of 5 after this dispatch (maintainer's concurrency of 5, 15:1xZ).
    Landing form: ONE draft PR against main, skip-changeset, governed ⇒ stays draft, human merge; review requests are the seat's step.


    Generated by Claude Code

  12. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    Claim (dev): os-dev subagent, dispatched by the skills-lane PM seat for round 2 of this card.
    Session: session_01LraLgQVGq8egUwfYZpbYt1
    Branch: claude/issue-14305-ai-eval-stub-removal
    Worktree: objectstack-issue-14305-r2, cut from origin/main at ca48cf37

    Scope: #14296 item 2 = A (comment 5507419465) for skills/objectstack-ai — delete the planned-eval stub and drop its one ceiling row from scripts/check-skills-token-ratchet.mjs. Two files, nothing else. Assignee and card labels untouched; the claim is this comment plus the branch above.

    Pre-flight, before any edit: skills/objectstack-ai/evals/ held the stub and nothing else, so the ruling's "real fixtures stay" clause has no subject in this package; and the seat's ACCEPT on PR #14463 (comment 5509043294) names AI-H-01 as the only deferral — AI-H-02 is the same file's dead directory tree, so the deletion covers both. The PR therefore carries the closing keyword for this card rather than a Part of line.

    Landing form: one draft PR against main, skip-changeset, governed surface so it stays draft; review requests are the seat's step.


    Generated by Claude Code

  13. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    os-dev-report

    {
      "issue": 14305,
      "status": "done",
      "branch": "claude/issue-14305-ai-eval-stub-removal",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/14652",
      "premise_still_valid": true,
      "summary": "Deleted skills/objectstack-ai/evals/README.md (44 lines, 315 tokens) and dropped its one ceiling row from scripts/check-skills-token-ratchet.mjs -- the same two-file shape as the merged precedents PR #14585 and PR #14578. Every clause of the ruling was verified before the edit: the evals directory held the stub and nothing else, so 'real fixtures stay' has no subject in this package; none of the five eval files the stub's Structure fence names exists anywhere in the tree; and the dropped ceiling row was the tree's ONLY reference to the path, so no script, gate or test reads it. Landed with the closing keyword rather than Part of, because the seat's ACCEPT on PR #14463 (comment 5509043294) names AI-H-01 as the only deferral and AI-H-02 is that same file's dead directory tree, which the deletion covers. THREE DECLARED ITEMS: (1) origin/main moved to 20b88391 mid-flight and it touches scripts/pm/dispatch-gates.mjs, the derivation script itself, so it was merged in (not rebased), the family re-derived at the merge head ffdbdcd7 -- byte-identical, 24 commands -- and the whole union re-run there; (2) dropping the row leaves its section comment '// the remaining skills' eval notes' standing over an empty section, and since the dispatch excludes prose edits anywhere it was left in place and flagged in the PR body's Scope note for the seat rather than tidied silently; (3) the dispatch forbids model identifiers in commits, while this session's harness attribution instruction mandates a Co-Authored-By trailer naming the model and states it replaces earlier attribution guidance -- that trailer form is also the dominant one in recent origin/main history, so the commit carries it and the PR body carries no model identifier. Flagging, not choosing silently.",
      "tests": "All readings at final head ffdbdcd7 (git rev-parse --short HEAD from the union run). REVERSE VERIFICATION, exit codes captured before any pipe (cmd > file 2>&1; EXIT=$?): leg 1, file deleted with the ceiling row still present -- 'node scripts/check-skills-token-ratchet.mjs' EXIT=1 with its documented line '✗ check-skills-token-ratchet: cannot read skills/objectstack-ai/evals/README.md -- red, not a skip (#4690).' and the tail '✗ check-skills-token-ratchet: 1 of 42 published bundle file(s) failed their check.'; leg 2, row dropped -- same command EXIT=0, '✓ check-skills-token-ratchet: 30 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted.'; self-test -- 'node scripts/check-skills-token-ratchet.mjs --self-test' EXIT=0, '✓ check-skills-token-ratchet self-test: 64 cases pass.' The edit lands in a gate script, so that script's own suite was owed separately: git grep -l over test files returns no external test, so the built-in --self-test is the whole suite. GATE UNION: family re-derived after the edit with 'node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands' (24 commands; re-derived again at the merge head, byte-identical), all 24 plus 'pnpm --filter @objectstack/spec check:skill-docs' run as one acquisition of scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14305-r2. Lock verdict line: 'os-verify-lock: VERDICT command-exit 0 - held the lock 325s (5m25s) - waited 266s (4m26s)'. Result 25 ran / 23 green (exit 0) / 2 NOT MEASURED (exit 3) / 0 red; the union was run twice (before and after the merge) and the 25 exit codes are identical. NOT MEASURED, both by design and neither touched by this flight: 'node scripts/check-test-completeness.mjs' exit 3, 'check-test-completeness: PREREQUISITE NOT MET -- this gate grades a saved turbo run test log, and no log was named.'; 'pnpm --filter @objectstack/lint run check:doc-formula-expressions' exit 3, 'check-doc-formula-expressions: PREREQUISITE NOT MET -- the workspace package @objectstack/formula is not built'. CI supplies both. The three the dispatch named as expected-green are green and quoted in the PR body: check:skill-docs ('✅ Skill docs in sync', no regeneration demanded), check:skill-compatibility, check:skill-identifier-liveness. Also ran pnpm check:nul-bytes EXIT=0 plus a raw control-byte grep over the edited file (no match). No ablation in this flight -- the change is a deletion, and the red leg IS the deletion's own failure mode, measured on the real tree rather than on a mutated copy.",
      "mcp_calls": "7 - one issue_read get_comments (card thread, the payload channel cannot reach tail comments), one paginated issue_read get_comments as comment read-back, two add_issue_comment (claim, this report), one create_pull_request, one pull_request_read get, one issue_write update for the label union. All bulk reads went through git and the public-repo page payload; no REST (this seat is session-gated: repo-scoped REST answers 403 while /rate_limit reads 15000/hr, so the credential is alive and the whole REST table is unreachable).",
      "open_questions": [],
      "out_of_scope_findings": [
        "not filed, surfaced in the PR body's Scope note instead: dropping the ai row empties the '// the remaining skills' eval notes' section of scripts/check-skills-token-ratchet.mjs, leaving that comment over zero rows. It is created by this PR's own sanctioned deletion, it is inert (the CEILINGS map is keyed by path), and the dispatch excludes prose edits anywhere -- so it is the seat's call, not a separate card.",
        "not filed, no drift today: content/docs/ai/skills.mdx:78 and :230 say other skills' evals/ directories are 'still placeholders'. That is still true after this PR (data, platform and ui stubs remain), but it goes stale once #14296 item 2 finishes deleting all five -- one for the program closeout, not for this card."
      ]
    }

    Generated by Claude Code

  14. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    ACCEPT — round 2, PR #14652 @ ffdbdcd7 (Fixes #14305)

    Session: session_01LraLgQVGq8egUwfYZpbYt1 (skills lane seat)

    Verified against GitHub, not the report:

    Seat's calls on the two things the dev flagged rather than chose: the // the remaining skills' eval notes header now standing over an empty section in the ratchet script is left as is — inert, and the ceiling re-lock pass that closes the programme is the one edit that touches every row anyway; content/docs/ai/skills.mdx:78 / :230 ("still placeholders") goes stale only when the last stub (#14299 r2, platform) lands — recorded on the programme closeout list, not a card yet. The Co-Authored-By trailer question is answered on #13680: harness attribution, accepted.

    Governed surface (skills/**): the PR stays draft; review requested from os-zhuang and hotlong; landing is the maintainer's. On merge: this card closes (Fixes), the seat strips pm:dispatched; #14296 closes once the platform stub (#14299 r2) has landed too.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentationdomain:skillspriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions