scripts/pm/os-verify-lock.sh's own header documents its usage as a direct invocation:
scripts/pm/os-verify-lock.sh -c 'pnpm --filter @objectstack/core test'
scripts/pm/os-verify-lock.sh -- pnpm --filter @objectstack/core test
scripts/pm/os-verify-lock.sh --status
⛔ That spelling cannot work. The file is tracked 100644 — no execute bit — so a direct call returns exit 126 / Permission denied.
⚠️ ⛔ Not a container accident: it is the tracked mode in git, so every checkout and every worktree gets it.
Measured, with the control in the same command
objectstack shared checkout, 2026-09-18T13:49Z:
|
|
scripts/pm/os-verify-lock.sh --self-test (direct) |
exit 126 |
bash scripts/pm/os-verify-lock.sh --self-test |
exit 0 |
git ls-files -s scripts/pm/os-verify-lock.sh |
100644 |
control 1 git ls-files -s scripts/pm/ensure-pm-labels.sh |
100644 |
control 2 git ls-files -s scripts/pm/os-regen-merge.sh |
100644 |
⇒ ⭐ the two controls widen the finding rather than isolate it: all three .sh files under scripts/pm/ are non-executable as tracked. ⛔ This is not one file's lost bit.
Why it is worth a card rather than a habit
⚠️ Exit 126 is one digit away from the code that means something else entirely. This script's own header teaches that exit 99 means the call never acquired the lock, and that a caller must 「read the VERDICT line, never a bare $?」. A dev that reads $? and sees 126 has a number the header does not explain, from a call that never ran the wrapped command and never printed a VERDICT line.
⇒ the failure mode is a dev recording a red gate that never ran — the same shape already measured twice on the objectui side today (pnpm -s check:changeset-presence exiting 254 for a script name that does not exist, and an eslint probe run with a sibling repo's flag reporting 16 phantom errors).
⚠️ ⭐ Every dev on this container hits it. It was reported by an os-dev on objectui#9802 after it worked around it with bash <path>; the reading above is the seat's own re-measurement, ⛔ not the report.
The class
(b) 违背已声明契约 — the contract is the script's own documented invocation, quoted above, and the file mode refuses it. ⛔ ⚠️ Whichever way it is answered, ⛔ the answer is ⛔ not 「everyone should know to use bash」: the header would still be teaching a spelling that does not run.
The shapes, ⛔ none of them ruled here
- A —
git update-index --chmod=+x on the three files, so the documented spelling works.
- B — rewrite the headers to the invocation that actually works (
bash scripts/pm/… or node), so nothing teaches a refused form.
- C — a gate: any
scripts/** file whose header documents a bare-path invocation must be mode 100755. ⚠️ ⛔ A new gate is a 人工地板 item and is ⛔ not proposed here as a default.
⚠️ ⭐ The first deliverable is the criterion, ⛔ not the chmod: which files in scripts/** are meant to be invoked directly at all? A blanket +x over everything would be the same unexamined move in the other direction.
Dedupe words
os-verify-lock.sh exit 126 permission denied
scripts/pm .sh not executable 100644
documented invocation refused by file mode
verify lock direct invocation bash prefix
Filed from another repo's lane, on the charter's rule
Filed by the domain:ui#2 execution seat at objectui. scripts/pm/** is objectstack's tooling and its single writer is an objectstack-side seat — 「他侧上游立卡回链」 — so this is the upstream card with the back-link, ⛔ not a change proposed from outside.
Back-link: objectui#9802 (where the os-dev hit it) · objectui#9860 (an objectui card whose dev used the same script in the same round).
filed by the domain:ui#2 execution seat at objectstack-ai/objectui · session_018HrVaotisyhgmot9o2MLRq · ⛔ this seat does ⛔ not grade or route, and ⛔ has no standing to route in this repo at all: no priority:*, no domain:* · readings taken 2026-09-18T13:49Z
Generated by Claude Code
scripts/pm/os-verify-lock.sh's own header documents its usage as a direct invocation:⛔ That spelling cannot work. The file is tracked
100644— no execute bit — so a direct call returns exit 126 / Permission denied.Measured, with the control in the same command
objectstackshared checkout, 2026-09-18T13:49Z:scripts/pm/os-verify-lock.sh --self-test(direct)bash scripts/pm/os-verify-lock.sh --self-testgit ls-files -s scripts/pm/os-verify-lock.sh100644git ls-files -s scripts/pm/ensure-pm-labels.sh100644git ls-files -s scripts/pm/os-regen-merge.sh100644⇒ ⭐ the two controls widen the finding rather than isolate it: all three
.shfiles underscripts/pm/are non-executable as tracked. ⛔ This is not one file's lost bit.Why it is worth a card rather than a habit
$?」. A dev that reads$?and sees 126 has a number the header does not explain, from a call that never ran the wrapped command and never printed a VERDICT line.⇒ the failure mode is a dev recording a red gate that never ran — the same shape already measured twice on the objectui side today (
pnpm -s check:changeset-presenceexiting 254 for a script name that does not exist, and an eslint probe run with a sibling repo's flag reporting 16 phantom errors).os-devon objectui#9802 after it worked around it withbash <path>; the reading above is the seat's own re-measurement, ⛔ not the report.The class
(b) 违背已声明契约 — the contract is the script's own documented invocation, quoted above, and the file mode refuses it. ⛔⚠️ Whichever way it is answered, ⛔ the answer is ⛔ not 「everyone should know to use
bash」: the header would still be teaching a spelling that does not run.The shapes, ⛔ none of them ruled here
git update-index --chmod=+xon the three files, so the documented spelling works.bash scripts/pm/…ornode), so nothing teaches a refused form.scripts/**file whose header documents a bare-path invocation must be mode100755.scripts/**are meant to be invoked directly at all? A blanket+xover everything would be the same unexamined move in the other direction.Dedupe words
os-verify-lock.sh exit 126 permission deniedscripts/pm .sh not executable 100644documented invocation refused by file modeverify lock direct invocation bash prefixFiled from another repo's lane, on the charter's rule
Filed by the
domain:ui#2execution seat at objectui.scripts/pm/**is objectstack's tooling and its single writer is an objectstack-side seat — 「他侧上游立卡回链」 — so this is the upstream card with the back-link, ⛔ not a change proposed from outside.Back-link: objectui#9802 (where the
os-devhit it) · objectui#9860 (an objectui card whose dev used the same script in the same round).filed by the
domain:ui#2execution seat at objectstack-ai/objectui ·session_018HrVaotisyhgmot9o2MLRq· ⛔ this seat does ⛔ not grade or route, and ⛔ has no standing to route in this repo at all: nopriority:*, nodomain:*· readings taken 2026-09-18T13:49ZGenerated by Claude Code