Skip to content

create-objectstack: a project name over 13 characters scaffolds a namespace that the first os validate warns about (sanitizeNamespace caps at 20, the #28473 rule warns above 13) #28992

Closed

Description

@objectstack-fleet

domain:devx#1 · os-warren · session_01JQwxbWJDYbbtH6dhJNoboN

立卡门: ① 产品缺陷,具名落点 + 复现(reach: os validate,在刚生成的脚手架项目上实测一次)
业务理由: 新开发者照文档 npx create-objectstack 起一个项目,第一次 os validate 就看到一条警告,要求把命名空间缩到 13 个字符以内并重命名脚手架自带的对象,而这些都不是他写的。项目名稍长(例如 qa-console-first-paint)就会撞上。新人的第一屏就是平台自己的工具在挑平台自己生成的东西的毛病。
动手的读者: domain:cli 席,packages/create-objectstack/src/index.ts 的 sanitizeNamespace():截到 13 个字符(对齐 packages/lint/src/validate-customization-namespace.ts 的上限),或生成时给出明确提示。
查重: sanitizeNamespace 7 命中、namespace-no-customization-pair 28、create-objectstack namespace 20 characters 31(均含已关);最近邻 #28473(规则本身,已关,正文说「仓库里今天没有受影响的」,没算脚手架)、#26642(项目名合法性,已关),都不是本现象。

QA-source: #28981 · cli.scaffold-console-first-paint · observed beside the clauses

What happens

A freshly scaffolded project named qa-console-first-paint gets manifest.namespace: "qa_console_first_pai" (20 characters). Its first os validate exits 0 but prints:

⚠ package "com.example.qa-console-first-paint": namespace "qa_console_first_pai" is 20 characters, so this package has no paired customization namespace … fix: shorten manifest.namespace to 13 characters or fewer, and rename the object names it prefixes (rule namespace-no-customization-pair).

sanitizeNamespace() truncates to 20; the lint rule from #28473 warns above 13 (MAX_CUSTOMIZATION_BASE_NAMESPACE_LENGTH, ADR-0146 D3).

Measured at framework 7fa9873f (main, 2026-11-02): the workspace's public packages packed at that commit and published to a local registry with no upstream, then npx -y create-objectstack@latest qa-console-first-paint.

Reproduction

  1. Scaffold any project whose sanitized name is 14 or more characters, e.g. npx create-objectstack qa-console-first-paint.
  2. cd qa-console-first-paint && npx os validate.
  3. Expected: a pristine scaffold validates with no warning.
  4. Actual: exit 0 with the namespace-no-customization-pair warning above.

Generated by Claude Code

Activity

  1. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: p2 · domain:server · area:devpath · pm:queue · 2026-11-02T05:54Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. added
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    domain:serverDomain lane — seat card indexed by label:pm:seat
    on Nov 2, 2026
  3. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo

    Claim: PM loop round 4 · card thread · 2026-11-02T06:25Z
    Session: session_0186vfjHHMsRXC9EUT9hTFMo (the seat); the card thread is session_01FEkQ5oqaD6uoTrtmva9fde
    Account: os-project-manager (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-g0aewi (the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)
    Worktree: the card thread's own container checkout
    Domain: domain:server
    Seat: domain:server#2
    Ruling-ref: the maintainer, 2026-11-01T03:46Z: 「server 车道现在就是你负责,任务有一大堆啊,都可以派,包括 p3」, with 2026-10-26T10:29Z 「p1 p2 处理完了,就可以处理 p3」. With 2026-11-01T12:11Z 「定级你可以自己决定」 (triage graded this card p2) and 2026-11-02T05:15Z 「队列进了很多任务,抓紧派发」; seat 1 confirmed seat 2 takes this card. Seat's route: sanitizeNamespace() caps at the lint rule's constant, read from one place or pinned equal by a test, with no trailing _. Names that already fit scaffold byte for byte.
    File surface: packages/create-objectstack/src/index.ts (and the constant's export if it moves); their tests; changeset
    Container & model: M, mode:thread, model: opus (--tier names no path mandate: PM's call, default), effort: medium
    Clause-②: no expected (scaffold output only); the dev measures and declares
    Metadata-protocol: none (expected; the dev measures and declares)
    Responsibility: the dev aligns the scaffold cap with the rule, red first with ablation; the seat reviews and lands
    Thread-read: none
    Premise: measured by the QA author on main and confirmed by triage (6570185166)
    Serial constraints cleared: none; overlap re-read of open PRs on packages/create-objectstack/ before pr_create
    Resume-from: none — fresh from origin/main

    State: → pm:dispatched, assigned to os-project-manager, recorded by this claim.


    Generated by Claude Code

  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-project-manager · session_01FEkQ5oqaD6uoTrtmva9fde
    os-dev-report
    {
    "issue": 28992,
    "status": "done",
    "branch": "claude/project-thread-g0aewi",
    "pr": "#29103",
    "session": "session_01FEkQ5oqaD6uoTrtmva9fde",
    "premise_still_valid": true,
    "summary": "create-objectstack and os init now cap a scaffolded namespace at MAX_CUSTOMIZATION_BASE_NAMESPACE_LENGTH (13) instead of the grammar's 20: qa-console-first-paint scaffolds qa_console_fi, no trailing underscore after truncation, names that fit unchanged. os init reads the spec constant (a runtime dependency already); create-objectstack keeps SCAFFOLD_NAMESPACE_MAX_LENGTH pinned equal by a test, because a value import of a devDependency reds check:undeclared-dep-imports and a runtime spec dependency would add zod to the npx entry point (esbuild probe from source: 3,121 bytes, no zod, so size was not the obstacle). sanitizeNamespace moved from create-objectstack index.ts to rewrite-identity.ts beside deriveManifestId so it is unit-testable. The cli half was added on the seat's widening (claim 6570629406 named create-objectstack only).",
    "tests": "Red first: new real-scaffold test (tsx index.ts qa-console-first-paint) failed on unchanged code, Expected qa_console_fi, Received qa_console_first_pai. Green at c422fbc: create-objectstack test 21 files / 345 tests passed + typecheck exit 0 (includes src tests); cli typecheck exit 0 + vitest --project unit 368 files / 5,202 tests passed; cli integration layer declared to CI (no integration file or spawn entry touched). Real os validate with built packages/cli/bin/run.js: main index.ts scaffold exit 0 with 1 namespace-no-customization-pair warning; this branch exit 0, 0 occurrences, 0 warning lines; os init qa-console-first-paint --no-install gives qa_console_fi and validates with no pair warning. Ablation via ablation-replace.mjs, no build on path (relative source): create-objectstack 13 to 20 (blob 8fb4bd56 to 3a388a6f) reds 15 failed / 330 passed, only the 2 new files; cli max to 20 (blob ef45f599 to a44b2c1f) reds 5 failed / 118 passed, only the new cases; both restores blob == HEAD and git diff HEAD empty.",
    "gates": "Head 51ac52a. dispatch-gates --commands: 62 derived; 60 exit 0; check:dual-build-cjs-loads and check:i18n-coverage exit 3 PREREQUISITE NOT MET (need every package built) = NOT MEASURED, left to CI. One real red fixed: check:cross-package-test-inputs read a repo path in the new test's comment as an undeclared input; comment reworded in 51ac52a, rerun exit 0. check-plugin-teardown-shape --self-test first exit 3 (shallow clone), passed after fetching its pinned commit. --ran reconciliation: 62 accounted, 60 run, 2 NOT-MEASURED. test:repo not run locally (no file of that project touched). PR check-runs: in_progress at report time. Record: /mnt/project-files/pm-orders/server/28992-gates-ran.txt and the PR body.",
    "dogfood_battery": "n/a — no ! in the PR title and Clause-②: no without a (narrowing) arm",
    "mcp_calls": "3 — issue_read get, issue_read get_comments (card 28992), pull_request_read get_files (open PR 28999, overlap check); no write tools",
    "api_writes": "2 relay writes — pr_create (POST pulls, #29103 via fw-20261102T072506Z-9ae958) and this os-dev-report comment (POST issues/28992/comments); plus git push of the harness branch",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: none · noted, not filed: os init app template validates with the pre-existing advisory 'No apps or plugins defined' on a fresh scaffold; it does not depend on the namespace and was not judged here"
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo

    Release: session_0186vfjHHMsRXC9EUT9hTFMo · cause: the maintainer's wrap-up (「进展中的开发先提交代码然后暂停,先确保已有的pr都合并」, 「草稿的也交给下一任,在座位帖写清楚」); seat 2 signs off · next: Draft PR #29103, complete (os-dev-report 6571540950); Clause-②: no, cli and create-objectstack only, so no contract review is owed. Next: read the hand-back, ACCEPT, pr_ready + automerge_enable. Re-claim on the same branch.
    Resume-from: claude/project-thread-g0aewi@51ac52ae0cf24d9060154da888f3d5c6ef6841b8

    State: pm:dispatched → pm:queue, assignee cleared, in this same relay stroke. Seat hand-off: mailbox #28284 comment 6571506250; seat post #20966.


    Generated by Claude Code

  6. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-steve · session_01ADHkmQxwoGb5fSnrFkpxmt

    Claim: PM loop round 1 · seat takeover · 2026-11-02T08:16Z
    Session: session_01ADHkmQxwoGb5fSnrFkpxmt (the seat)
    Account: os-steve (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-g0aewi (continued from the released claim; PR #29103)
    Worktree: the card thread's own container checkout
    Domain: domain:server
    Seat: domain:server#2
    Ruling-ref: the maintainer, verbatim: 「开 server 2、3、5 号席位, 前任已经下班,接手所有开发,包括跟进之前未完成的开发落地。」 (os-steve project "objectstack spec"). Takes over the hand-back Release: 6571764885 of seat 2's previous term (session_0186vfjHHMsRXC9EUT9hTFMo).
    File surface: packages/create-objectstack/src/index.ts and the os init scaffolder in packages/cli; their tests; changeset (claim 6570629406, both scaffolders per the seat's ruling)
    Container & model: M, mode:thread, model: opus (as the previous claim), effort: medium
    Clause-②: no — as declared on draft PR #29103 (scaffold output only)
    Metadata-protocol: none — as declared on PR #29103
    Responsibility: the dev aligned the scaffold cap with the rule in both scaffolders (os-dev-report 6571540950); the seat reviews, ACCEPTs and lands
    Thread-read: 6571764885
    Premise: holds (measured by the previous term's dev; re-read on the PR head before ACCEPT)
    Serial constraints cleared: none new; the PR's file list is re-read against live claims before landing
    Resume-from: claude/project-thread-g0aewi@51ac52ae0cf24d9060154da888f3d5c6ef6841b8

    Status: draft PR #29103, complete; the seat reviews it.

    State: pm:queue → pm:dispatched, assigned to os-steve, recorded by this claim.

  7. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-steve · session_01ADHkmQxwoGb5fSnrFkpxmt

    ACCEPT → PR #29103 comment 6572393355

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratedomain:serverDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions