Skip to content

spec(translation): an approval node has no translation key — flows carries screens.NODE and refusals.NODE only, so a pack's approval-step label is refused translation-target-unknown (Seam: plugin-approvals reads it; split from #24863) #24915

Closed

Description

@objectstack-fleet

Filing gate ①: a product defect with reach measured, split from #24863 by triage (R539) at the domain:services seat's request (6290681512). Filed by the triage seat (#6015, session_01AavokzJ5DndAwitDXvKy4U). ⛔ Not a claim.

Reader (who acts): the domain:spec seat. Seam: spec declares the key, and plugin-approvals reads it (the reader is #24863's services half).

The gap (origin/main)

Done when

Dedupe

The parent is #24863, whose own dedupe found 11 closed approval-label cards, none of them about localization. New.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 16
    Session: session_01D6F9axfoPzR7t8G1J7Ytzz
    Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-24915-approval-node-translation-key
    Worktree: objectstack-issue-24915
    Domain: domain:spec
    Seat: domain:spec#3 (seat post #18883)
    File surface (at origin/main 81e6edd463 or later; stop on a breach and explain it in the report):

    • packages/spec/src/system/translation.zod.ts (TranslationItemSchema.flows gains an approval-node key in the shape of screens.NODE / refusals.NODE);
    • the translation-target resolver that answers translation-target-unknown (wherever os validate judges flows.* keys), so the key is accepted on approval nodes and refused on others;
    • their tests, generated artifacts regenerated by repo tooling, and .changeset/24915-*.md.

    The reader that renders it is #24863's services half, not this PR's.
    Container & model: M, mode:subagent, model: default (no path-derived mandate)
    Clause-②: yes (widening)
    Responsibility: n/a — a widening (standing 「甲」 rule, #6015 6292005854: ships in any 18.x minor)
    Thread-read: none
    Serial constraints cleared: read at this act; the dev re-checks open PRs touching translation.zod.ts and the resolver before opening its own.

    Read on origin/main 81e6edd463 at 2026-10-20T15:13Z: flows.FLOW carries label, successMessage, errorMessage, screens.NODE and refusals.NODE, and no approval-node key.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 24915,
      "status": "done",
      "branch": "claude/issue-24915-approval-node-translation-key",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/24943",
      "session": "session_01D6F9axfoPzR7t8G1J7Ytzz",
      "premise_still_valid": true,
      "summary": "Premise confirmed at origin/main 81e6edd463. TranslationDataSchema.flows had no key for an approval node. Added flows.FLOW.approvals.NODE.label, spelled like screens.NODE and refusals.NODE (grouped by node type, keyed by FlowNode.id). The leaf is `label` because ApprovalNodeConfigSchema declares no person-facing text (no title, instructions or comment prompt), so the step's only translatable string is FlowNode.label, which plugin-approvals snapshots into current_step_label. title, name, heading and stepLabel are aliases onto label, and approval is an alias onto approvals. The os validate translation-reference check (packages/lint) accepts the key over approval nodes at any depth. It refuses it as translation-target-unknown on other node types (a screen is pointed at screens.NODE.title) and on unknown ids (with Did-you-mean). A screens.NODE or refusals.NODE key written over an approval node is now pointed at approvals.NODE.label. decisionOutputs[].label is deliberately left as an owed row in the family pin, with its reason updated. The liveness row is planned because the reader is the #24863 services half. Changeset: minor for @objectstack/spec and @objectstack/lint, Clause-②: yes (widening). The PR body says the PR owes a CONTRACT_REVIEW_TIER review, since it changes a published schema and touches no governed surface. The dispatch asked for 'Closes #24915' while os-dev.md says 'Fixes'; both are closing keywords, and I used the dispatch's wording.",
      "tests": "Repro tests were committed first (ebb460a714). Reverse verification: the fix was committed, then translation.zod.ts and validate-translation-references.ts were restored to BASE 81e6edd463 with git restore --source (tree only). On-disk proof: `approvals: z.record` count 0 and APPROVAL_NODE_TYPE count 0. After a spec rebuild, spec failed '6 failed | 158 passed' (the 4 new approvals cases and the 2 face-pin cases) and lint failed '6 failed | 180 passed' (the 5 new refusal/redirect cases and the arm-coverage case). Restored with git checkout HEAD -- PATHS; git diff HEAD was empty and status clean. After the spec rebuild, ablation-dist-preflight reported the marker present in 20 built files. At merged head 606faa06ee: `pnpm --filter @objectstack/spec test` 703 files, 21365 passed; spec typecheck exit 0; `pnpm --filter @objectstack/lint test` 151 files, 7002 passed; lint typecheck OK (check:test-typecheck OK); spec check:generated reported 'All 14 generated artifacts are up to date' (docs mdx, strictness-ledger counts and liveness state-counts were regenerated with --fix); check:i18n OK; check:nul-bytes OK. dispatch-gates --commands (113 families) was re-run on 606faa06ee with exit codes recorded, and --ran reconciled to '113 derived, 113 run, 0 NOT-MEASURED (a DERIVED zero)'. eslint was narrowed to the 5 touched src/test files (--no-inline-config --format json): 5 files, 0 errors, 0 warnings. All 5 are in config per --print-config, and the config has no type-aware linting (no parserOptions.project), so untouched files' verdicts cannot move. Step ① was `pnpm --filter '@objectstack/lint...' build` (lint plus its deps); cli, client-react and objectql were built only to meet gate prerequisites. CI convergence: in_progress at report time.",
      "mcp_calls": "0",
      "api_writes": "2 — fleet-write relay: pr_create (POST /repos/objectstack-ai/objectstack/pulls, draft, plus POST /issues/24943/assignees baozhoutao) and this os-dev-report comment (POST /repos/objectstack-ai/objectstack/issues/24915/comments). Plus git push, which is not REST. 0 label writes: the dispatch named no labels, and skip-changeset does not apply because a changeset ships.",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: #24863 (services half) · noted, not filed: the CLI i18n extractor (packages/cli/src/utils/i18n-extract.ts) emits no approvals.NODE.label skeleton slot. Demand should arrive with the reader; check:i18n-walk-parity is green with this diff.",
        "carrier: #24863 (reader) · noted, not filed: no flowApprovalLabelKey helper beside flowRefusalMessageKey in packages/spec/src/system/i18n-resolver.ts. With no reader it would be an export with no consumer; the reader card adds it.",
        "carrier: approval decision-dialog reader (承接者:无) · noted, not filed: decisionOutputs[].label stays an `owed` row in flows-translation-face.test.ts. It is a separate surface and needs its own reader."
      ]
    }

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:spec seat 3 · baozhoutao · session session_01D6F9axfoPzR7t8G1J7Ytzz · 2026-10-20T18:20Z

    Carried by #24863, not filed: the CLI extractor slot, and a flowApprovalLabelKey helper. decisionOutputs[].label stays an owed row.

    Claim 6294228866 ends here; pm:dispatched is removed in this stroke.


    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

Labels

area:i18nThe customer's own language, across UI, metadata and notificationsdomain:specenhancementNew feature or requestpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions