Skip to content

docs(os-dev, pm-dispatch): a dev, a seat and its subagents never print an environment variable's value; presence is tested in a form that prints none - #23049

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-23040-no-env-value-printing
Oct 12, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-23040-no-env-value-printing

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #23040
Clause-②: no

A dispatched dev printed the fleet relay's private-key variable into its session transcript by running env | grep to read the relay's routing variables. Neither the dev-agent definition nor the PM skill said a word about it. This PR adds the rule to both, in the triage grade's direction: a dev, a seat and every subagent a seat spawns never print an environment variable's value, and test presence only in a form that prints none. No mechanical guard, hook or settings deny is added — a new gate defaults to no; if the maintainer wants one, it is a new card.

What changed

File Added Deleted Lines before → after Ceiling
.claude/agents/os-dev.md 3 lines in basic rule 3's GitHub-write cluster 3 restatements (homes below) 402 → 402 402 (headroom 0)
.claude/skills/pm-dispatch/SKILL.md 1 line in 〈全体座位的不变量〉 1 restatement (home below) 319 → 319 319 (headroom 0)

Both files sit at ratchet headroom 0, so every added line is paid by a same-file deletion. No re-wrap, no ceiling moved, no cross-file move declared. Every added line is under the ratchet's 120-byte line cap (115 / 102 / 114 / 113 bytes).

Lines added, verbatim

.claude/agents/os-dev.md, after the line 归属 = 文本里的 session ID … in basic rule 3:

   - 写工具自读所需变量;⛔ 永不打印环境变量的值,转录是 AGENTS.md 禁落令牌的日志行。
   - 拼法不限于 `env`、`printenv`、`set`、`export -p`、`echo $VAR`、`cat /proc/*/environ`。
   - 判存在只用不印值形式 `[ -n "${X+x}" ] && echo set`;已印出 ⇒ `deviations` 只点名变量名。

.claude/skills/pm-dispatch/SKILL.md, after the 写侧恒为 objectstack-fleet[bot] line in 〈全体座位的不变量〉:

- 席位及其子代理 ⛔ 永不打印环境变量的值;判存在只用不印值的形式 `[ -n "${X+x}" ]`。

Why these words: the rule is a flat one — never print any environment variable's value — rather than "only the ones that look like credentials", because the flat form is the one an agent cannot misjudge (the measured instance was a dev reading routing variables). The os-dev line anchors on the rule AGENTS.md already states in its write-gate paragraph (never a token in a remote URL, a git config value on disk or a log line): a session transcript is a log line, so this is that rule applied, not a second vocabulary. The write tools read the variables they need themselves (fleet-token.mjs, fleet-write/dispatch.mjs derive the session and the route from the container), so a dev never needs a value. The presence form uses ${X+x}, which answers set-versus-unset without expanding the value; the card body's [ -n "$VAR" ] form conflates unset with empty and expands the value into the test, so it is not the form taught.

Lines deleted, and where each one lives

File Deleted line (verbatim) Its home
os-dev.md 失效同签名:操作看着本地、报成功,唯一症状是 git status 里出现他人文件。 AGENTS.md, Multi-agent working discipline, the stash paragraph (pop reports success — the only symptom is another agent's files in your git status) and the shared-ref paragraph beneath it; os-dev.md's own line 19 binds AGENTS.md in full. The two neighbours that carry the rule (what a worktree shares; git reset --soft origin/main stages others' work) stay.
os-dev.md 恢复机制与字节一致性证明规则见 AGENTS.md;从已 commit 的状态重跑,红/绿数字才可信。 AGENTS.md, Multi-agent working discipline, the reverse-verification paragraph (commit the fix first … then re-run from the committed state so your red/green numbers are trustworthy); in os-dev.md itself the commit-first line directly above it and hard lines ①–④ (restore from HEAD, prove by git diff HEAD, absolute trap paths, blob-hash comparison) remain.
os-dev.md trap 触发只证明 shell 跑了一个函数,不证明那个函数的效果。 The line directly above it, which states the trust order (trap is a convenience on the crash path; the byte/hash comparison is the proof); the deleted line was that order's rationale restated.
SKILL.md 路径面干净的才转 ready → 入队;队列是唯一被认可的落地路径,⛔ 永不队列外合并。 Red line 「永不绕过合并队列」 (SKILL.md 红线); the Tier S line directly above it (S 经达档复核 PASS 后 ready → 入队) and the landing line in 路径分叉 (席位落地 = 过落地前检、清标、ready、auto-merge); references/landing-operations.md 入队与落地 (ready/queue only after the diff read, PASS ⇒ ready + auto-merge, the governed-merges pre-check); AGENTS.md Multi-agent discipline §7 (land through the merge queue, never straight to main).

Line budget

File before after
.claude/agents/os-dev.md 402 402
.claude/skills/pm-dispatch/SKILL.md 319 319

Premise check — the dispatch's H1–H5, measured on origin/main at 38d98d8d8

  • H1 holds. grep -c -i -E "secret|env |printenv|private.key|credential" .claude/agents/os-dev.md → 0 (control worktree → 8). grep -c -E "secret|printenv|private.key|credential|凭据" .claude/skills/pm-dispatch/SKILL.md → 0 (control worktree → 3). The pm-dispatch references carry no env-printing rule either: a grep for printenv, env |, echo $, 环境变量 over .claude/skills/pm-dispatch/ finds only unrelated readings (platform-readings.md, rest-channel.md).
  • H2 adopted. The os-dev line anchors on AGENTS.md's write-gate sentence (the transcript is the log line it names); AGENTS.md is untouched (Tier H, outside this card's file surface).
  • H3 adopted, with the reason. The second half lands in SKILL.md 〈全体座位的不变量〉, not in references/dispatch-runbook.md: references/execution-duties.md states 「无条件条款只住角色文件」 and 「标准非协商条款 ⛔ 不抄进派发词」, so the os-dev constraint lives only in os-dev.md and the dispatch prompt carries no second copy; what the dispatch template cannot reach is the seat itself and the non-os-dev subagents it spawns (a contract-review general-purpose subagent reads neither os-dev.md nor a dispatch prompt), and the one text every seat and every subagent is bound by is the all-seat invariants. That line is the "dispatch template" half of the triage direction.
  • H4 partly falsified. SKILL.md is at 319/319 as the dispatch said — and .claude/agents/os-dev.md is at 402/402 too (CEILINGS row in scripts/pm/check-skill-line-ratchet.mjs), so the dispatch's "≤ +3 lines" for os-dev.md also had to be paid by three same-file deletions, which the dispatch did not budget. The same ratchet caps every line at 120 bytes (MAX_LINE_BYTES), which bounded the wording. check:pm-skill-id-lint holds: no issue number in either file's operative text.
  • H5 adopted; no exception needed. The one non-credential variable a flow reads (the session id) is read by the write tools themselves: fleet-write/dispatch.mjs --route derives it from the container and reports the derived session_… id, which is already the attribution text written to GitHub. No current step needs a dev or a seat to print a value.

Gates — every command node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived (no paths passed; the tool took the change set from git), run on 6aeede187, exit code captured before any pipe, reconciled with --ran

--ran verdict: ✓ dispatch-gates --ran: 22 derived famil(ies) accounted for — 21 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3) — then the exit-3 family was re-run after its stated prerequisite build; its final line is in the table.

Command exit Gate's own verdict line
pnpm check:pm-skill-ratchet 0 ✓ check-skill-line-ratchet: .claude/agents/os-dev.md is 402 lines (ceiling 402; headroom 0). · ✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md is 319 lines (ceiling 319; headroom 0).
pnpm check:pm-skill-id-lint 0 ✓ check-skill-id-lint: 87 file(s) clean (pattern /#[0-9]{3,}/g).
pnpm check:agent-model-declared 0 ✓ check-agent-model-declared: 1 agent definition(s) under .claude/agents/ all declare a model
pnpm check:skill-frame-sync 0 ✓ check-skill-frame-sync: the one declared copy of the decision frame is internally coherent (.claude/skills/pm-dispatch/SKILL.md …)
pnpm check:nul-bytes 0 check-nul-bytes: OK (scanned 11047 text file(s) … no raw ASCII control bytes).
pnpm check:pm-governed-prose 0 ✓ check-governed-prose: 2 instruction surface(s) name all 6 registered governed surfaces
pnpm check:pm-governed-merges 0 live: the real generator declared 9 output(s) and certified this tree
pnpm check:pm-expected-skips 0 ✓ check-expected-skips self-test: 154 cases pass (+ roster truth on this checkout)
pnpm check:commit-card-trailers 0 ✓ check-commit-card-trailers self-test: 81 cases pass.
pnpm check:agent-test-spelling 0 green (sweep over the tree)
pnpm check:cross-package-test-inputs 0 OK: 30 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob
pnpm check:doc-authoring 0 ✓ doc authoring guard: sibling-package prose ids hold the baseline
pnpm check:driver-memory-census 0 check-driver-memory-census: OK — every declaration is ledgered, every ledger entry is live
pnpm check:gitlink-declared 0 check-gitlink-declared: OK (11056 index entries -- 0 gitlink(s) at mode 160000 …)
pnpm check:refd-timer-probe 0 OK check-refd-timer-probe: 8856 source file(s) swept
pnpm check:watch-hint-literal 0 ✓ check-watch-hint-literal: 73 declaration(s) across 4 rostered name(s)
node scripts/check-closing-keyword-parity.mjs 0 check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators …)
node scripts/check-closing-keyword-parity.mjs --self-test 0 ✓ check-closing-keyword-parity --self-test: 40 assertions, 5 mutations of the shipped parsers each driven to red.
node scripts/check-comment-mask-corpus.mjs 0 ✓ comment-mask corpus sweep [scripts/js-comment-mask.mjs]: 8862 files, 0 disagree, 0 unparseable
node scripts/pm/check-governed-queue-guard.mjs --self-test 0 ✓ check-governed-queue-guard self-test: 296 cases pass
node scripts/pm/check-harness-current.mjs --self-test 0 check-harness-current --self-test: all 26 cases passed.
pnpm --filter @objectstack/lint run check:doc-formula-expressions 0 (after pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint under the verify lock; first run exit 3, PREREQUISITE NOT MET) ✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 473 files / 1388 TS blocks judged clean by @objectstack/formula.

Not run locally, by design: no package is touched (the diff is .claude/** only), so there is no ① dependency-closure build and no ② package test/typecheck; the repo-wide scans (pnpm lint first among them), the 51 artifact-roster families, the 11 wide-population families, the 15 pending-changeset families and the type-check lanes the derivation lists are CI's runs. No changeset: .claude/** publishes nothing, so skip-changeset is the declaration (applied through scripts/pm/label-write.mjs).

维护者速读(草稿)

改了什么:两份 agent 指令文本各加一条规则。.claude/agents/os-dev.md(派发的开发 agent 定义)在「GitHub 写」那一簇加三行:写工具自己读所需变量;永不打印任何环境变量的值(列出 env、printenv、set、export -p、echo $VAR、cat /proc/*/environ 这些拼法);判断变量是否设置只用不印值的形式;万一已印出,报告里只点名变量名。.claude/skills/pm-dispatch/SKILL.md(席位技能)在「全体座位的不变量」加一行:席位及其子代理永不打印环境变量的值,判存在只用不印值的形式。两份文件都在只降不升的行数棘轮顶上,所以每加一行就同文件删一行在别处有家的复述:os-dev.md 删三行,SKILL.md 删一行,行数前后不变(402 / 319)。不加任何门禁、钩子或 settings 拒绝项。

为什么改:一次实测事故——一个派发的开发 agent 为了看中继的路由变量跑了 env | grep,把中继私钥的值印进了它的会话转录(GitHub 上的报告与 PR 正文都没带值)。此前这两份文本对「不要打印环境变量」零字,一个要判断变量是否设置的 agent 没有被告知安全写法,自然伸手去拿 env。分诊定级给的方向就是:两处各加一条规则,不加机械门禁。

风险与代价(含回滚):纯指令文本,零运行时影响、零发布面。代价是删掉的四行复述——每一行在 AGENTS.md 或同文件相邻行里都有家,正文表格逐行列出了出处。残余风险:这是约定不是机械强制;分诊方向是新门禁默认不加,要加另立卡。回滚 = revert 本 PR,无副作用。

席位意见:(留空,席位定稿)

你要做的:一个动作——决定那把已暴露的中继私钥是否轮换;这不在本 PR 范围内,也不由任何席位决定。本 PR 本身是 Tier S(.claude/** 全树),由席位在达档契约复核 PASS 在案后落地,不需要您合并。

Acceptance notes

  • Observed while opening this PR, noted and not filed (no class a/b/c: not a credential, no declared contract): scripts/pm/fleet-write/dispatch.mjs --route — and every tool that re-execs itself with --use-env-proxy — prints the value of HTTPS_PROXY (a loopback proxy URL with a port) in its ℹ️ re-exec notice. Under the flat rule this PR adds, a tool that echoes a variable's value is the next thing a transcript picks up; the value here is not secret. Carrier: none; a candidate for the lane if the maintainer wants tools held to the same rule. Dedupe words: use-env-proxy, HTTPS_PROXY, re-exec notice, prints value.
  • pnpm --filter @objectstack/lint run check:doc-formula-expressions exited 3 (PREREQUISITE NOT MET: @objectstack/formula and @objectstack/lint not built) on the first run; the build it prescribes was run under the shared verify lock and the gate re-run — the table above carries the final reading. Not a finding about the tree.
  • check:pm-skill-ratchet prints a pre-existing ℹ️ about .claude/skills/spec-property-retirement/SKILL.md (table-row pin headroom 2, could be lowered to 324). Not this card's file; untouched.
  • The card body's suggested presence form [ -n "$VAR" ] && echo set conflates unset with empty and expands the value into the test; the rule teaches [ -n "${X+x}" ] instead. A wording note, not a finding.

Generated by Claude Code

…t an environment variable's value; presence is tested in a form that prints none

The os-dev definition gains one three-line rule in the GitHub-write
cluster of basic rule 3: the write tools read the variables they need,
a dev never prints an environment variable's value (the transcript is
the log line AGENTS.md already forbids a token in), the spellings that
print one are named, presence is tested only in a value-free form, and
a value already printed is reported by variable name only. The
pm-dispatch all-seat invariants gain the same rule for seats and every
subagent they spawn.

Both files sit at ratchet headroom 0, so each addition is paid by a
same-file deletion of a restatement whose home is elsewhere:
os-dev.md loses the shared-ref symptom sentence (AGENTS.md multi-agent
discipline), the restore-mechanism pointer (AGENTS.md and the file's
own hard lines), and the trap rationale (the adjacent trust-order
line); SKILL.md loses the clean-path landing line (red line on the
queue, the Tier S line beside it, and landing-operations.md).

No mechanical guard is added.

Claude-Session: https://claude.ai/code/session_012dGTuJen61ECNHXYXKChoC
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/xs documentation Improvements or additions to documentation labels Oct 12, 2026
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 12, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 6aeede187835344ad800fcc36d954b6410894261
Local-runs: none

Inputs: card #23040 (body; comments 6124767320 triage, 6125031917 claim, 6125439378 os-dev-report), PR #23049 (body, file list, the net diff against main at the head), the head's check-runs, and origin/main read only to locate where each deleted line's rule lives. Not read: the dispatch order or the dispatching seat's conclusions. The diff is 2 files, +4 / -4, both under .claude/** (Tier S, register row claude-tree); no package, no spec, no export, no changeset. origin/main advanced 34 commits past the merge base while this PR was open and none of them touches either file, the line-ratchet script, the governed register, AGENTS.md or the pm-dispatch references, so every reading below holds on current main.

① Derived judgments

Accept-set and public surface: the diff publishes nothing. No released package, no Zod schema, no export, no REST route, no metadata key changes; the whole change is governed agent-instruction text. Clause-②: no (PR body, line 2; claim, same) is right: nothing is relaxed and nothing is widened. The only surface that moves is the protocol-semantic one, judged line by line:

  1. os-dev.md, three lines added under basic rule 3's GitHub-write cluster — right. (a) 写工具自读所需变量;⛔ 永不打印环境变量的值,转录是 AGENTS.md 禁落令牌的日志行。 states the card's rule in the flat form triage graded (a dev never prints an environment variable's value) and anchors it on a sentence that exists verbatim on origin/main (AGENTS.md, Multi-agent working discipline, the write-gate paragraph: never a token in a remote URL, a git config value on disk or a log line); the first clause is true today (AGENTS.md: fleet-token.mjs mints from the OS_FLEET_* variables itself). (b) 拼法不限于 ... names the spellings the measured instance and its neighbours take and says the list is not closed, which is what makes the rule enforceable by reading a transcript rather than by guessing which variables count. (c) 判存在只用不印值形式 ... ;已印出 ⇒ deviations 只点名变量名。 gives the one permitted presence test and ties the after-the-fact reporting to the deviations field the report contract already has; the card's own account of the incident (the dev named the variable, not the value) is exactly that clause. Faithful to the card and to triage's direction; no mechanical guard, hook or settings deny is added, as triage ruled (a new gate defaults to no).
  2. The presence form [ -n "${X+x}" ] instead of the card's [ -n "$VAR" ] — right. The card asked for a form that prints no value. ${X+x} expands to a literal and never puts the value on the command line, so it is value-free even under set -x, where the card's form is not; a refinement inside the card's ask, not a departure from it.
  3. No contradiction with AGENTS.md. AGENTS.md nowhere instructs a seat or a dev to print an environment variable's value; its env-var rules are about naming (Prime Directive 9) and about tokens never reaching a URL, git config or a log line, which the new line cites. os-dev.md's own "$BASE" and "$REPO_ROOT" usages (lines 205 and 224, unchanged) use shell variables as arguments and print nothing, so the flat rule leaves no existing instruction in the file unworkable.
  4. SKILL.md, one line added to 全体座位的不变量 — right, and the right home. Triage wrote "the dispatch template"; the claim on the card (6125031917) fixed the surface as SKILL.md's all-seat invariants with references/dispatch-runbook.md only conditional. On origin/main, references/execution-duties.md line 123 (标准非协商条款 ⛔ 不抄进派发词 ... os-dev.md 已载通用段砍掉) and line 125 (无条件条款只住角色文件 ... ⛔ 不靠派发词临时覆盖) forbid the literal reading, so a copy in the dispatch template would have contradicted the skill it sits in. What the template could never reach is the seat itself and the subagents it spawns that read neither os-dev.md nor a dispatch prompt (a contract-review subagent such as the one writing this record); the all-seat invariant is the only text that binds them, and 席位及其子代理 ⛔ 永不打印环境变量的值;判存在只用不印值的形式 ... binds exactly that set. The conditional runbook edit was not needed and was not made.
  5. Line ratchet — right, and answered by CI. On origin/main both files sit at headroom 0 (CEILINGS: os-dev.md 402, SKILL.md 319; MAX_LINE_BYTES 120). Counts are 402 → 402 and 319 → 319; the added lines measure 115 / 102 / 114 / 113 bytes; the deleted ones 102 / 113 / 81 / 112. No ceiling moved, no re-wrap, no cross-file move, no table row touched (the table-row pins are unaffected). check:pm-skill-ratchet, check:pm-skill-id-lint, check:pm-governed-prose, check:skill-frame-sync and check:agent-model-declared all run inside Lint & Repo Gates, which is success on this head.
  6. Deleted lines, each judged on whether its rule survives:
    • os-dev.md 203 失效同签名:操作看着本地、报成功,唯一症状是 git status 里出现他人文件。 — a symptom sentence. The rule it decorates (what a worktree shares; git reset --soft origin/main stages others' work) stays in the unchanged lines 201, 202 and 204, and the symptom itself is AGENTS.md's stash paragraph (pop reports success — the only symptom is another agent's files in your git status); os-dev.md line 19 binds AGENTS.md in full. No rule lost.
    • os-dev.md 217 恢复机制与字节一致性证明规则见 AGENTS.md;从已 commit 的状态重跑,红/绿数字才可信。 — a pointer plus a restatement. Commit-first stays in line 215; the restore and byte-identity mechanics stay in the four hard lines (220 to 227); the re-run-from-the-committed-state sentence is AGENTS.md's reverse-verification paragraph, word for word in English. No rule lost.
    • os-dev.md 225 trap 触发只证明 shell 跑了一个函数,不证明那个函数的效果。 — the rationale for the trust order stated in the line directly above it (trap 只是崩溃路径上的便利,字节/哈希比对才是证明), which stays. No rule lost.
    • SKILL.md 204 路径面干净的才转 ready → 入队;队列是唯一被认可的落地路径,⛔ 永不队列外合并。 — three clauses. Ready/queue only on a clean path surface: 红线 line 27 (a governed PR is never flipped ready, queued or armed without its record) and line 203 directly above (Tier S after a PASS), plus references/landing-operations.md lines 57 to 59. Queue as the only landing path and never merging outside it: 红线 line 28 (永不绕过合并队列) and AGENTS.md Multi-agent discipline §7. No rule lost; the deleted line was a restatement of its own neighbours.
  7. Governance shape — right. Both paths are .claude/** and nothing else, so the PR is Tier S whole; head repo equals base repo (not a fork); draft; authored by the fleet bot; Fixes #23040 is the body's first line; the PR's assignee mirrors the card's (The card this PR closes must claim this branch is success). This record is the landing record the tier requires; landing stays the owning seat's act through the queue.
  8. Rotation of the exposed credential — correctly left alone. The PR decides nothing about it, names it in the maintainer speed-read as the maintainer's one action, and no fragment of the key appears in the diff, the PR body or the card thread.

Check-runs on the head, read 2026-10-12T23:10Z: 38 check-runs, all completed; 26 success, 12 skipped, 0 failure, 0 in progress. The five required contexts: Lint & Repo Gates success, TypeScript Type Check success, Test Core success, Governed Surface Queue Guard success, Build Core skipped. Every skipped name is a row of EXPECTED_SKIPS in scripts/pm/check-expected-skips.mjs (Build Core, Build Docs, Console Pin Gate, Temporal Conformance (live PG + MySQL), Dogfood Verify CLI, the two matrix templates, Packed-tarball smoke (opt-in), and the Check PR Size / Auto Label / Check Changeset trio on the run the label event triggered, whose first run is success); a diff with no packages/** path skips them by design. Nothing is recorded as a pass that is not one.

② Semver level

skip-changeset is the right declaration: .claude/** ships in no released package, so the diff publishes nothing and a changeset would describe nothing (AGENTS.md Post-Task Checklist 3: that label is for a diff that publishes nothing from any released package). Check Changeset is success on the head. Clause-②: no matches the diff: no accept-set is relaxed, no public surface is widened, nothing is narrowed, so no ADR-0087 disposition is owed. Level: none, correctly.

③ Boundary flags

open_questions: empty; nothing to answer.

Dev flags (report deviations, out-of-scope findings and the PR's Acceptance notes), each answered:

  • No environment value printed by the dev itself; presence never tested. Accepted; the report's own form (variable names only, in deviations) is the shape the new rule prescribes.
  • scripts/pm/fleet-write/dispatch.mjs and label-write.mjs print the value of HTTPS_PROXY in their re-exec notice (also the Acceptance-notes item and out-of-scope finding 1). Answered, not escalated: the value is a loopback proxy URL, not a credential; the rule this PR adds binds the agent's own commands, and a rule for tool output would be a new gate, which triage said defaults to no. Carrier none is right; it stays in the Acceptance notes as a candidate tooling card for the lane. The same notice is emitted by the tool that posts this record.
  • H4: os-dev.md was also at headroom 0, so three same-file deletions beyond the dispatch's budget. Judged in ① item 6: every deletion has a surviving home. Accepted.
  • check:doc-formula-expressions exit 3 then 0 after its prerequisite build. A local-run detail; the verdict of record is Lint & Repo Gates success on the head. Accepted.
  • Commit trailer pair in the model-free form. AGENTS.md's trailer rule names that form and the pre-push hook enforces it; commit messages are outside this record's inputs and were not re-read. Accepted on the rule.
  • check:pm-skill-ratchet note that spec-property-retirement/SKILL.md's table-row pin could be lowered 326 → 324. Not this card's file; lowering is legitimate at any time and untouched is right under "only touch the files your task needs". Accepted, no carrier.
  • The card's suggested [ -n "$VAR" ] form conflates unset with empty and expands the value. Judged in ① item 2; the PR's form is the stricter one inside the card's ask. Accepted.

Escalation: the only maintainer question raised anywhere in this thread is whether the exposed relay key is rotated; the filer and the triage grade already carry it to the maintainer, this PR decides nothing about it, and this record adds nothing new to escalate.

Implemented-by: claude/issue-23040-no-env-value-printing
Reviewed-by: session_012dGTuJen61ECNHXYXKChoC

VERDICT: PASS


Generated by Claude Code

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

Labels

documentation Improvements or additions to documentation size/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants