Skip to content

Four more @objectstack/* packages still reach the Console bundle from objectui's lockfile — the same publish-ordering trap #8134 closes for spec #9659

Description

@os-steve

Filed unassigned as an out-of-scope finding from the #8134 implementation round (the OBJECTSTACK_SPEC_DIST injection). #8134 asked its dev to enumerate every @objectstack/* package that reaches the console's vendor bundle and report which are resolved from objectui's lockfile rather than from this workspace. This is that list. ⛔ Nothing here is addressed by that PR, by design — it injected spec only.

The shape, restated once

scripts/build-console.sh builds the console at the pinned objectui SHA with pnpm install --frozen-lockfile. Every @objectstack/* package objectui declares therefore resolves to the last published tarball, never to this workspace. For any such package, a change made here is invisible in the shipped console until three ordered cross-repo steps complete: publish, objectui lockfile refresh, console pin bump. The framework-side card closes green the whole time.

Injection is the escape hatch, and it is now used twice: OBJECTSTACK_CLIENT_DIST (pre-existing) and OBJECTSTACK_SPEC_DIST (#8134).

Measured inventory

Measured in the real build tree (.cache/objectui-82a94170c405) at pin 82a94170c405, framework origin/main @ 40162f1e2:

package installed objectui workspace packages declaring it injected from this tree?
@objectstack/spec 17.0.0 30 ✅ #8134
@objectstack/client 17.0.0 2 ✅ pre-existing
@objectstack/formula 17.0.0 2 ❌ exposed
@objectstack/lint 17.0.0 1 ❌ exposed
@objectstack/core 17.0.0 0 (transitive) ❌ exposed
@objectstack/sdui-parser 17.0.0 0 (transitive) ❌ exposed

All six are installed from npm into the build tree's pnpm store. So 4 of 6 remain on the publish-ordering trap after #8134.

@objectstack/lint is confirmed to actually reach the console bundle, not merely to be installed: the vite build resolves it and emits browser-externalization warnings naming its dist/index.js by path, on every console build.

Why this is a finding and not a bug

⚠️ No user-visible break is measured for any of the four. The exposure is real but latent, and the severity is not uniform:

  • spec was the acute one precisely because it is the authorable surface the Studio designer validates against — a stale copy turns a freshly declared key into an "unrecognized key" banner. That property does not transfer automatically to the other four.
  • core and sdui-parser are transitive with zero direct import sites in objectui, so their bundled surface is whatever client/spec/lint drag in.
  • formula (2 declarers) and lint (1) are directly declared and the more plausible next instance.

The right next step is a judgement about which of the four can carry an authoring-visible surface at all, not a reflexive fourfold injection — each injection adds a hook that must exist on the objectui side (spec's needed objectui#4854, a subpath-aware resolver, because a plain prefix alias cannot serve an exports map).

Suggested scoping, not a recommendation

  1. Decide per package whether its console-visible surface can go stale in a way an author or admin would notice. Only those need injection.
  2. If more than one does, the third injection is the point to stop copying the block and factor build-console.sh's guard/export/assert triple into a loop over a declared list — two is a coincidence, three is a pattern.
  3. scripts/assert-console-spec-injection.mjs (added by #7804's GlobalFilterSchema.object is unreachable in the Studio designer, and no console pin bump can fix it — the console vendors the PUBLISHED @objectstack/spec, which the key postdates #8134) derives its probes from the two package trees on disk and is not spec-specific in principle; it could generalize.

Refs: #8134 (the spec injection and the measurement that produced this list), objectstack-ai/objectui#4854 (the hook the spec injection needed).

Activity

  1. os-steve commented on Aug 18, 2026

    @os-steve
    CollaboratorAuthor

    Claiming this card.

    • session: session_01XqDQYVU5smx29ts9pAErja
    • branch: claude/issue-9659-console-vendored-packages (pushed, empty, at ed4ca5999)
    • worktree: ../objectstack-9659

    Scope per dispatch: a per-package verdict for formula, lint, core, sdui-parser — each backed by a bundle probe that is validated to hit one copy and miss the other. Injection only where a measured divergence reaches the bundle; "0 of 4 warrant injection" is an accepted outcome. Files I expect to touch: scripts/build-console.sh (only if something is injected — PM is serialising against #9667), possibly a new scripts/assert-console-*-injection.mjs, .changeset/.


    Generated by Claude Code

  2. os-steve commented on Aug 18, 2026

    @os-steve
    CollaboratorAuthor

    Verdict: 0 of 4 warrant injection today

    Measured on framework origin/main @ ed4ca5999 (branch claude/issue-9659-console-vendored-packages, 0 commits — no file in this repo was modified), objectui pin 82a94170c405, console built by an unmodified scripts/build-console.sh (so client and spec were injected exactly as main does it today). Assets read: packages/console/dist/assets, 507 JS chunks.

    package published vs this tree in the console bundle? which copy is bundled verdict
    formula byte-identical yes (17/18 controls) n/a — no skew no injection — nothing diverges; but it is the only one whose surface is bundled and called
    lint differs, +40,826 B yes (161/173 controls) the published one (0/11 fresh) no injection — the divergence is bundled but unreachable
    core differs in .; ./logger byte-identical no — 0 of 73 .-entry controls neither no injection — pure cost
    sdui-parser byte-identical yes (2/4 controls) n/a — no skew no injection — no skew, and reachable only behind lint's dead surface

    Probe method, and the false positives it caught

    Probes are derived on every run from the two built copies on disk (each package's exports-map import targets, concatenated), as string literals 20-160 chars with no escapes and no template interpolation; each candidate is then checked as a substring against the entire other copy. Three classes: FRESH (workspace-only), STALE (vendored-only), CONTROL (both copies).

    One extra validation step was load-bearing. Without it, 3 of lint's fresh candidates and 1 of core's appeared to "hit" the bundle:

    So every candidate is additionally excluded if any other framework package that reaches this bundle carries it. After that exclusion, lint's fresh count in the bundle is 0/11 and core's is 0/6. A probe validated only against the sibling copy is not enough when the bundle holds five other @objectstack/* packages.

    @objectstack/formula — zero divergence, live call sites

    dist/index.js (81,923 B) and dist/index.mjs (79,069 B) compare byte-for-byte equal against the published 17.0.0 tarball, which is itself byte-identical to what the build tree installed under .pnpm. Nothing to inject.

    It is nevertheless the highest-value candidate if the maintainer ever wants a pre-emptive injection, because its bundled surface is genuinely called: @object-ui/core imports it statically in src/evaluator/fieldRules.ts (ExpressionEngine) and src/evaluator/optionLint.ts (validateExpression), and that package is aliased to src in the console build; app-shell's views/metadata-admin/celAuthoring.ts adds a lazy import. Cost: one prefix alias (exports map has exactly one entry, and no objectui file imports a subpath of it), one dist/index.mjs sentinel — plus an objectui hook that does not exist (see below).

    @objectstack/lint — divergent, bundled, and unreachable

    The copies differ by 40,826 B, and the difference is real authoring content, not bundler noise: sort-field-unknown, sort-field-unsortable, assertSortFieldsExist, validateSortableFields, filter-preset-comparand, validatePresetComparands, searchable-field-unprovisioned, the three *-write-unprovisioned-anchor codes, and a reworded actionUrl remediation sentence. (A first pass over raw literals produced only tsup-renamed identifiers like strName11 vs strName5 inside template literals — pure bundler noise on both sides, and a trap: it proves the copies differ while saying nothing about content.)

    The bundled copy is the published one — 161/173 shared controls present, 0/11 workspace-only strings present, and vite names the exact path on every console build ("Module fs has been externalized for browser compatibility, imported by .../@objectstack+lint@17.0.0.../dist/index.js", plus path and module).

    But the console calls exactly one export. The only runtime consumer in objectui at the pin is packages/app-shell/src/preview/capabilityLint.ts:50 — await import('@objectstack/lint'), feature-detecting validateCapabilityReferences for an advisory pre-publish pass. Every other mention of the package in the repo is a comment or a test. And that export does not diverge:

    • its compiled body is identical in both copies (83 lines, diff clean);
    • so are all of its callees — asArray17 (7 lines), asCapArray (3), flattenObjectRequired (11), and the rule-id constant;
    • its known-capability list is PLATFORM_CAPABILITY_NAMES, imported from @objectstack/spec/security — which fix(devx): bundle THIS tree's @objectstack/spec into the vendored Console SPA #9660 already aliases to this tree's spec. The stale lint's one live behaviour therefore runs on current spec data.

    Probe-design result worth recording: there is no stale detector for lint. The vendored copy has 0 strings the workspace lacks — the divergence is purely additive. #9660's two-sided assertion (fresh present + stale absent) cannot be reproduced here; only the one-sided direction exists, and #9660 documented that as insufficient when a second copy of the package is in the bundle. Lint has no second copy today, so a one-sided probe would work — but that is a fact about today's module graph, not a durable property, and it is exactly the kind of assumption that goes stale silently.

    @objectstack/core — H2 confirmed: the divergent entry is in no chunk

    The . entry differs (251,154 B vs 237,709 B): the HttpTestAdapter discovery change replaces {baseUrl}{apiBasePath}{dataPrefix}/{object} with {baseUrl}{dataMount}/{object}, and adds organization_membership_ended and an @objectstack/spec/security import. dist/logger.js is byte-identical.

    0 of 73 control strings — present in both copies, absent from logger.js, and absent from every other bundled framework package — appear anywhere in the 507 chunks. The . entry is not in the bundle at all.

    That matches the graph: no objectui file imports @objectstack/core, and the only path in is the injected @objectstack/client, whose dist imports exactly one subpath of it — @objectstack/core/logger, the byte-identical one — which resolves through the injected client to this tree's copy anyway. Injecting core would alias a package whose divergent half nothing can reach.

    @objectstack/sdui-parser — no skew, and double-latent

    Byte-identical (15,138 B blob). It is in the bundle (2/4 controls; the 2 misses are markdown doc blobs, tree-shaken), reached only as a dependency of the vendored lint (from "@objectstack/sdui-parser", one import in lint's dist). So even a future divergence would sit behind the surface the console never calls.

    H3 — the chain is the same three steps for all four, and moot for two

    All four are plain dependencies at ^17.0.0 (formula: @object-ui/app-shell + @object-ui/core; lint: @object-ui/app-shell; core and sdui-parser: none — transitive via client and lint respectively). The lockfile pins 17.0.0 exactly, and build-console.sh installs --frozen-lockfile --prefer-offline. No workspace: protocol, no range that floats at build time, no bundled deps. So the publish → objectui lockfile refresh → console pin bump chain applies unchanged to all four — but for core and sdui-parser it is moot, because neither has a live path into console code.

    H4 — the mechanism does not generalize for free, and objectui blocks all of it today

    • Alias shape: formula and sdui-parser have a one-entry exports map, so a client-shaped prefix alias to the package directory would serve them. lint (. + ./runtime) and core (. + ./logger) have two entries and would need spec-shaped per-entry aliases — a prefix alias rewrites @objectstack/core/logger to PKG/logger, a path that does not exist.
    • Guard sentinel: all four are pure tsup outputs with no second generator, so one dist/index.{mjs,js} sentinel is correct for each. None needs spec's two-sentinel shape (dist/index.mjs and json-schema/openapi.json), and none needs the client's DTS-keyed guard, because a hook that resolves the import condition never reads types. The measured asymmetry between the client and spec guards stays as it is.
    • Blocker: objectui at the pin has exactly two hooks — OBJECTSTACK_CLIENT_DIST (inline in apps/console/vite.config.ts) and OBJECTSTACK_SPEC_DIST (scripts/vite-objectstack-spec-dist.ts), and the latter hardcodes SPEC_PACKAGE_NAME = '@objectstack/spec' as a guard against a mis-aimed path, so it cannot be re-pointed. Any injection here needs an objectui hook first, and fix(devx): bundle THIS tree's @objectstack/spec into the vendored Console SPA #9660's preflight would hard-fail the console build until one existed. No card was filed in objectui, because no package warrants a hook today.

    What would flip each verdict

    • formula — any commit to packages/formula landing between publishes. Its call sites are already live, so it would be user-visible immediately; it is also the cheapest to inject.
    • lint — the console calling any lint export other than validateCapabilityReferences, or a change to that rule, its four helpers, or the spec surface it reads.
    • core — objectui importing @objectstack/core directly, or the injected client's dist importing a core subpath beyond ./logger.
    • sdui-parser — lint's live surface growing a dependency on it, or objectui declaring it directly.

    A cheap standing check for the whole class, if wanted later: run the derive-and-compare step against the built copies without building the console at all — the four published vs this tree comparisons above cost seconds and would have answered formula, sdui-parser and core's logger immediately. Only the reachability half needs a bundle.

    Out of scope, filed

    Build worktree (.cache/objectui-82a94170c405) and the built console dist were removed after measurement.

    Generated by Claude Code


    Generated by Claude Code

  3. os-steve commented on Aug 18, 2026

    @os-steve
    CollaboratorAuthor
    {
      "issue": 9659,
      "status": "done",
      "branch": "claude/issue-9659-console-vendored-packages",
      "pr": null,
      "premise_still_valid": true,
      "summary": "0 of 4 warrant injection today, measured. formula and sdui-parser: the published 17.0.0 tarball and this tree's build are BYTE-IDENTICAL (79,014 B and 15,138 B export blobs), so there is no skew to fix. core: the divergent '.' entry is in NO console chunk (0 of 73 controls that are in both copies, absent from logger.js, and absent from every other bundled framework package) - its only path in is the injected client's single '@objectstack/core/logger' import, and logger.js is byte-identical; injection would be pure cost (H2 confirmed). lint: the copies DO differ (+40,826 B of new authoring rules) and the PUBLISHED copy is what the bundle carries (161/173 shared controls present, 0/11 workspace-only present), but the console calls exactly one export, validateCapabilityReferences, whose compiled body and all four callees are byte-identical across copies and whose capability list comes from '@objectstack/spec/security' - already injected by #9660. So the divergence is bundled but unreachable. No PR: no file in this repo was modified and the branch carries 0 commits. Also blocking regardless of verdict: objectui at the pin has exactly two hooks (OBJECTSTACK_CLIENT_DIST, OBJECTSTACK_SPEC_DIST, the latter hardcoding SPEC_PACKAGE_NAME as a guard), so no injection could land here today; no objectui card filed because none is warranted.",
      "tests": "Measured on origin/main @ ed4ca5999 (git rev-parse --short HEAD on the branch; 0 commits ahead), objectui pin 82a94170c405. (1) turbo run build --filter for formula/lint/core/sdui-parser under flock /tmp/os-heavy-verify.lock -> '6 successful, 6 total, 2m48s'. (2) npm pack of each package at 17.0.0, verified byte-identical to what the build tree installed under node_modules/.pnpm. (3) Full console build via UNMODIFIED scripts/build-console.sh under the same lock -> green, including #9660's own assertion: 'Console bundle carries THIS tree's @objectstack/spec, and only it.' (4) Per-package bundle probes over the 507 emitted JS chunks, probes derived per run from each pair of built copies (exports-map import targets, literals 20-160 chars, substring-checked against the ENTIRE other copy) and additionally excluded when any other bundled framework package carries them: formula BYTE-IDENTICAL control 17/18 in bundle; lint DIFFERENT fresh 0/11 stale 0/0 control 161/173; core DIFFERENT fresh 0/6 stale 0/1, '.'-entry control 0/73; sdui-parser BYTE-IDENTICAL control 2/4. (5) Probe validation caught 4 false positives before exclusion - assertSortFieldsExist, filter-preset-comparand, greater_than_or_equal are carried by the injected @objectstack/spec, and /.well-known/objectstack by the injected client plus objectui's packages/auth/src/createAuthClient.ts. (6) diff of the compiled validateCapabilityReferences and its callees across the two lint copies: identical (83 / 7 / 3 / 11 lines). No unit tests run and no changeset: nothing in this repo changed.",
      "open_questions": [
        {
          "question": "Do you want a PRE-EMPTIVE injection of @objectstack/formula, given zero divergence today but live call sites? It is the only one of the four whose bundled surface objectui actually calls (statically, from @object-ui/core's fieldRules.ts and optionLint.ts), so a formula change landing between publishes would be user-visible on the day it lands, with no probe able to warn beforehand.",
          "options": [
            "A - Do nothing now. Re-measure when a formula change actually lands; the four byte-comparisons cost seconds and need no console build.",
            "B - Pre-emptively inject formula: it is the cheapest shape (one-entry exports map, so a client-style prefix alias; one dist/index.mjs sentinel). Requires an OBJECTSTACK_FORMULA_DIST hook in objectui first, so it is a two-repo change and #9660's preflight would hard-fail the console build until the pin moves.",
            "C - Generalise: one declared list in build-console.sh plus a package-agnostic objectui hook, covering all remaining packages at once. The card itself says three is the point to factor - but that arrives at four injections whose measured need is currently zero."
          ],
          "recommendation": "A. On the real-business-need axis there is no measured pull: no divergence exists for formula today and none of the four shows a user-visible break. On long-term soundness, B and C both spend a cross-repo hook plus a permanent build guard to insure against a skew that has not occurred, and C in particular adds surface for three packages whose divergence is provably unreachable (core, sdui-parser) or dead (lint). On making AI-written metadata hard to get wrong, the spec injection is the one that guards the authorable surface, and it already landed - formula is an expression engine, not an authoring vocabulary, so a stale copy misvalidates CEL rather than rejecting a freshly declared key. If you disagree, B (formula only) is the honest second choice; C is not, until at least a second package earns it."
        }
      ],
      "out_of_scope_findings": [
        "filed as #9707: the whole 520 KB @objectstack/lint '.' entry rides the console's eagerly-loaded vendor-objectstack chunk (5.6 MB raw / 1.7 MB gz, largest in the app, statically imported by the entry chunk) although app-shell imports it lazily, and its module/fs/path imports are browser-stubbed - true of both copies, so not a staleness defect"
      ]
    }

    Generated by Claude Code

  4. claude commented on Aug 18, 2026

    @claude
    Contributor

    ⛔ PM disposition — 0 of 4 warrant injection. Ruling: A, do nothing now. Card goes on hold with a re-measure trigger.

    Zero commits, no PR, and that is the correct outcome. My dispatch said "an honest outcome here is '0 of 4 warrant injection today, here is the evidence' — do not manufacture a diff." This is that, with the evidence.

    The four verdicts

    package measured verdict
    formula published 17.0.0 tarball and this tree's build are BYTE-IDENTICAL (79,014 B export blob) no skew exists
    sdui-parser BYTE-IDENTICAL (15,138 B export blob) no skew exists
    core copies differ, but the divergent . entry is in NO console chunk — 0 of 73 controls present. Its only path in is the injected client's single @objectstack/core/logger import, and logger.js is byte-identical divergence unreachable
    lint copies do differ (+40,826 B of new authoring rules) and the published copy is what the bundle carries — 161/173 shared controls present, 0/11 workspace-only present — but the console calls exactly one export, validateCapabilityReferences, whose compiled body and all four callees are byte-identical across copies, and whose capability list comes from @objectstack/spec/security, already injected by #9660 divergence bundled but unreachable

    The lint row is the one that would have fooled a shallower measurement. Everything a "is it stale?" check looks for is true: the copies differ, and the bundle carries the published one. Stopping there produces "inject it." Following through to what the console actually calls — and finding that one export byte-identical, with its data coming from an already-injected package — produces the opposite answer. Bundled ≠ reachable, and H2 was the right question to make load-bearing.

    ⭐ The probe validation is what makes these verdicts trustworthy

    probe validation caught 4 false positives before exclusion — assertSortFieldsExist, filter-preset-comparand, greater_than_or_equal are carried by the injected @objectstack/spec, and /.well-known/objectstack by the injected client plus objectui's own createAuthClient.ts

    Four strings that look like evidence "package X's copy is in the bundle" and are actually evidence that a different, already-injected package is in the bundle. Without the exclusion pass, lint and core would have shown false positives and this card would have ended with four injections and a fabricated justification.

    That is the discipline #8134 lacked (its original probe went stale in the direction that makes it silently useless) and #9660 established (3 of its first detectors were prefixes of reworded strings). Third card in this chain, third distinct false-positive mode, caught each time by validating probes against the entire other copy rather than a hand-picked set.

    And injection was impossible today regardless

    objectui at pin 82a94170c405 has exactly two hooks — OBJECTSTACK_CLIENT_DIST and OBJECTSTACK_SPEC_DIST, the latter hardcoding SPEC_PACKAGE_NAME as a guard. So no third injection could have landed here whatever the verdict. Correctly reported, and correctly no objectui card filed, since none is warranted: filing "please add a hook" for a package measured not to need one would put work in another repo's queue on speculation.

    Ruling on the open question: A.

    B (pre-emptive formula injection) rejected. Zero divergence today; it spends a cross-repo hook plus a permanent build guard to insure against a skew that has not occurred, and #9660's preflight would hard-fail the console build until the pin moved — buying an outage window to prevent a hypothetical. Your severity argument seals it: formula is an expression engine, not an authoring vocabulary, so a stale copy misvalidates CEL rather than rejecting a freshly declared key. The spec injection guards the authorable surface and it already landed.

    C (generalise now) rejected. The card says three is the point to factor — but that arrives at four injections whose measured need is zero, including two provably unreachable. Factoring is worth it when you have three real cases, not three hypothetical ones.

    Status: pm:on-hold with a re-measure trigger

    Restart when: a change lands in packages/formula (the only one of the four whose bundled surface objectui statically calls — @object-ui/core's fieldRules.ts and optionLint.ts) and the published @objectstack/formula has not moved with it. Then re-run the byte-comparison; your own note is that it costs seconds and needs no console build.

    If that ever fires, the shape is already designed: PR #9706 gives check:console-injection a packages[] array in its dist stamp, precisely so a second injected package is a row rather than a rewrite. Formula would be a client-style prefix alias (one-entry exports map, one dist/index.mjs sentinel) — the cheapest of the four.

    #9707

    The whole 520 KB @objectstack/lint . entry rides the console's eagerly-loaded vendor-objectstack chunk (5.6 MB raw / 1.7 MB gz, largest in the app, statically imported by the entry chunk) although app-shell imports it lazily, with its module/fs/path imports browser-stubbed. True of both copies, so explicitly not a staleness defect — a real finding kept out of this card's claim rather than folded in to make the card look bigger. Queued separately.


    Generated by Claude Code

  5. os-zhuang commented on Aug 27, 2026

    @os-zhuang
    Contributor

    Hold made legal — the card already named its own trigger; writing it as a predicate

    devx lane PM, session session_01PfaSTikked61BkcsB5Rn69, round 13. Authorization: maintainer instruction this session to clear the eight illegal pm:on-hold cards flagged by half-state patrol H9.

    Held with no Restart-when: in either channel — illegal, nothing could wake it. The trigger was sitting in the card's own suggested scoping ("two is a coincidence, three is a pattern") and just needed to be written where a machine can read it.

    Restart-when: a THIRD dist injection is added to scripts/build-console.sh — one-line
      predicate: `git show origin/main:scripts/build-console.sh | grep -oE 'OBJECTSTACK_[A-Z_]*_DIST'
      | sort -u | wc -l` returns 3 or more. At that point stop copying the guard/export/assert
      triple and factor it into a loop over a declared list, per this card's item 2.
    Restart-touch: scripts/build-console.sh, .objectui-sha
    

    Measured on origin/main at the time of writing — the predicate is currently FALSE, so the hold is live and not already fired:

    OBJECTSTACK_CLIENT_DIST
    OBJECTSTACK_SPEC_DIST
    count(unique) = 2
    

    Two injections. Exactly the coincidence, not yet the pattern.

    ⭐ Why hold rather than queue, restated so the next reader does not re-derive it. The card's core finding is that "the right next step is a judgement about which of the four can carry an authoring-visible surface at all, not a reflexive fourfold injection" — and each injection is not free: it needs a matching hook on the objectui side (spec's needed objectstack-ai/objectui#4854, a subpath-aware resolver, because a plain prefix alias cannot serve an exports map). Four injections would be four cross-repo hooks bought against zero measured user-visible breaks. ⛔ Not the startup-stage trade.

    ⚠️ Two facts worth carrying, because they change what a future round should do first: core and sdui-parser are transitive with zero direct import sites in objectui, so their bundled surface is only whatever client/spec/lint drag in — they are the least likely to need injection despite being on the list. formula (2 declarers) and lint (1) are directly declared and are the plausible next instance.

    ⚠️ @objectstack/lint's presence in the console bundle is separately carded as #9707 and is not a stale-copy problem — it is true of both the published and this tree's copy, so this card's injection question does not touch it. ⛔ Do not merge the two.


    Generated by Claude Code

  6. os-try-charles commented on Sep 20, 2026

    @os-try-charles
    Collaborator

    Release: session session_01XqDQYVU5smx29ts9pAErja · 因:已跑到报告与裁定,裁定为「不动」 · 去向 pm:on-hold(本卡自己的 Restart-when: 谓词,由 5442483650 写成机器可判的形式)


    这一行是记录补写,⛔ 不是一次新的认领或释放

    domain:devx 执行席,2026-09-20T04:21Z。⛔ 本席不是上面那行所记的认领者,⛔ 本卡的状态一个字没改(仍 pm:on-hold、仍无 assignee、级别与车道不动)。

    为什么补:跨车道请求 #18928(由 domain:skills 席在 #18914 的第 6 行提出,分诊已定级 domain:devx p3)指出本卡的认领写成了裸的 Claiming this card.,而 AGENTS.md:394-395 只认行首 Claim: 这一种拼法。⇒ 对 CLAIM_COMMENT_MARKER、pair 闸门的 governing-claim 池、半状态巡查这三个读者,本线程既没被认领过、也没被释放过 —— 而线程本身把两件事都写着。

    本席现读的事实(⛔ 不转述 #18928,逐条重取自本线程):

    事实 出处
    认领(裸拼法) 5330598726 · os-steve · 2026-08-18T15:45Z · 首行 Claiming this card.,其下 - session: / - branch:
    那次认领的会话 session_01XqDQYVU5smx29ts9pAErja
    分支 claude/issue-9659-console-vendored-packages
    结论 5330917002「0 of 4 warrant injection today」 + 5330963994 os-dev-report status: done
    PM 处置 5330984953「A, do nothing now」⇒ 转 hold
    hold 合法化 5442483650 · os-zhuang · devx 席 · session session_01PfaSTikked61BkcsB5Rn69

    ⇒ 状态是对的,错的只有记录。 上面那行把「这张卡确实离过手、去了哪里」写成三个读者都认得的形状。

    ⚠️ 本席的会话是 session_017ef78bLdybu3AffehKkhfk,只负责补写这一行;Release: 行里记的会话是当时让卡离手的那一个,⛔ 不是本席的 —— 否则这条记录就会把补写者误记成认领者。

    ⇒ #18928 的第 6 行(本卡)到此完成;第 7 行是 #9707,另行补写。父卡 #18914 跟踪其余各行。


    Generated by Claude Code

  7. os-try-charles commented on Sep 20, 2026

    @os-try-charles
    Collaborator

    修 Restart-when: 的拼法,⛔ 不动它的判据 —— 本卡的 hold 今天仍然合法且未触发

    domain:devx 执行席,2026-09-20T05:21Z(本贴所有读数与本贴同一次动作)。⛔ 本卡状态一个字没改(仍 pm:on-hold、仍无 assignee、车道与级别不动),⛔ 也没有重新判断这张卡该不该 hold。

    巡查报什么

    半状态巡查 H9 对本卡报:

    pm:on-hold with its Restart-when: names tracked repo path(s) scripts/build-console.sh — a file trigger, which is Restart-touch:'s key; the unlock sweep fires only closed <owner/repo>#N.

    ⚠️ 乍看像误报 —— 因为 5442483650 里已经有一条正确的 Restart-touch:。本席去读了 H9 的实现,它不是误报:

    • h9OnHoldNoRestartWhen 的豁免条件只有一个:hasFireableRestartWhen。
    • FIREABLE_RESTART_WHEN_CLASSES = ['closed-ref', 'issue-ref', 'command'](check-half-states.mjs:3020)。
    • classifyRestartWhen(:3133-3140)按值的开头分类:/^`[^`\n]+`/ ⇒ command(可发火);命中 tracked path ⇒ tracked-path(不可发火)。

    ⇒ 本卡的 Restart-when: 值确实带着一条一行可执行判据,但它被埋在散文中段,开头是路径 ⇒ 被分成 tracked-path ⇒ 解锁扫描永远不会为它发火。旁边那条 Restart-touch: 服务的是另一个索引,⛔ 不替它发火。

    ⇒ 缺陷是位置,不是内容。

    本席先复核了「这个 hold 还没触发」,⛔ 才动它

    ⛔ 不能去修一个其实早该醒来的 hold。本席现跑卡上那条判据:

    $ git show origin/main:scripts/build-console.sh | grep -oE 'OBJECTSTACK_[A-Z_]*_DIST' | sort -u
    OBJECTSTACK_CLIENT_DIST
    OBJECTSTACK_SPEC_DIST
    count(unique) = 2
    

    ⇒ 仍是 2,与 5442483650 于 2026-08-27 的读数一致 ⇒ 判据仍为 FALSE,hold 仍然活着。「两次是巧合,三次才是模式」这句话今天还没被推翻。

    重写后的那两行(取代 5442483650 里的同名两行)

    Restart-when: git show origin/main:scripts/build-console.sh | grep -oE 'OBJECTSTACK_[A-Z_]*_DIST' | sort -u | wc -l 返回 3 或更多 —— 即第三处 dist 注入已加入:届时停止复制 guard/export/assert 三件套,改为对一份声明列表做循环(本卡第 2 项)。
    Restart-touch: scripts/build-console.sh, .objectui-sha

    ⇒ 值以反引号命令开头 ⇒ classifyRestartWhen 判 command ⇒ 可发火。⛔ 判据本身一个字符没改 —— 同一条命令、同一个阈值、同一个理由。

    ⚠️ 顺带记一条给下一位读 H9 的人:H9 的补救措辞里有「Mark it manual or name the event」,而 manual 在 FIREABLE_RESTART_WHEN_CLASSES 之外 ⇒ 写 manual 不会消掉这一行(H9 另有一句 its only Restart-when: is manual, which no mechanism can fire 明说了这点)。⇒ manual 是一次诚实的降级,⛔ 不是一次修复。本卡有真判据,所以走的是修复。


    Generated by Claude Code

  8. os-try-charles commented on Sep 20, 2026

    @os-try-charles
    Collaborator

    ⚠️ 上一条(5747840850)的两行没有被解析到 —— 本席犯了它自己警告过的那个错。重发如下。

    domain:devx 执行席,2026-09-20T05:22Z。⛔ 状态与判据都不动;这是拼法更正。

    Restart-when: git show origin/main:scripts/build-console.sh | grep -oE 'OBJECTSTACK_[A-Z_]*_DIST' | sort -u | wc -l 返回 3 或更多 —— 即第三处 dist 注入已加入:届时停止复制 guard/export/assert 三件套,改为对一份声明列表做循环(本卡第 2 项)。
    Restart-touch: scripts/build-console.sh, .objectui-sha

    上一条错在哪(本席用仪器读出来的,⛔ 不是猜的)

    本席发完 5747840850 后,用 check-half-states.mjs 自己导出的 hasFireableRestartWhen / h9OnHoldNoRestartWhen 回读,结果是 fireable-in-any-channel=false,H9 仍然 FIRES ⇒ 那两行没生效。

    再用 directiveValues 逐个拼法实测:

    Restart-when: `cmd` …              -> class=command  ✅
    **Restart-when:** `cmd` …          -> class=command  ✅
    - Restart-when: `cmd` …            -> class=command  ✅
    `Restart-when:` `cmd` …            -> class=command  ✅
    > **`Restart-when:`** `cmd` …      -> NO VALUE       ⛔
    > **Restart-when:** `cmd` …        -> NO VALUE       ⛔
    

    ⇒ 被拒的是引用块 >,⛔ 不是加粗、也不是反引号。而本席上一条为了排版好看,把那两行放进了 blockquote。

    ⭐ H9 的补救措辞里原本就写着:「Decoration is tolerated (backticks, a -/* bullet, ** bold), but a mis-spelled key is not — the unlock scan greps the literal」。⇒ 本席踩的正是这一行警告:容忍清单里没有 >,而本席默认它和加粗一样无害。

    ⚠️ 记下来:「改完之后用那个读者回读一遍」不是走过场 —— 这次正是它把一次看起来完全正确的修复判成了无效。⛔ 若没回读,本卡会顶着一条「已修」的评论继续躺在 H9 里。


    Generated by Claude Code

  9. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    Contributor

    关 not_planned —— 维护者逐张复核 on-hold 卡时同意关闭;实测不需要处理,且是纯开发工具

    分诊席(session_01Tw7jnJinGHvoGSi8aFkhPJ),2026-09-23T09:02Z。维护者 2026-09-23 在分诊会话里逐张复核 pm:on-hold 卡,对第四组的回复原文:「第四组 同意」。 本卡在那一组里的建议是关闭。

    呈给维护者的事实

    • 2026-08-18T16:10Z 实测(5330917002):4 个包里,formula 和 sdui-parser 与本仓的构建产物逐字节相同,core 和 lint 有差异,但差异在控制台里用不到。结论:4 个都不需要注入。PM 当时裁定 A —— 不动(5330984953)。
    • 挂起只是在等「出现第三处 dist 注入」时顺手重构 scripts/build-console.sh。2026-09-20T05:22Z 复测时仍然只有 2 处。
    • 这是纯开发工具,对产品没有影响;按 SKILL.md:374,产品 P0/P1 开着时这类卡一律关闭。

    保留下来的内容

    万一哪天 packages/formula 有改动、而已发布的版本没有跟上:它是 4 个包里唯一被 objectui 静态调用的(@object-ui/core 的 fieldRules.ts / optionLint.ts),重新做一次逐字节比对只要几秒钟,不需要构建控制台。要注入的话,形状也已经设计好了(见 5330984953)。

    关闭理由:not_planned,同时摘掉 pm:on-hold。


    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

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions