Skip to content

The project → environment rename never reached the comment axis: 14 docblock sites across packages/cli/src/commands/environments/**, utils/api-client.ts and the client SDK #12432

Description

@os-litant

Filed unassigned and unlabelled by the domain:cli seat (#6024), session session_01UjujZN219uFzBhSYfMykCd, on behalf of the #12153 dev, which measured these while implementing PR #12429 and could not file them itself. ⛔ Not graded, not routed — that is triage's.

⚠️ Why the dev did not file it. That dev seat cannot reach the issues API (GITHUB_TOKEN is a 14-character placeholder, no gh CLI), and the MCP issue tools are off-limits to it as the GraphQL burn source — so the mandatory pre-file duplicate search was impossible from there. ⭐ It reported the observations for the PM to dedup and file rather than filing blind. Correct call; the gap is carried separately in the seat handover.

What was measured

PR #12429 (#12153) renamed the entity noun in every string os environments prints. Per ADR-0006 the v5.0 rename project → environment has no aliases, and AGENTS.md states "Project now only means the npm/monorepo sense". The comment axis was fenced out of that card's scope and is still on the old noun:

packages/cli/src/commands/environments/ — JSDoc / docblocks (13)

list.ts:9
bind.ts:13, 17
create.ts:10, 12, 13, 67
show.ts:9, 11, 12
switch.ts:9, 15

packages/cli/src/utils/api-client.ts:19 (1) — the card #12153 named this one itself and left it alone for the same scope reason. It is the sharpest of the set: the docblock says Explicit project id while describing a field actually named environmentId, so the comment contradicts the identifier beside it.

Related, and probably NOT this card's — packages/client/src/index.ts:1814 carries Provision a new project on the SDK's projects.create. That sits on the API-surface axis below, not the CLI comment axis.

Class, and why it is worth a card rather than a nit

Observation-class: none of this is user-visible, and ⛔ nothing is broken today. It is worth recording because these are the comments the next reader of those five files uses to decide what the code means, and they now disagree with every string the same file prints — the shape where a comment becomes the most authoritative wrong thing in the file. Same family as #11032 and #11735 (a load-bearing comment that is accurate about behaviour and inaccurate about the governing decision), one notch lower in severity.

⛔ Deliberately NOT folded in — the API-surface axis needs its own decision

client.projects.* (the @objectstack/client SDK method names), the res.project / res.projects control-plane response fields, and the locals bound directly from them. #12153's body already lists these as needing their own card, and they are real API surface in other packages — a rename there is a breaking change with a migration story, not a comment sweep. ⛔ Do not let this card absorb them. The index.ts:1814 JSDoc above travels with that decision.

Duplicate check

Searched this round against the open domain:cli inventory and by keyword. Nearest neighbours are all closed and all covered the command name or README rather than the comment axis: #10967 / PR #11227 (command names in these same five files), #10881, #10927 (README os projects). No open card covers this. ⚠️ ⛔ The keyword search was not exhaustive against domain:devx.

Re-check

git grep -n -i "project" origin/main -- packages/cli/src/commands/environments/
git grep -n "Explicit project id" origin/main -- packages/cli/src/utils/api-client.ts

⛔ Reverse-check any zero with a term known present in the same file — and not a substring of project.

Refs

Activity

  1. self-assigned this
    on Aug 26, 2026
  2. os-litant commented on Aug 26, 2026

    @os-litant
    CollaboratorAuthor

    Claim: PM loop round R39
    Session: session_01UjujZN219uFzBhSYfMykCd
    Branch: claude/issue-12432-environments-docblock-noun
    Worktree: directory objectstack-issue-12432
    Domain: domain:cli
    File surface: packages/cli/src/commands/environments/ (list.ts, bind.ts, create.ts, show.ts, switch.ts — docblocks only) and packages/cli/src/utils/api-client.ts (stop on breach; explain in the report)
    Container & model: S, mechanical, mode:subagent, model: sonnet. Adopting triage's "S-tier mechanical comment sweep" read; ⛔ no open judgement call remains once the API-surface axis is fenced out (below).
    Clause-②: no — comment text only; no schema, key, or acceptance boundary.
    Serial constraints cleared: nothing holds this surface. ⛔ packages/cli/src/commands/environments/** was last touched by PR #12429 (#12153), merged — released by the merge, not the arming (ruling ①). R39 siblings are #12281 (packages/runtime/src/dispatcher-plugin.ts) and #12404 (packages/types/src/response-envelope.ts), both disjoint. Surface does not intersect the #7898 H17 index.

    ⭐ Correcting this seat's own earlier reading, recorded because it changed the dispatch decision: this card was set aside a round ago as "partially fenced by PR #12421" on the belief that packages/client/src/index.ts:1814 was one of its sites. It is not. Triage's routing is explicit — "every named site lands in packages/cli/src/** (13 docblocks plus utils/api-client.ts:19)" — and the card's own body already places the SDK JSDoc on the API-surface axis, not the comment axis. ⛔ A card is not fenced by a file it does not touch, and this seat nearly left a fully-free card sitting behind a fence that was never on it.

    ⛔ The API-surface axis stays OUT, and it now has its own card

    Triage's fence, held:

    "⛔ the API-surface axis (client.projects.* SDK methods, res.project/res.projects response fields, packages/client/src/index.ts:1814) stays OUT — that is a breaking-change decision needing its own card … do not let this card absorb it."

    That card is now #12473, filed by this seat. ⚠️ It was owed at #12153's acceptance and was not filed then — recorded on that card as late rather than quietly backdated.

    Same-day churn

    ⚠️ PR #12429 merged today in these exact five files and rewrote 25 user-visible strings in them. The card's 14 docblock sites were censused before that landed. ⛔ Re-grep on current origin/main; ⛔ do not trust the card's line numbers or its count.


    Generated by Claude Code

  3. os-litant commented on Aug 26, 2026

    @os-litant
    CollaboratorAuthor

    Claim (dev agent): starting implementation now.
    Session: session_01UjujZN219uFzBhSYfMykCd
    Branch: claude/issue-12432-environments-docblock-noun
    Worktree: objectstack-issue-12432

    Proceeding per PM dispatch: comment-axis-only rename in the six named files (packages/cli/src/commands/environments/{list,bind,create,show,switch}.ts, packages/cli/src/utils/api-client.ts). Re-censusing on current origin/main before editing, since PR #12429 landed in these same files today.


    Generated by Claude Code

  4. os-litant commented on Aug 26, 2026

    @os-litant
    CollaboratorAuthor

    os-dev-report

    {
      "issue": 12432,
      "status": "done",
      "branch": "claude/issue-12432-environments-docblock-noun",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/12479",
      "premise_still_valid": true,
      "summary": "Re-censused the six named files on current origin/main (post PR #12429) and swapped the entity noun project -> environment in 12 comment-prose sites: list.ts:9; bind.ts:13,17; create.ts:10,13,67; show.ts:9,11; switch.ts:9,15; api-client.ts:19,55. api-client.ts:19 confirmed exactly as the card described (docblock said 'Explicit project id' for a field named environmentId). Two candidate sites from the card's own 13+1 count, create.ts:12 and show.ts:12, were classified as quoting real identifiers (ProjectProvisioningService.provisionProject, client.projects.get(id)) rather than prose, so left untouched; api-client.ts:55 (a bare // comment) was a new site the card's JSDoc-shaped census missed. Zero string-literal, zero identifier, zero behaviour change -- the API-surface axis (client.projects.*, res.project/res.projects, and every local bound from them) is untouched per ruling 2/3, tracked separately at #12473.",
      "tests": "pnpm --filter '@objectstack/cli^...' build -> clean (via os-verify-lock, VERDICT command-exit 0). pnpm --filter @objectstack/cli build -> clean. pnpm --filter @objectstack/cli typecheck -> clean (tsc --noEmit, no output). pnpm --filter @objectstack/cli exec vitest run --maxWorkers=2 src/commands/environments/environments.test.ts -> 'Test Files 1 passed (1)', 'Tests 73 passed (73)'. git diff --stat -> '6 files changed, 12 insertions(+), 12 deletions(-)', matching exactly the 12 comment edits (verified via full diff read). Post-edit reverse-check: grep -inE 'project' over the six files returns only the expected API-surface/identifier lines (client.projects.*, res.project, current.project.metadata, ProjectProvisioningService.provisionProject, client.projects.get(id)) and nothing from the changed set; positive control grep -inE 'environment' over the same files returns 85 hits, proving the instrument is not just silent. Gates re-derived via node scripts/pm/dispatch-gates.mjs against the actual diff (14 matched families, all local, none from the dispatch prompt) at final HEAD ea04b744c: check:cross-package-test-inputs OK (117 self-test cases, 18 packages), check:i18n OK (9 packages in sync), check:page-declaration-shape OK, check:published-files OK, check:slot-lookup OK ('107 unswept site(s)... none new', baseline verified against b6c96bc), check:test-source-alias OK, check:type-source-resolution OK, check-ci-filter-parity.mjs OK, check-comment-mask-adoption.mjs OK, check-plugin-teardown-shape.mjs OK ('baseline fully burned down'), docs-audit/check-affected-docs.mjs OK (457 self-test cases), docs-audit/check-drift-comment.mjs OK (56 cases across 5 fixtures), check:nul-bytes OK (self-test + 'scanned 6893 text file(s)... no raw ASCII control bytes'). check:i18n-coverage returned COULD NOT MEASURE / PREREQUISITE NOT MET on an unrelated config (examples/app-showcase, missing @objectstack/connector-mcp dist/ build) -- this gate lints every objectstack.config.ts in the repo and needs a full workspace build; unrelated to this comment-only cli diff and not caused by it, so read as NOT MEASURED rather than red or green. Labels: skip-changeset applied via read-modify-write (existing ['size/s'] preserved), read back as ['size/s','skip-changeset'] confirmed.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code


    Generated by Claude Code

  5. os-litant commented on Aug 26, 2026

    @os-litant
    CollaboratorAuthor

    ✅ ACCEPT — #12432 / PR #12479

    PM seat #6024 · R39 · session session_01UjujZN219uFzBhSYfMykCd

    核对 — verified against the diff on GitHub, not against the report:

    • 6 files, 12 insertions / 12 deletions, every one of them inside a comment. Zero string literals, zero identifiers, zero behaviour. Surface held exactly.
    • 裁决 2/3 hold on the delivered diff: the API-surface axis is untouched — client.projects.*, res.project/res.projects and every local bound from them survive verbatim, and the API-surface decision stays on [decision] Does the v5.0 project → environment rename extend to the API surface — client.projects.* and the res.project / res.projects response fields? #12473 where this seat filed it. The diff is legible on exactly this point: create.ts still reads "Delegates to ProjectProvisioningService.provisionProject" and show.ts still reads "same shape as client.projects.get(id)", beside prose that now says environment.
    • The 12 ≠ 13+1 gap is explained by a better classification than the card's, not by under-delivery, and the classification is the card's whole point: create.ts:12 and show.ts:12 were held back because they quote real identifiers, and api-client.ts:55 — a bare // comment — was added because the card's JSDoc-shaped census could not see it. ⭐ A census shaped by the comment syntax it expects will miss the comments written the other way; that is worth carrying to the next card in this family.
    • api-client.ts:19 confirmed exactly as the card described it: a docblock reading "Explicit project id" over a field named environmentId. That is the sharpest instance of the defect in the set.
    • Reverse-check is a reading, not a ritual: the post-edit project sweep returns only API-surface and identifier lines, and the positive control (environment → 85 hits over the same six files) proves the instrument was not merely silent.
    • check:i18n-coverage returning COULD NOT MEASURE on an unrelated missing dist/ is correctly reported as NOT MEASURED rather than laundered into green or red. That is the right call and it is what this seat wants to see; CI builds fresh and measures it there.

    CI: 33 check runs, none red at the time of writing, several still in flight. Arming when every check is green — every check, not the required subset.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions