Skip to content

feat(lint): validate app.defaultAgent value against platform agent roster (#6041) - #7272

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-6041-default-agent-value-lint
Aug 10, 2026
Merged

feat(lint): validate app.defaultAgent value against platform agent roster (#6041)#7272
os-project-manager merged 1 commit into
mainfrom
claude/issue-6041-default-agent-value-lint

Conversation

@os-project-manager

Copy link
Copy Markdown
Collaborator

Fixes #6041

What changed

validate-ai-agent-authoring gains the value half: it already scanned stack.agents for withdrawn agent declarations (ADR-0063 §2), but never looked at app.defaultAgent's value. Because the Zod type is a plain SnakeCaseIdentifierSchema, any snake_case string parses, builds, and passes os:check — while the runtime only resolves the platform agent roster (ask/build and legacy aliases data_chat/metadata_assistant, ADR-0063 §2) and silently falls back to the platform default for anything else. #5985 measured the blind spot directly: replaying the bad example defaultAgent: 'sales_copilot' left check:skill-examples at 208 green, EXIT=0.

New logic in validateAiAgentAuthoring: for every stack.apps[] entry whose defaultAgent is a non-empty string not present in the existing PLATFORM_AGENT_NAMES set (reused, not duplicated), emit a warning finding (rule: 'default-agent-outside-roster') naming the offending value and the allowed roster. Warning tier per the maintainer's ruling (2026-08-07, reaffirmed 2026-08-09, option A): the failure mode is a silent runtime fallback, not a crash, and the schema itself is intentionally left alone (SnakeCaseIdentifierSchema stays — narrowing to an enum was explicitly rejected as a breaking authoring change ADR-0063 already walked back once).

Sequencing requirement (2026-08-09 ruling, verbatim constraint)

Per the ruling, the existing-metadata hit count was measured before landing:

  • Repo-wide content search for defaultAgent (all extensions, excluding node_modules/dist/.turbo), narrowed to actual value assignments (defaultAgent: '<value>').
  • Only one real assignment exists in-repo: packages/platform-objects/src/apps/studio.app.tsdefaultAgent: 'metadata_assistant' (a legal legacy platform alias).
  • Cross-validated by building @objectstack/platform-objects and running the new check programmatically against every exported platform app (account, setup, studio, system_overview) — 0 findings.
  • apps/app-crm, apps/app-showcase, apps/app-todo, and the skills/ corpus were also swept; the only other literal match is a commented-out doc example in skills/objectstack-ui/SKILL.md (// defaultAgent: 'build'), itself an in-roster value.

Hit count: 0. The "does not punish existing metadata" premise of the warning tier is verified, not assumed — consistent with the expectation that PR #6030 already fixed the one known bad corpus instance.

Tests

Anti-vacuous coverage added to packages/lint/src/validate-ai-agent-authoring.test.ts:

  • A roster-outside value (sales_copilot) plants a finding and the test asserts the exact rule/severity/where/path, plus that the message names both the offending value and the full allowed roster.
  • Every canonical name (ask, build) and every legacy alias (data_chat, metadata_assistant) is asserted to produce zero findings (reverse case).
  • Absent / empty-string / non-string defaultAgent stays silent.
  • Multiple apps report independently with stable apps[n].defaultAgent paths, alongside the pre-existing agents[] limb.
  • Junk app shapes don't throw.

Notes

  • packages/lint/src/index.ts: added DEFAULT_AGENT_OUTSIDE_ROSTER to the existing barrel re-export block for validate-ai-agent-authoring.js (required by this repo's own rule-id-barrel-exports.test.ts gate — every declared rule id constant must be reachable from a published barrel). This is not a registry/wiring change: the rule (validateAiAgentAuthoring) was already registered in reference-integrity-suite.ts; only the new constant's export needed adding.
  • No changes to SnakeCaseIdentifierSchema, authoring-rules.ts, or validate-flow-trigger-readiness.* (parallel-safety per dispatch note).

Changeset

Real changeset added (@objectstack/lint: minor) — a functional addition to a published package.

Verification

pnpm --filter '@objectstack/lint' test -- --run --maxWorkers=2
 Test Files  69 passed (69)
      Tests  1805 passed | 4 skipped (1809)

pnpm --filter '@objectstack/lint' typecheck   # clean, no output

npx eslint packages/lint/src/index.ts packages/lint/src/validate-ai-agent-authoring.ts packages/lint/src/validate-ai-agent-authoring.test.ts --no-inline-config   # clean, no output

node scripts/check-nul-bytes.mjs   # OK

Generated by Claude Code

…ster (#6041)

validate-ai-agent-authoring previously scanned only stack.agents. Add the
value half: app.defaultAgent outside PLATFORM_AGENT_NAMES (canonical +
legacy aliases, reused not duplicated) now emits a warning finding naming
the offending value and the allowed roster. Warning tier per maintainer
ruling on #6041 (2026-08-07, reaffirmed 2026-08-09, option A) -- the
failure mode is a silent runtime fallback, not a crash; schema stays a
plain SnakeCaseIdentifierSchema (narrowing to an enum was explicitly
rejected as a breaking change).

Existing-metadata hit count measured before landing per the ruling's
sequencing requirement: 0 (only real in-repo assignment is
studio.app.ts's defaultAgent: 'metadata_assistant', an in-roster legacy
alias).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F8q5J1MQyocgtNspb15fSn
@vercel

vercel Bot commented Aug 10, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 10, 2026 4:18am

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

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

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

  • content/docs/automation/hook-bodies.mdx (via @objectstack/lint)
  • content/docs/permissions/authorization.mdx (via @objectstack/lint)

1 release-owned page(s) also reference the affected code. These are read-only:

  • content/docs/releases/v17.mdx (via @objectstack/lint)

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

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.

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling labels Aug 10, 2026
@os-project-manager
os-project-manager marked this pull request as ready for review August 10, 2026 05:08
@os-project-manager
os-project-manager added this pull request to the merge queue Aug 10, 2026

Copy link
Copy Markdown
Collaborator Author

PM 验收:ACCEPT。 门禁按名点名复读(head b6da25d77,带 branch 过滤):25 项全部 success/skipped,零 failure —— 04:4xZ 缺席的 ESLint(04:22:46Z)与 TypeScript Type Check(04:33:57Z)均已报到。今日第五例延迟形态,五例全部证实为延迟而非失败,判据「缺席就等、不催不改」再次成立。已 draft:false + auto-merge 入队(仓库要求走 merge queue,直接 merge 返回 405)。

逐条对照裁决与派单约束:

  • 命中数纪律 —— 本单标杆。0 命中不是 grep 一遍就收工:唯一真实赋值(studio.app.tsmetadata_assistant)先判定为 ADR-0063 §2 合法 legacy 别名,再用新规则本身对四个平台 app 对象(account/setup/studio/system_overview)跑程序化交叉验证得 0 findings;example apps 与 skills/ 语料全扫,唯一其他字面量是注释掉的 // defaultAgent: 'build',本身即表内值。「warning 档不惩罚存量」从假设变成了测量 —— 这正是 08-09 裁决要求的先测后落。
  • warning 档按裁决(2026-08-07 立、08-09 重申,方案 A):失败形态是静默回退而非崩溃。
  • roster 复用:PLATFORM_AGENT_NAMES.has,未新开名单。
  • schema 未动:SnakeCaseIdentifierSchema 保持原样 —— 收窄为 enum 是 ADR-0063 已经回退过一次的破坏性改动,裁决明确拒绝。
  • 测试五案例:表外值(断言精确 rule/severity/where/path + 消息同时点名违规值与完整 roster)、canonical + legacy 全过的反向案例、absent/empty/非串静默、多 app 独立报告且路径稳定、junk 形状不抛。
  • index.ts 桶导出一行:偏差由仓库自己的 rule-id-barrel-exports.test.ts 门禁强制,推前被套件抓住 —— 正确类型的偏差(机械门禁先于人发现)。非注册/接线改动,规则本身早已在 reference-integrity-suite.ts 注册。
  • 真 changeset(@objectstack/lint: minor),非空非豁免。
  • 清理:worktree 洁净移除,remove 未带 --force —— 连续第二例合规。

合入后本单收卡、#6041pm:dispatched


Generated by Claude Code

Merged via the queue into main with commit d0e5537 Aug 10, 2026
26 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-6041-default-agent-value-lint branch August 10, 2026 05:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[决策] 是否给 app.defaultAgent 的取值加 lint(平台 agent 名单外即 warning)—— #5985 实测门禁对该类缺陷结构性失明

2 participants