Skip to content

docs: accept the hook-body write-set static-analysis gap (ADR-0107) - #3716

Merged
os-zhuang merged 2 commits into
mainfrom
claude/hookschema-structured-writes-czvrhp
Jul 27, 2026
Merged

docs: accept the hook-body write-set static-analysis gap (ADR-0107)#3716
os-zhuang merged 2 commits into
mainfrom
claude/hookschema-structured-writes-czvrhp

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

落实 #3700 的短期建议(选项 1):接受 hook body 写入面的静态检查缺口,并把它写进文档 —— 即 #3583 评估文档 §5 D4 的 (a)。选项 2(结构化 writes 声明)按 issue 的定位保留为独立提案,继续在 #3700 讨论,本 PR 不实现它,因此用 Refs 而非 Closes 关联。

改动内容

  • docs/adr/0107-hook-body-write-set-accepted-static-gap.md(新增) — 决策记录:
    • D1 接受缺口并在作者会读到的每个界面标注(ADR-0049 的 trichotomy:不可覆盖的面必须标注,不能默认让作者以为有覆盖);
    • D2 永久不做对 body 源码的启发式静态分析(正则/AST 猜测写入集)—— 部分覆盖会制造「写入已被检查」的假信心,与评估 §7 的立场一致;
    • D3 结构化 writes 声明定位为能力提案(声明 → lint 校验 → 运行时强制,与 capabilities 同形),deferred + evidence-gated,由 Hook body writes are not statically checkable — accept the gap or give HookSchema a structured writes declaration #3700 跟踪;ADR-0078 §4 的注册期诊断维持原判,不在此重新决策;
    • D4 现有的作者侧缓解指引。
    • ADR 里还记录了当前的真实运行时行为(写入未知字段时):validateRecord 跳过未知键 → SQL driver 把未知列透传给数据库、整个操作在运行期报错;schemaless driver(memory/MongoDB)则静默持久化,与成功不可区分。
  • content/docs/automation/hook-bodies.mdx — 新增「Not statically checked: the write set」小节:明确检查边界(condition 读取侧和 capability 面有检查;写入集没有)、运行时后果、以及替代做法(写入集固定时优先用 flow update_record 节点,它的结构化 fields 是可被 lint 检查的)。
  • content/docs/automation/hooks.mdx — Best Practices 增加一条指向上述小节。
  • packages/spec/src/data/hook-body.zod.tsScriptBodySchema TSDoc 声明该盲区(契约自述边界)。仅注释,无行为变化。
  • docs/audits/2026-07-app-metadata-reference-integrity-assessment.md — §5 D4 标记为已决策,并链接落点。

验证

  • pnpm --filter @objectstack/spec test:256 个文件、6688 个用例全部通过。
  • pnpm --filter @objectstack/spec check:docs:250 个生成文件与 spec 同步(TSDoc 注释不影响生成的 references)。
  • 纯文档 + TSDoc 改动,无运行时行为变化;按 AGENTS.md 清单,非 feature 不加 changeset。

Refs #3700, #3583

🤖 Generated with Claude Code

https://claude.ai/code/session_01EsRh53G7SMwFQL57BpFDsx


Generated by Claude Code

Closes out option 1 of #3700 (from the #3583 reference-integrity
assessment, §5 D4): the set of fields a hook body writes lives in an
opaque JS string, so unknown-field writes cannot be statically checked —
and per the assessment's own posture, must be marked rather than guessed
at.
- ADR-0107 records the decision: accept + mark the gap (D1), never
heuristically analyze body source (D2), and route the structured
`writes` declaration as a deferred, evidence-gated capability proposal
tracked in #3700 (D3), with author guidance (D4).
- content/docs/automation/hook-bodies.mdx gains "Not statically checked:
the write set" — the exact coverage boundary (condition and
capabilities are checked; writes are not), the runtime failure modes
(late SQL driver error vs. silent persistence on schemaless drivers),
and what to do instead.
- hooks.mdx best practices point at that section.
- ScriptBodySchema TSDoc states the blind spot at the contract itself.
- The assessment's open decision D4 is recorded as decided.
No behavior change; documentation and TSDoc only.
Refs #3700
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EsRh53G7SMwFQL57BpFDsx
@vercel

vercelBot commented Jul 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredJul 27, 2026 3:56pm

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation protocol:data size/m labels Jul 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec.

104 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx(via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx(via @objectstack/spec)
  • content/docs/ai/skills.mdx(via @objectstack/spec)
  • content/docs/api/client-sdk.mdx(via @objectstack/spec)
  • content/docs/api/environment-routing.mdx(via @objectstack/spec)
  • content/docs/api/error-catalog.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx(via @objectstack/spec)
  • content/docs/api/index.mdx(via @objectstack/spec)
  • content/docs/automation/approvals.mdx(via packages/spec)
  • content/docs/automation/flows.mdx(via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx(via packages/spec)
  • content/docs/automation/hooks.mdx(via @objectstack/spec)
  • content/docs/automation/index.mdx(via @objectstack/spec)
  • content/docs/automation/webhooks.mdx(via @objectstack/spec)
  • content/docs/automation/workflows.mdx(via @objectstack/spec)
  • content/docs/concepts/architecture.mdx(via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx(via packages/spec)
  • content/docs/concepts/index.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx(via packages/spec)
  • content/docs/concepts/north-star.mdx(via packages/spec)
  • content/docs/data-modeling/analytics.mdx(via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx(via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx(via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx(via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx(via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx(via @objectstack/spec)
  • content/docs/data-modeling/index.mdx(via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx(via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx(via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx(via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx(via @objectstack/spec)
  • content/docs/deployment/cli.mdx(via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx(via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx(via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx(via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx(via @objectstack/spec)
  • content/docs/getting-started/examples.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx(via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx(via @objectstack/spec)
  • content/docs/kernel/cluster.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx(via packages/spec)
  • content/docs/kernel/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx(via packages/spec)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/spec)
  • content/docs/permissions/authorization.mdx(via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx(via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx(via @objectstack/spec)
  • content/docs/permissions/positions.mdx(via @objectstack/spec)
  • content/docs/permissions/rls.mdx(via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx(via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx(via @objectstack/spec)
  • content/docs/plugins/development.mdx(via @objectstack/spec)
  • content/docs/plugins/index.mdx(via @objectstack/spec)
  • content/docs/plugins/packages.mdx(via @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx(via @objectstack/spec)
  • content/docs/protocol/diagram.mdx(via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/runtime-capabilities.mdx(via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx(via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx(via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx(via @objectstack/spec)
  • content/docs/releases/index.mdx(via @objectstack/spec)
  • content/docs/releases/v12.mdx(via @objectstack/spec)
  • content/docs/releases/v13.mdx(via @objectstack/spec)
  • content/docs/releases/v16.mdx(via @objectstack/spec)
  • content/docs/releases/v9.mdx(via @objectstack/spec)
  • content/docs/ui/actions.mdx(via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx(via @objectstack/spec)
  • content/docs/ui/dashboards.mdx(via @objectstack/spec)
  • content/docs/ui/forms.mdx(via @objectstack/spec)
  • content/docs/ui/index.mdx(via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx(via @objectstack/spec)
  • content/docs/ui/setup-app.mdx(via @objectstack/spec)
  • content/docs/ui/translations.mdx(via @objectstack/spec)
  • content/docs/ui/views.mdx(via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

The Check Changeset gate requires every PR to add a changeset; an
empty-frontmatter changeset is its sanctioned "this PR releases
nothing" declaration.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EsRh53G7SMwFQL57BpFDsx
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationprotocol:datasize/mtooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-zhuang@claude