Repository navigation
docs(skills): teach one naming rule, every package-authored metadata name starts with its namespace - #30831
Conversation
…name starts with its namespace State the rule once in objectstack-platform beside the object rule, with the four exceptions (fields, object extensions, container views, translations) and what main enforces today. Rename every bare non-object name the skills' examples and evals show or generate to the crm_ prefix (or the snippet's own package namespace), cross-references included. Token ratchets are paid by same-file deletion of restatements. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cw4B24PbS5MZbX1r5j
|
domain:skills#1 · os-elon-musk · session_016WV4d1mkgEris4MHHLjtnk Contract-review-claim: session_016WV4d1mkgEris4MHHLjtnk · head 7fd4006 · 2026-11-06T05:41Z |
|
domain:skills#1 · os-elon-musk · session_016WV4d1mkgEris4MHHLjtnk Contract reviewServed-tier: ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
Implemented-by: VERDICT: FAIL |
… action lint wording The objectstack-upgrade "Open decisions" row for `agent.tools` still named the skill `case_management` in both cells while the example below it declares `crm_case_management`; both cells now match. The platform rule's enforcement sentence now says an action warns only when one package declares its name twice on one object, which is how the lint keys actions. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cw4B24PbS5MZbX1r5j
|
domain:skills#1 · os-elon-musk · session_016WV4d1mkgEris4MHHLjtnk Contract reviewServed-tier: ① Derived judgments
② Semver levelUnchanged: ③ Boundary flags
④ Design judgment
Implemented-by: VERDICT: PASS |
|
domain:skills#1 · os-elon-musk · session_016WV4d1mkgEris4MHHLjtnk 维护者速读
席位核对 — ACCEPT · head b31889f
Generated by Claude Code |
Requested by Elon · project thread
Fixes #30805
Clause-②: no
Metadata-protocol: none
维护者速读
crm_send_email、crm_sales_rep),例外只有字段、对象扩展、容器视图和翻译;全部示例和 evals 里的裸名已改成带前缀。skills/**文档和 evals,不动任何代码、schema 或行为;回滚就是还原这一个 PR。skills/objectstack-platform/SKILL.md第 123 行新加的规则段,以及下方的改名表和保留名单。node scripts/check-skills-token-ratchet.mjs全绿(每个文件都在原天花板内,靠同文件删减付费);pnpm --dir ui run check:skill-eval-tokens通过。What changes
objectstack-platform/SKILL.mdstates the rule once, as a new paragraph right after the object rule:every metadata name a package authors starts with its namespace (flows, actions, hooks, apps, pages,
dashboards, reports, datasets, queues, positions, permission sets, skills). The exceptions are fields,
object extensions and container views (derived from a prefixed object), and translations (the namespace,
an underscore, then the locale). The paragraph is taught as the authoring contract. It also says what
origin/main enforces today, read off the code:
defineStackrefuses a bare object name (validateObjectNamespacePrefix,packages/spec/src/kernel/namespace-prefix.ts).os buildrefuses a bare doc name (docs/namespace-prefix, an error).os lint'snaming/namespace-prefixwarns only when one package declares an app, page, dashboard,flow, action, report or dataset name twice (
packages/cli/src/commands/lint.tsaround L280-330).The old sentence in that paragraph said
os lintwarns on every bare UI or automation name whenever anamespace is set. That is false on main, so it is removed. #30804 (open) widens that lint. If it lands
first, this paragraph's last sentence must be re-matched to its type list before merge. If this PR lands
first, #30804's PR owes that one-sentence update.
Every example and eval in
skills/**that showed or generated a bare non-object name now carries theprefix. Snippets with no manifest use
crm. Snippets with their own package context keep it:todoforthe i18n app-todo mirror, which already uses
todo_app. Cross-references move together: action targets,dashboardName/reportName, approver and queue values,permissionSets,skills,action_toolnames, translation keys and eval
must_containtokens.skills/README.md"Conventions enforced across skills" now teaches the same rule. It keeps the existingshort-object-name convention for snippets, with no object-level
namespaceand notableName.Rename table (file → old → new)
legal_counsel, permission setcontracts_editorcrm_legal_counsel,crm_contracts_editorsupport_intake(×3), positionservice_agent(×2)crm_account,crm_convert_lead)";crm_support_intake,crm_service_agentreassign_lead,convert_lead,create_campaign,print_a3,open_invoice_pdf(and its handler target); flow targetlead_conversion; app segment/apps/crm/…crm_reassign_lead,crm_convert_lead,crm_create_campaign,crm_print_a3,crm_open_invoice_pdf;crm_lead_conversion;/apps/crm_enterprise/…(the app navigation.md declares)dashboardName: 'sales_dashboard',reportName: 'opportunities_by_stage', pagetask_workbenchcrm_sales_dashboard,crm_opportunities_by_stage,crm_task_workbenchinvoice_print,release_notescrm_invoice_print,crm_release_notessales_dashboard; datasetssales,opportunity_metrics(×3),order_metrics(×2),project_metrics,task_metrics(×2),employee_metrics,contract_metrics(×2); cubeopportunity; actionUrlcreate_opportunity,export_dashboard_pdf; reportpipeline_coverage_by_quartercrm_(the cube'ssql: 'opportunity'table stays)lead_conversion(evals 3, 8); key_actions.log_call(eval 11)crm_lead_conversion;_actions.crm_log_callopportunity_metrics(×2)crm_opportunity_metricscase_intake; queuesescalations,support_intake(×2)crm_case_intake;crm_escalations,crm_support_intakeescalate_overdue_cases,renewal_alertcrm_escalate_overdue_cases,crm_renewal_alertstripe_balance_sweepcrm_stripe_balance_sweepopportunity_discount_approval,dynamic_approval; positionssales_manager(×2, one in theorg_membership_levelcounter-example),sales_director,manager,auditorcrm_budget_approval(eval 3),convert_lead(eval 9); positionsmanager,finance_manager(×2); permission setcontractor_portal; assignment rulecase_intake; queuessupport_team,support_leadscrm_budget_approvalcrm_budget_approvalcase_management; actionescalate_case, toolaction_escalate_casecrm_case_management;crm_escalate_case,action_crm_escalate_caseescalate_case/action_escalate_case(eval 1,must_containtoo);close_case/action_close_case(evals 4, 5); agentsupport_bot(eval 5); eval 1 expects "a snake_casename"crm_; "a namespace-prefixed snake_casename"support_bot;skills: ['case_management']crm_support_bot;['crm_case_management']support_intake; positionservice_agentcrm_support_intake;crm_service_agentsales_user(×2); positionsales_repcrm_sales_user;crm_sales_repmy_validation_hook,fill_position_on_hire,protect_strategic_accounts,audit_trail,cascade_account_updates,mask_pii,hcrm_validation_hook,crm_fill_position_on_hire,crm_protect_strategic_accounts,crm_audit_trail,crm_cascade_account_updates,crm_mask_pii,crm_haccount_defaultscrm_account_defaultstax_id_external_checkcrm_tax_id_external_checkinside_sales(×2), positioninside_sales_rep(eval 8)crm_inside_sales,crm_inside_sales_rep_actions.complete(the app-todo mirror, namespacetodo)_actions.todo_completeclose(eval 1); reportpipeline_by_stage, permission setsales_manager, positionregional_lead, picklistdeal_stage(eval 6); pagehome, flowexpense_claim(eval 7)crm_"approve""crm_approve"namespace, notableName."namespace, notableName."Not renamed, because they are exempt as nested names: validation rule names, flow node ids, edge targets,
widget ids, dataset dimensions and measures, assignment-rule entries, nav item ids, params, and container
view keys.
Held, not renamed (report per the dispatch's external-caller stop)
stripe,github_mcp,warehouse_api,legacy_erp(integration-recipes.md),erp_api(datasources.md),sap_erp(upgrade eval 3) and the platformslackconnector. The id iswhat credentials and inbound calls name.
carrier_callback. Its name is a segment of the inbound URL the carrier calls(
…/hooks/carrier_callback/carrier).warehouse. Its name keys theOS_DATASOURCE_WAREHOUSE_PASSWORDvariable.view_piiandexpense.approve_request. Their grammar is dotted, and how a prefixapplies to it is a phase-3 question.
normalize,helpdesk.aiTriageStub,billing.sync). They are not ametadata type. Knowledge source id
support_kb. It is not stack metadata.account,lead,task, …). These are outside this card, whichcovers non-object names. See Open questions.
Token ratchet: paid by same-file deletion, no ceiling moved
os lintsentence; two TOC parentheticals that restate the H2 headings ofplugin-development.mdandoperations.mdmaxRevisionsrow's pointer, which the bullet list below repeatsseeds.md's headings and was already missing one)afterFindcode comment that repeats the sentence above itdefineStack({ permissions })line under itPackage-wide (all authored and eval files under
skills/**this PR touches, ceil of bytes over 4):7633 → 7635 lines, 97336 → 97353 tokens (+17). The +17 is the eval fixtures, which are measured but not
ratcheted, plus
skills/README.md, which is outside the ratchet. Every ratcheted file is at or under itsceiling.
Why
Decision #30798 ruled C (maintainer, verbatim: 「同意 c」). Every package-authored metadata name carries its
namespace, in three phases. This is phase 2, the AI-authoring half: the published skills teach the one rule
before phase 3 makes a bare name a refusal.
Tests
No code changes, so there are no new unit tests. The gates that read
skills/**are what judge this diff.Families derived by
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(48), run locally at head
7fd40067, each exit code recorded asCOMMAND :: exit CODE:node scripts/check-skills-token-ratchet.mjs(and--self-test),pnpm --filter @objectstack/spec run check:skill-examples(after the@objectstack/client-react...closure build),check:skill-docs,check:skill-refs,pnpm --filter @objectstack/lint run check:doc-formula-expressions(after the@objectstack/lint...closure build),
pnpm check:skill-top-level-keys,check:skill-identifier-liveness,check:skill-frame-sync,check:skill-compatibility,check:nul-bytes,check:doc-authoring,check:pm-governed-mergesandpnpm --dir ui exec vitest run scripts/.pnpm check:dual-build-cjs-loadsexited 3 with "PREREQUISITE NOT MET — this gate reads built output,and some package has no dist/". Nothing was measured. The gate reads
packages/**/dist, which this diffdoes not touch. The PR's CI check-run is the reading for it.
--ranreconciliation: "48 derived famil(ies) accounted for — 47 run, 1 NOT-MEASURED (1 DERIVED froma recorded exit 3)", with 0 unrun.
pnpm --dir ui run check:skill-eval-tokens --self-testandpnpm --dir ui run check:skill-eval-tokensexited 0 ("Every must_contain token is taught by its ownskill bundle").
pnpm lintexited 0.Acceptance notes
skills/objectui/guides/project-setup.mdL199-221 imports
defineConfigfrom@objectstack/runtime, which exports nodefineConfigon main.The snippet also nests
objectsunderapps[]with the namemy-app. It carries noos:checkmarker, so no gate compiles it.
crmis bare, becausevalidateObjectNamespacePrefixchecksfor the namespace followed by an underscore. That is why the action URL now points at
crm_enterprise.Open questions
account,lead) bythe README convention, while ADR-0129 requires the prefix once a namespace is set. Recommendation: a
separate card after phase 3, so this PR stays at the card's non-object scope.
phase 3 exempt names an external caller or a variable spells, or rename them with a migration note.
crm.view_piiorcrm_view_pii).Verification
node scripts/check-skills-token-ratchet.mjs. Every ratcheted filereads at or under its ceiling, and no ceiling moved.
pnpm --dir ui run check:skill-eval-tokens. It passes, including the renamedaction_crm_escalate_casetoken.skills/objectstack-platform/SKILL.mdL123 againstpackages/spec/src/kernel/namespace-prefix.tsand
packages/cli/src/commands/lint.ts. The enforcement sentence matches main.git grep -nE "name: '(lead_conversion|support_intake|sales_rep|escalate_case|case_management)'" -- skills.It returns nothing.
Human Minimum
packages/specholds no runtime logic. (packages/specuntouched.)pnpm lintpasses.main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed. (Not touched.)content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.## 维护者速读summary.🤖 Generated with Claude Code
https://claude.ai/code/session_016WV4cw4B24PbS5MZbX1r5j