Skip to content

skills: integrations are declared, not coded — teach the declarative-connector-first rule, the per-archetype recipes and the credential hand-off in objectstack-automation, with an eval that refuses the "write a DocuSign plugin" answer #27223

Closed

Description

@objectstack-fleet

Filing gate ③ (maintainer-directed task). The maintainer in this session, 2026-10-28, verbatim: 「hotclm 的开发agent 就搞错了,说明 skills还是不对,要立卡完善」, after 「所以应该先处理 A/B 吧,并且要有 skills或者文档指导元数据开发者。前面agent还在建议我开发 DocuSign」. North Star rule 4: 「写给 AI 的文档与 skills 说错一句,等于产品缺陷」.

Filed by session_01J8VVAjRKqdoEYQ4hXxtBuf. ⛔ Not a claim. Lane suggestion: domain:skills (skills/objectstack-automation/** is a governed surface, Tier H: a seat drafts, the maintainer lands). Triage sets labels and priority.

The defect, with its instance. An app-authoring agent working on HotCLM (objectstack-ai/hotclm#83) needed DocuSign and concluded the platform had to build a code plugin. #25747 records its reasoning: "Today the only shipped path is a declarative instance over a generic provider (provider: 'openapi' | 'rest' | 'mcp', ADR-0097). Each app would then re-derive 'envelope → contract' semantics from DocuSign's several hundred OpenAPI operations". It knew the declarative path existed and judged it unusable, so it asked for connector-esign. The right answer for a vendor API reachable over HTTP is a declarative instance inside the app — a trimmed, packaged spec with an operation allowlist, auth.credentialRef, a flow connector_action, and the vendor callback as an api-triggered flow — and, where the loader cannot take the vendor's document yet, to say which platform capability is missing (#26709 for include and normalization, #26702 for OAuth) rather than to propose code. Nothing in the published skills teaches that rule, and two lines steer the other way:

  • skills/objectstack-automation/SKILL.md:89 — "connector_action | Invoke a pre-built integration connector" (read at c3fb185a). "Pre-built" reads as "someone ships a plugin"; the declarative instance an app author writes is not mentioned on the node table.
  • skills/objectstack-automation/SKILL.md:404-405 — "model the business lifecycle in Flow/Approval metadata first, reserve custom code for edge-case integrations". With no definition of "edge-case", an agent facing a 4.7 MB vendor spec files the integration under custom code.
  • skills/objectstack-automation/references/ holds examples-flows.md and state-machines-and-approvals.md; no reference covers defineConnector with a provider, and no eval under skills/objectstack-automation/evals or skills/objectstack-api/evals mentions a connector (grep -rln -i connector → 0 files).
  • The docs page content/docs/automation/connectors.mdx does teach all of it (the three entry shapes, the three providers' providerConfig, credentialRef, "Where is oauth2?", dispatch from a flow, failure modes, a runnable example). The gap is in the skills, which is what an agent reads first.

Business reason. Every integration-bearing app (HotCRM, HotCLM, hotsrm, the GRC and expense products planned for the marketplace) will be written by agents reading these skills. Each wrong turn costs a platform card, a maintainer ruling and weeks of queue (#25747 is one). Reader of the fix: every app-authoring agent; the eval is what proves the fix.

Dedupe (semantic issue search, objectstack-ai/objectstack, open and closed, 2026-10-28): "skills teach declarative connector instance versus plugin integration recipe eval DocuSign connector_action" → 2 hits: #25747 (open; the instance this card cites, not a skills card), #20287 (closed; connector triggers and designer keys). No card covers the skills.

Governing text

  • North Star 「写给 AI 的文档与 skills 说错一句,等于产品缺陷」 (docs/NORTH-STAR.md, 优先级 4). Re-check: git grep -n "说错一句" origin/main -- docs/NORTH-STAR.md.
  • ADR-0097 §1-§2: a provider-bound connectors: entry is "a live, dispatchable connector authored as pure metadata"; a declared provider with no installed factory is a hard boot error. Re-check: git grep -n "authored as pure metadata" origin/main -- packages/spec/src/stack.zod.ts.
  • ADR-0019 D2: plugins are internal contributions, never the consumer unit; an app ships what it needs inside itself.
  • AGENTS.md Prime Directive chore: version packages #10: never advertise a capability the runtime does not deliver — so the recipes must describe today's loader limits and the cards that lift them, not keys that have not landed.
  • pm-dispatch references/decision-analysis.md 〈应用仓推荐序特例〉: 「能力先建在平台…应用仓不自建替代」 — which the agent honoured; the skill must tell it that a declarative instance is the platform path.

Protocol statement. Metadata-protocol: none — a skills and evals change only. No spec key, no runtime behaviour.

Premises (each with a re-check; read at c3fb185a)

  1. The node table's connector_action row says "pre-built". Re-check: git grep -n "pre-built integration connector" origin/main -- skills/objectstack-automation/SKILL.md.
  2. No skill reference or eval covers a provider-bound declarative instance. Re-check: git grep -rln -i "defineConnector\|provider: 'openapi'" origin/main -- skills/*/references skills/*/evals (expected 0).
  3. The docs page covers it. Re-check: git grep -n "Declaring a provider-bound instance" origin/main -- content/docs/automation/connectors.mdx.

Work (one PR, governed surface)

  1. The rule, in skills/objectstack-automation/SKILL.md. Replace the two lines above with a short section "Integrations are declared, not coded": a vendor system reachable over HTTP (an OpenAPI document, a remote MCP server, or a plain REST API) is a connectors: entry inside the app with provider: 'openapi' | 'mcp' | 'rest', a packaged spec, auth.credentialRef, and connector_action from flows; inbound vendor callbacks are api-triggered flows. Platform code is written only when one of five things is true: the protocol is not HTTP; the work writes platform identity objects (users, units, positions); it processes files or binaries locally; it needs one fixed action contract across several vendors; or the inbound callback's signature is outside trigger-api's HMAC. When the loader cannot take a vendor document today (YAML, Swagger 2.0, $ref, OAuth, request signing), the agent names the gap and the card that lifts it — connectors: auto-shelf readiness — declarative include and a loud Swagger 2.0 refusal for connector-openapi; tools/list pagination, fatal 401 and a tool-snapshot hash for connector-mcp; an offline spec-normalization tool #26709, connectors: outbound OAuth in the open tier — connection-scoped authorization-code / client-credentials / app-credential tokens, refreshed per dispatch, for the openapi, mcp and rest providers #26702, connectors: request-signing auth kind for the openapi and rest providers (RSA2 / HMAC canonical-request signers: Alipay, WeChat Pay, Aliyun, Tencent Cloud, e签宝) — the vendor-auth half that #26702 does not cover #26710 — and does not propose a plugin.
  2. references/integration-recipes.md: one end-to-end recipe per archetype, each as connector entry + fields + flow + optional ai: { exposed: true } action: static-key OpenAPI (Stripe read); remote MCP with a static header (GitHub); generic REST (provider: 'rest', actionId: 'request'); vendor callback (api trigger with secretRef); a vendor with no machine-readable spec (write a minimal OpenAPI document by hand and package it); and two "not yet" entries stating plainly what OAuth-protected and signature-authenticated vendors wait on. Each recipe states what the app author declares and what the customer's administrator supplies (the credential behind credentialRef), because those are two different people.
  3. Evals under skills/objectstack-automation/evals: (a) the DocuSign case — the expected answer is a declarative openapi instance with three allowlisted operations and an api-triggered callback flow, marked blocked on OAuth, and the eval fails on any answer proposing a platform plugin; (b) the Stripe-read case — a correct entry with credentialRef and a scheduled flow writing back to crm_account fields; (c) a vendor-without-spec case.
  4. Cross-link the docs page from the skill; carry the include, oauth2 and signed keys into the recipes only when connectors: auto-shelf readiness — declarative include and a loud Swagger 2.0 refusal for connector-openapi; tools/list pagination, fatal 401 and a tool-snapshot hash for connector-mcp; an offline spec-normalization tool #26709, connectors: outbound OAuth in the open tier — connection-scoped authorization-code / client-credentials / app-credential tokens, refreshed per dispatch, for the openapi, mcp and rest providers #26702 and connectors: request-signing auth kind for the openapi and rest providers (RSA2 / HMAC canonical-request signers: Alipay, WeChat Pay, Aliyun, Tencent Cloud, e签宝) — the vendor-auth half that #26702 does not cover #26710 land (their own Skills-docs: lines owe that).

Acceptance

  • pnpm skill evals green with the three new cases; the DocuSign eval demonstrably fails against the current skill text and passes against the new one.
  • The words "pre-built integration connector" no longer appear in skills/objectstack-automation/SKILL.md; git grep -n "Integrations are declared, not coded" -- skills/objectstack-automation/SKILL.md hits.
  • The recipes name no key the runtime does not deliver at the PR's base.

Related

#25747 (the instance; its scope is the maintainer's to re-rule) · #26709 · #26702 · #26710 · content/docs/automation/connectors.mdx · ADR-0097.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Triage: p1 · domain:skills · area:automation · 2026-10-28T12:00Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Part of #27293 (E3 author surface) · 2026-10-28T15:01Z

    Epic link on the maintainer's ruling 「是否建议立专题卡统一处理。」→「同意」 (2026-10-28, session_01J8VVAjRKqdoEYQ4hXxtBuf). Role in the chain: the skills rule and recipes; carries the include / oauth2 / signed keys only as #26709 / #26702 / #26710 land (Prime Directive #10). Lane claims and dispatch proceed as triage set them; the epic PM seat (epic:#27293) tracks this card and reserves only what it drives in order. ⛔ Not a claim.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U

    Reserved for the epic subtree · 2026-10-28T15:12Z — pm:queue → pm:epic (one label write); triage grade and lane unchanged.

    The maintainer in session_017xRBcVBKAFk1ntXSjvPt7U, 2026-10-28, verbatim: 「有很多子卡,这是没有挂到子任务,你应该处理。」 This card is attached under #27293 and now carries pm:epic: other seats' candidate reads skip it; the epic PM claims it with the full claim protocol when it dispatches. ⛔ Not a claim, ⛔ not a dispatch.

  4. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:skills#1 · sunhaolin · session_017xRBcUi2qhP1eKRbZJ1Ze1

    Claim: PM loop round 1
    Session: session_017xRBcUi2qhP1eKRbZJ1Ze1
    Account: sunhaolin (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-27223-declarative-connectors-skill
    Worktree: objectstack-issue-27223
    Domain: domain:skills
    Seat: domain:skills#1
    File surface: skills/objectstack-automation/SKILL.md (the node-table connector_action row, the "reserve custom code" line and the new rule section; net tokens ≤ 0 under the ratchet, headroom 0), skills/objectstack-automation/references/integration-recipes.md (new), skills/objectstack-automation/evals/ (one new eval file), scripts/check-skills-token-ratchet.mjs (the CEILING_BASIS rows for the two new files only) (stop on breach; explain in the report)
    Container & model: L, mode:subagent, model: CONTRACT_REVIEW_TIER (MANDATORY — dispatch-gates --tier this fire: skills/objectstack-automation/SKILL.md ⇢ 'skills/**' — clause ① (2026-09-10 ruling, verbatim 「必须 fable的还包括对外发布的skills」); no one-line exit under this root), effort: xhigh
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: 6472521534
    Premise: holds (re-checked at origin/main 5b5cff15, 2026-10-28T15:20Z: pre-built integration connector hits SKILL.md:89; defineConnector|provider: 'openapi' → 0 files under skills/*/references skills/*/evals; Declaring a provider-bound instance hits content/docs/automation/connectors.mdx:40)
    Serial constraints cleared: none — no open PR and no in-flight claim touches skills/objectstack-automation/** (open PR list read this fire; seat 2's post r73 carries the file only as a ratchet reading). Seam: #27237 (domain:server, os-bill, in flight) lands sys_connector_credential; this card teaches today's credentialRef path (env at boot) and names #27237 for the administrator door, carrying no key the runtime does not deliver at the PR's base.

  5. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:skills#1 · sunhaolin · session_017xRBcUi2qhP1eKRbZJ1Ze1

    already claimed — yielding · 2026-10-28T15:28Z. The epic PM's reservation 6472857708 (epic:#27293#1, session_017xRBcVBKAFk1ntXSjvPt7U, pm:queue → pm:epic at 2026-10-28T15:12Z) precedes this seat's claim 6472995916; the seat's label step ① had already read pm:epic and no pm:queue, and the write should have stopped there. Rolled back in this act: pm:dispatched removed, sunhaolin unassigned, pm:epic kept. The card is the epic subtree's; this seat does not touch it again.

    Hand-over of what this seat read (data for the epic PM, not instructions): premise re-checks hold at origin/main 5b5cff15 (pre-built integration connector at skills/objectstack-automation/SKILL.md:89; 0 files for defineConnector|provider: 'openapi' under skills/*/references skills/*/evals; Declaring a provider-bound instance at content/docs/automation/connectors.mdx:40); skills/objectstack-automation/SKILL.md token ratchet 6466 / 6466, headroom 0 (new text is paid by deletion in the same file; a new references/ or evals/ file needs a CEILING_BASIS row in scripts/check-skills-token-ratchet.mjs or the ratchet is red); dispatch-gates --tier MANDATORY CONTRACT_REVIEW_TIER (skills/**, no one-line exit), effort xhigh; no open PR or claim touches skills/objectstack-automation/** (open PR list read this fire); seam #27237 (os-bill, in flight) — teach today's env-at-boot credentialRef path and name #27237 for the administrator door, carrying no key the runtime does not deliver at the PR's base.

  6. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U

    Claim: PM loop round 1
    Session: session_017xRBcVBKAFk1ntXSjvPt7U
    Account: sunhaolin (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-27223-integrations-declared
    Worktree: objectstack-issue-27223
    Domain: domain:skills
    Seat: epic:#27293#1
    File surface: skills/objectstack-automation/SKILL.md (the node-table connector_action row, the "reserve custom code" line, the new rule section; net tokens ≤ 0 under the skills token ratchet), skills/objectstack-automation/references/integration-recipes.md (new), skills/objectstack-automation/references/_index.md (one entry), skills/objectstack-automation/evals/ (one new eval file), scripts/check-skills-token-ratchet.mjs (CEILING_BASIS rows for the new files only) (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: CONTRACT_REVIEW_TIER (MANDATORY — dispatch-gates --tier this fire, 2026-10-28T15:50Z: skills/objectstack-automation/SKILL.md ⇢ 'skills/**' — clause ①, no one-line exit under this root), effort: xhigh
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: 6473190116
    Premise: corrected (this comment, § Premise correction)
    Serial constraints cleared: none — the 7 open PRs updated since 2026-10-28T15:15Z touch no file under skills/objectstack-automation/** (files read 2026-10-28T15:52Z); the domain:skills#1 claim 6472995916 was rolled back by its own yield 6473190116. Seam: #27237 (domain:server seat 3, in flight) lands the administrator credential door; this card teaches today's credentialRef path and names #27237 for that door.

    Premise correction

    Read at origin/main 65b49208, 2026-10-28T15:48Z. Premises 1–3 hold (pre-built integration connector at skills/objectstack-automation/SKILL.md:89; 0 files for defineConnector|provider: 'openapi' under skills/*/references/* and skills/*/evals/*, control flow 19 files; Declaring a provider-bound instance at content/docs/automation/connectors.mdx:40). One work item changes form, target unchanged:

  7. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U
    os-dev-report

    {
      "issue": 27223,
      "status": "done",
      "branch": "claude/issue-27223-integrations-declared",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/27322",
      "session": "session_017xRBcVBKAFk1ntXSjvPt7U",
      "premise_still_valid": true,
      "summary": "SKILL.md: the `connector_action` row no longer says \"pre-built\", the \"reserve custom code for edge-case integrations\" line is gone, and a new section \"Integrations are declared, not coded\" states the declarative-connector-first rule, the five cases that justify platform code, and gap-naming against a platform card (net -1 token under the ratchet, paid in the same file). New `references/integration-recipes.md` (150 lines, six archetypes + two not-yet entries + the author/administrator credential hand-off) and `evals/integrations-declared.json` (DocuSign, Stripe-read, vendor-without-spec; the DocuSign case's must_not_contain refuses any plugin answer). Three runtime limits were measured on base and are taught plainly: `connectorConfig.input` is handed to the provider as written (no CEL/{{ }} evaluation), the `openapi` provider has no `include` (the trimmed document is the allowlist), and the inbound `api` door verifies only ObjectStack's own timestamped signature. Draft PR #27322 (Tier H, never readied), assignee sunhaolin, `@objectstack/skills` patch changeset. `#25747` is now closed (not_planned); the premise was re-verified on origin/main a0aa8a1f and holds.",
      "tests": "No package source changed; no pnpm test/typecheck owed. Skill evals: NO runner exists in the root repo (no pnpm script consumes skills/*/evals/*.json; ui/scripts/check-skill-eval-tokens.mjs scans ui/skills only), so the card's `pnpm` skill evals cannot be run as spelled. Ran a scratch replay (not committed) of that gate's whole-token rule over skills/objectstack-automation/*.md: BASE bundle (a0aa8a1f) -> exit 1: eval 1 5 untaught tokens (defineConnector, provider: 'openapi', type: 'api', Swagger 2.0, blocked), eval 2 1 untaught, eval 3 3 untaught; THIS branch (2993d737) -> exit 0: eval 1/2/3 PASS, 0 untaught. Existing eval file on the new bundle: 9 PASS, evals 7 and 8 untaught on base too (pre-existing). Ratchet: `node scripts/check-skills-token-ratchet.mjs --self-test` exit 0 (79 cases), gate exit 0 (84 files within ceilings; automation SKILL.md 6465/6465, recipes 2177/2177, eval 1193/1193). id-lint probe: a `#26709` line under references/ -> exit 1 naming the line (why no card numbers are in the skill text). FlowSchema probe (tsx, scratch, deleted): a CEL envelope inside connectorConfig.input parses success=true and is kept verbatim. NOT MEASURED: a live LLM answering arm per eval (base vs new text) — no runner; a self-graded run by the authoring seat is not evidence. No ablation owed (docs/skills/eval/ceiling rows only).",
      "gates": "Local subset: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 64 commands for the 5 changed paths; every one ran as `bash -c CMD > log 2>&1; code=$?` (exit captured before any pipe) and was recorded as `CMD :: exit CODE`; `--ran` reconciliation exit 0: 64 derived, 59 run (all exit 0, incl. check:skill-docs, check:skill-refs, check:doc-authoring, check:nul-bytes, check:pm-skill-id-lint, check:skill-identifier-liveness, check:skill-frame-sync, check:skill-compatibility, check:ratchet-remedy-authority, check:pm-dispatch-gates 412s, check-empty-changeset --base origin/main, check-adr-0087-registration --base origin/main, check:published-files, check:merge-driver), 5 NOT-MEASURED with recorded exit 3 PREREQUISITE NOT MET (they read built dist/, never built for this skills-only diff): check:doc-formula-expressions, check:dts-closure, check:dual-build-cjs-loads, check:lean-entry-closure, check:sourcemap-no-sources-content. check:dev-prereqs / check:skill-frame-freshness not owed (no spec build, no frame file). CI on head 2993d737 at report time: 20 check-runs — 17 in_progress (Lint · docs & code guards; Lint · repo & tooling gates; Lint · PM dispatch-gates; Lint · ESLint; Lint · CI, release & engine gates; Lint · scoped · tooling self-tests; Lint · scoped · slot lookup & corpus; Lint · scoped · query-options erasure; Type Check · workspace; Type Check · source gates; Type Check · consumer gates; Type Check · debt ledger; Governed Surface Queue Guard; Check Changeset; Check PR Size; PR-body guards; filter), 3 skipped (Schedule gate; Packed-tarball smoke (opt-in); 18.x upgrade harness (opt-in)). Not re-run locally; convergence is the PM's read.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "0 — no MCP GitHub calls; all GitHub reads via gh api, all writes via scripts/pm/ relay tools",
      "api_writes": "2 REST write strokes via the fleet relay: (1) pr_create = POST /repos/objectstack-ai/objectstack/pulls + POST /repos/objectstack-ai/objectstack/issues/27322/assignees (one relay dispatch, run 40729892978, read-back byte-identical, draft forced); (2) this os-dev-report comment = POST /repos/objectstack-ai/objectstack/issues/27223/comments via post-stamped. Plus git push x2 (empty probe branch, then the one commit; not REST). No labels sent (a changeset is included, so no skip-changeset).",
      "deviations": [
        "Card numbers (#26709, #26702, #26710, #27237) are NOT spelled in the skill text: scripts/pm/check-skill-id-lint.mjs forbids /#[0-9]{3,}/ in every .md under skills/ by maintainer ruling; measured red on a probe line. The recipes name each gap as blocked on 'its platform card'; the numbers are in the PR body.",
        "references/_index.md not edited: it is generator-owned (gen:skill-refs writes schema pointers only) and check:skill-refs passes with the hand-written reference beside it; SKILL.md links the recipes directly.",
        "The card's 'pnpm skill evals green' has no runner in this repo; evidence is the scratch whole-token oracle (base FAIL / new PASS) and the eval's must_not_contain list; live model arms NOT MEASURED.",
        "The DocuSign expected answer names a third gap beyond the PM's two (include, OAuth): connectorConfig.input is literal, so a per-contract payload is not a declarative dispatch today; and the api callback flow is declared with the caveat that DocuSign Connect's own signature is outside the door's scheme (the card's own fifth code condition). The eval still fails any plugin answer.",
        "Inside the declared SKILL.md surface, more than the three named sites moved to pay the ratchet: one 'When to Use' bullet added, the http row's auth-routing tail moved into the recipes, a stale '(see the approval example below)' pointer and the eval pointer in References removed, eight clause-level trims; nothing outside the claimed file surface was touched.",
        "PR body says the bundle 'grows by 3,370 tokens' (sum of the two new files); the net delta is +3,369 (SKILL.md -1). dev writes the body once; the seat may correct that one figure.",
        "The single commit's title carries '(WIP)'; not amended to avoid a force-push on a Tier H branch.",
        "Five derived families NOT MEASURED locally (exit 3, built dist prerequisite); CI runs them after its build."
      ],
      "line_budget": {
        "skills/objectstack-automation/SKILL.md": "lines 451 -> 451; tokens 6466 -> 6465 (net -1; ceiling re-locked 6465, headroom 0; PM budget net <= 0 met)",
        "skills/objectstack-automation/references/integration-recipes.md": "new, 150 lines, 2177 tokens (PM budget <= 150 lines met)",
        "skills/objectstack-automation/evals/integrations-declared.json": "new, 35 lines, 1193 tokens, 3 cases",
        "package": "sum of all skills/*/SKILL.md lines 4615 -> 4615; bundle total (whole shipped tree) 215826 -> 219195 tokens",
        "diff": "5 files, +282 / -56 (dispatch-gates: 338 changed lines, under the 3000 human-merge threshold)"
      },
      "files_changed": [
        "skills/objectstack-automation/SKILL.md (+54/-56)",
        "skills/objectstack-automation/references/integration-recipes.md (new, +150)",
        "skills/objectstack-automation/evals/integrations-declared.json (new, +35)",
        "scripts/check-skills-token-ratchet.mjs (+24/-1: SKILL.md row 6466 -> 6465; two new rows)",
        ".changeset/27223-integrations-declared.md (new, +18; @objectstack/skills patch)"
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "class: c · reach: public door — FlowSchema.safeParse (the schema os validate runs) accepts a CEL envelope under connectorConfig.input (success=true, envelope kept verbatim), while the executor hands cfg.input to the provider as written (packages/services/service-automation/src/builtin/connector-nodes.ts:108; builtin/value-slot-map.ts resolves fields / subflow+map input / script inputs / screen defaults / notify templateData / http body, never connector input); the openapi handler then interpolates the path from String(value), so the vendor receives an object stringified · producer: any app author's stored flow definition · dedupe words: connector_action input value slot CEL envelope verbatim · carrier: none — for the seat to file (sub-issue of the connectors epic #27293 if the PM reads it so)",
        "observation (not a card): the root catalog's skills/*/evals/*.json have no mechanical consumer in this repo; ui/ gates its own bundle with check:skill-eval-tokens; the card's acceptance names a pnpm eval run that does not exist · carrier: PM (acceptance wording)",
        "observation (not a card): under the whole-token rule, existing evals 7 and 8 in evals/flows-triggers-approvals.json carry must_contain tokens the bundle never spells (excludeSubmitter: true; type: 'screen', type: 'file', signed_copy) on base as well · carrier: none",
        "observation (not a card): SKILL.md's runAs paragraph requires a system sweep to pin its organization but names no column, and the catalog's own scheduled example carries no predicate; the Stripe recipe mirrors the taught shape with a one-line reminder · read-only inference · carrier: none",
        "observation: #25747 (the DocuSign instance the card cites as open) is closed not_planned; no effect on this card · carrier: none"
      ]
    }
  8. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U
    os-dev-report

    {
      "issue": 27223,
      "status": "done",
      "branch": "claude/issue-27223-integrations-declared",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/27322",
      "session": "session_017xRBcVBKAFk1ntXSjvPt7U",
      "premise_still_valid": true,
      "round": "contract-review patch round on PR comment 6475700322 (PASS, two should-fixes) plus the coordinator's addendum (two items); supersedes nothing in report comment 6475198480 except the figures restated below",
      "summary": "ONE new commit 51e80455 on claude/issue-27223-integrations-declared (no amend, no force-push; parent 2993d737), four files. (1) SKILL.md five-condition sentence now reads 'Platform code only when one holds — and then it is the platform's, filed as a card; the app still writes none: …' (ADR-0019 D2). (2) recipe 1's `$ref` wording widened to 'dereference every `$ref` offline, in-document ones included: the loader skips a `$ref` parameter, request body or response, and the derived input/output schema silently loses it' (openapi-connector.ts:295/:336/:342 verified on this tree). (3) The flow-type table's `api` row now says 'needs a start-node `secretRef` (or a literal `secret`; …)' — verified: both keys are accepted, one required, both together refused (api-trigger-secret-ref.zod.ts:30, :128; api-trigger.ts:267-270 'set a non-blank `config.secret` … or name the secret in `config.secretRef`'); an in-place fix inside the declared file, same defect class (a key taught incompletely), mechanical. (4) eval 1 `must_not_contain`: `clientSecret` -> `clientSecret:` so a correct answer that names the absent OAuth client-secret field still passes; `token:` kept — the bundle's own wrong-shape spelling is `authentication: { token }` (no colon after token), so a correct answer quoting the refusal does not trip it, only an authored `token: '…'` key does. Ratchet paid in-file for SKILL.md (−33 priced bytes net: the CEL blockquote's '(the example apps use plain strings)', three pointer lines' 'Moved to', five clause-level trims) and re-locked at 6457; recipes and eval rows moved by their measured deltas only (2177 -> 2204, 1193 -> 1194). PR still a draft, assignee sunhaolin. PR body NOT patched (see deviations).",
      "tests": "Scratch whole-token oracle on the patched bundle (tree 51e80455): eval 1/2/3 PASS, 0 untaught, exit 0 (base bundle a0aa8a1f still FAILs all three, from round 1). Ratchet: --self-test exit 0 (79 cases); gate exit 0: SKILL.md 6457 tokens (ceiling 6457; headroom 0), integrations-declared.json 1194/1194, integration-recipes.md 2204/2204; 84 authored files within ceilings. Eval JSON parses. No package source changed; no pnpm test/typecheck owed; no ablation owed.",
      "gates": "Local subset re-run on the patched tree: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 64 commands (identical set to round 1); every one ran as `bash -c CMD > log 2>&1; code=$?` and was recorded as `CMD :: exit CODE`; `--ran` reconciliation on tree 51e80455 exit 0: 64 derived, 59 run (all exit 0, incl. check:skills-token-ratchet + --self-test, check:skill-docs, check:skill-refs, check:doc-authoring, check:nul-bytes, check:pm-skill-id-lint, check:skill-identifier-liveness, check:skill-frame-sync, check:skill-compatibility, check:ratchet-remedy-authority, check:pm-dispatch-gates 411s, check-empty-changeset --base origin/main, check-adr-0087-registration --base origin/main), 5 NOT-MEASURED with recorded exit 3 PREREQUISITE NOT MET (built dist/ never built for this diff): check:doc-formula-expressions, check:dts-closure, check:dual-build-cjs-loads, check:lean-entry-closure, check:sourcemap-no-sources-content. CI on head 51e80455 at report time: 41 check-runs — 26 success (incl. Lint & Repo Gates, TypeScript Type Check, Build Core, Governed Surface Queue Guard, Check Changeset, Check PR Size, PR-body guards, Lint UI, Type Check UI, Test UI, Build & E2E UI, Live E2E UI, Dogfood Regression Gate, Dogfood Verify CLI, Temporal Conformance), 14 skipped (opt-in / matrix placeholders), 1 in_progress (Test Core (1/8)). Not re-run locally; convergence is the PM's read. Round-1 review of head 2993d737 (comment 6475700322) saw 42 runs all completed, 28 success, none red.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "0 — no MCP GitHub calls this round; reads via gh api, writes via scripts/pm/ relay tools",
      "api_writes": "This round: 1 REST write via the fleet relay — this os-dev-report comment (POST /repos/objectstack-ai/objectstack/issues/27223/comments via post-stamped). Plus git push x1 (51e80455; not REST). No PR body edit, no labels, no ready flip. Cumulative on the card: pr_create stroke (2 requests) + 2 comments.",
      "deviations": [
        "PR body NOT corrected via the relay: .claude/agents/os-dev.md binds the dev to write the PR body once and never PATCH it (the seat writes later changes), and the relay's only body-editing op is `issue_patch` on `/issues/{n}` (an issues op; the coordinator's own fallback applies). Corrections for the seat, verbatim: (a) 'grows by 3,370 tokens' -> 'grows by a net 3,389 tokens (SKILL.md 6466 -> 6457 = -9; integration-recipes.md +2,204; integrations-declared.json +1,194; bundle total 215,826 -> 219,215)'; (b) 'net -1 token under the ratchet' -> 'net -9 tokens'; (c) recipes '2177' -> '2204', eval '1193' -> '1194' in What changes and the Verification table (SKILL.md tokens 6466 -> 6457; lines 451 -> 450; package SKILL.md line sum 4615 -> 4614); (d) 'Head 2993d737 … no commit followed' -> 'Head 51e80455 (patch round)'; (e) add under What changes: 'In-place adjacent fix (same file, same class, mechanical): the flow-type table's `api` row said the flow needs a start-node `secret`; the start node takes `secretRef` (a name the deployment fills) or a literal `secret`, one required, both together refused — packages/spec/src/automation/api-trigger-secret-ref.zod.ts:30,:128; packages/triggers/trigger-api/src/api-trigger.ts:267-270 — so the row now names `secretRef` (or a literal `secret`).'",
        "Eval 1 keeps `token:` in must_not_contain (reviewer flagged only `clientSecret`): the bundle spells the refused inline shape as `authentication: { token }`, which `token:` does not match; only an authored `token: '…'` key trips it.",
        "The recipes file stays at 150 lines by folding two prose lines (the intro's final sentence and recipe 1's trailer), not by cutting content."
      ],
      "line_budget": {
        "skills/objectstack-automation/SKILL.md": "lines 451 -> 450 (base 451); tokens 6465 -> 6457 this round (base 6466; net -9; ceiling re-locked 6457, headroom 0)",
        "skills/objectstack-automation/references/integration-recipes.md": "150 lines (unchanged); 8705 -> 8814 bytes, 2177 -> 2204 tokens (+27, the widened `$ref` wording); row moved by the measured delta",
        "skills/objectstack-automation/evals/integrations-declared.json": "35 lines; 4772 -> 4773 bytes, 1193 -> 1194 tokens; row moved by the measured delta",
        "package": "sum of all skills/*/SKILL.md lines 4615 -> 4614; bundle total 215826 (base) -> 219215 (net +3389)",
        "commit": "51e80455: 4 files, +43 / -28"
      },
      "files_changed": [
        "skills/objectstack-automation/SKILL.md (+13/-14)",
        "skills/objectstack-automation/references/integration-recipes.md (+6/-6)",
        "skills/objectstack-automation/evals/integrations-declared.json (+1/-1)",
        "scripts/check-skills-token-ratchet.mjs (+23/-7: SKILL.md row 6465 -> 6457; eval row 1193 -> 1194; recipes row 2177 -> 2204, each with its arithmetic)"
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "unchanged from report comment 6475198480: the class-c `connectorConfig.input` finding (FlowSchema accepts a CEL envelope, executor sends it as written) still awaits the seat's filing; the four observations stand",
        "observation (this round): in-document `$ref` parameters / request bodies / responses are skipped by the openapi loader (openapi-connector.ts:295, :336, :342) with no boot diagnostic — the reviewer named it, the recipe now states it; whether it merits a card under #26709's normalization item is the PM's read · carrier: #26709 (candidate)"
      ]
    }
  9. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U

    ACCEPT → PR #27322 comment 6476475773 · head 51e80455 · 2026-10-28T17:52Z. Contract review PASS 6475700322 (2993d737) and delta PASS 6476424433 (51e80455). In the merge queue by the maintainer (os-zhuang, 2026-10-28T17:49Z).

    Acceptance wording, corrected on the record: "pnpm skill evals green with the three new cases" cannot be met as spelled, because no script in the root repo consumes skills/*/evals/*.json (only ui/ gates its own bundle). The cases were judged by reading them against the shipped bundle and the runtime (both review records ④): the DocuSign case's required tokens are absent from the base bundle and taught by this head, and its must_not_contain refuses every plugin answer. Whether the root catalog should get an eval runner is not decided here.

    Out-of-scope dispositions: filed #27327 (connectorConfig.input is sent as written) · in-document $ref skipped by the openapi loader with no diagnostic → carrier #26709 (its normalization item) · the package-schedule deployment-policy switch is taught nowhere in the skill → noted, not filed.

  10. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U

    MERGED → PR #27322 through the merge queue (queued by the maintainer) · 2026-10-28T18:33Z. Closed completed by its Fixes #27223; pm:dispatched removed in this act, pm:epic kept as subtree membership. Follow-up cards: #27327 (connectorConfig.input sent as written).

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions