docs(releases): qualify the #4366 svc:flow audit-label entry in v17 and link the #5494 refinement (#14039) - #14410

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-14039-v17-svc-flow-qualifier
Sep 2, 2026
Merged

docs(releases): qualify the #4366 svc:flow audit-label entry in v17 and link the #5494 refinement (#14039)#14410
baozhoutao merged 2 commits into
mainfrom
claude/issue-14039-v17-svc-flow-qualifier

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes#14039

What this is

A dedicated docs-only PR. content/docs/releases/ is fenced by CLAUDE.md and by the
AGENTS.md Documentation Guardrails table ("Never edit in a code PR"), and both name the same
exit: "Factual error on a releases page → dedicated docs-only PR or an issue, never a rider on
code changes."
This is that exit. The diff carries no code: one file, six inserted lines of
prose.

The problem

content/docs/releases/v17.mdx states the #4366 audit-label behaviour unqualified:

and a runAs: 'system' flow's writes are audited as svc:flow:FLOWNAME instead of
"Unknown user" (#4366).

About 790 lines later the same page carries the #5494 entry, which refines that behaviour —
elevation does not cost a run its operator. Read in page order, the later entry supersedes the
earlier one, and nothing connected them.

The fix — a qualifier and a pointer, not a rewrite

Per the triage ruling on the card, this is option 1: annotate, do not rewrite. The #4366
sentence is preserved exactly as shipped — this PR does not restate the historical entry as
though #5494 had already been true when #4366 landed, which would falsify what #4366 actually
shipped. Two sentences are appended: one qualifying the label as a fallback, one pointing at the
#5494 entry later on the page.

 (#4365); and a `runAs: 'system'` flow's writes are audited as
- `svc:flow:FLOWNAME` instead of "Unknown user" (#4366).+ `svc:flow:FLOWNAME` instead of "Unknown user" (#4366). That label is a+ fallback, not a replacement for the operator — it stands in only for a run+ that resolves no user at all (a schedule, or a system flow fired by a write+ that itself carried no user). Where the trigger does resolve a user, #5494+ later on this page carries that user through unchanged, so the audit row+ still names the human.

(The angle-bracket placeholder in the real file is spelled FLOWNAME here only to survive body
sanitisation; the file itself is unchanged in that respect.)

Why this wording

The semantics were read from the implementation, not inferred:
packages/services/service-automation/src/runtime-identity.ts — the #5494 — elevation is not anonymity block — carries the triggering user through whenever the trigger resolved one, and a
schedule-shaped trigger resolves none.

The wording deliberately mirrors the .d.ts face of the same false belief, #14011, which
landed via PR #14035 and whose prose lives on
packages/spec/src/contracts/automation-service.ts: "The label is a FALLBACK, not a
replacement"
, and "what a genuinely USER-LESS run falls back to — a schedule, or a
runAs:'system' flow fired by a write that itself carried no user"
. The ruling asked the two to
name each other so the two surfaces do not drift into separate phrasings; this PR is the release-
notes half of that pair. No source file is touched here.

Scope

Exactly one file: content/docs/releases/v17.mdx.

Deliberately not touched, per the ruling and the dispatch:

  • content/docs/releases/v15.mdx:863 — the card's own "not a defect" verdict was re-confirmed on
    review and stands.
  • packages/services/service-automation/src/runtime-identity.ts and
    packages/spec/src/contracts/automation-service.ts — read for semantics only.
  • The bare shorthand index later in v17 (#4365/#4366 (approval reassign + audit attribution))
    makes no substantive claim about the label and needs no qualifier.

Release-process fork clause — did not fire

The dispatch instructed a stop-and-report if any release-process rule forbids cross-links or
qualifiers in release notes. None exists. The opposite is documented:
docs/releases-maintenance.md §3 defines this layer as "The curated, developer-facing 'big
picture', written for third parties"
— a curated narrative, not a mechanical per-change ledger.
Intra-page pointers are established precedent on these pages (v13:69, v16:237, v17:682, v17:2311,
v17:2394 all use "see below"). No stop was warranted.

No changeset

Docs-only; nothing is published from any package. Requesting the skip-changeset label, which
exempts the changeset-check job wholesale.

Verification — head 5c6fb906b

Gate family derived by node scripts/pm/dispatch-gates.mjs, letting the script compute the
change set itself, re-derived after merging origin/main and re-run in full on the final head.

✓ dispatch-gates --ran: 32 derived famil(ies) accounted for — 31 run, 1 NOT-MEASURED.

ResultCountDetail
RAN-PASS31every derived family, exit 0 captured before any pipe
NOT-MEASURED1node scripts/check-test-completeness.mjs — exit 3, PREREQUISITE NOT MET
UNRUN0

The one NOT-MEASURED family is structurally unmeasurable locally: the derived family names that
script with no argument, it needs a saved turbo run test log it cannot itself produce, and its
own output prescribes recording it as NOT MEASURED rather than as a pass or a red. check:pm-dispatch-gates
has no path overlap with this diff and is declared UNRUN.

Four gates first returned a build-prerequisite refusal (three as exit 3, check:skill-examples as
exit 1 with a "package is not built" verdict line — a refusal, not a finding). All four were
re-run to a real green after building spec, lint, formula, client-react and client;
lint was rebuilt again after the origin/main merge moved packages/lint/src.

Declared narrowing — repo-wide pnpm lint. Not run locally; CI owns it. This is a measurement
rather than a skip: the population was read from eslint's own configuration, not guessed —
isPathIgnored('content/docs/releases/v17.mdx') returns true, so the edited file is outside
eslint's population entirely and no eslint verdict can move. This diff also touches no eslint
config, so no untouched file's judgement changes either.

A control-character scan over the edited file returned zero matches.


Generated by Claude Code

@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/xs documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 05:21
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit a69dfdeSep 2, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14039-v17-svc-flow-qualifier branch September 2, 2026 05:47
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@baozhoutao@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

docs(releases): qualify the #4366 svc:flow audit-label entry in v17 and link the #5494 refinement (#14039) - #14410

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-14039-v17-svc-flow-qualifier
Sep 2, 2026
Merged

docs(releases): qualify the #4366 svc:flow audit-label entry in v17 and link the #5494 refinement (#14039)#14410
baozhoutao merged 2 commits into
mainfrom
claude/issue-14039-v17-svc-flow-qualifier

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes#14039

What this is

A dedicated docs-only PR. content/docs/releases/ is fenced by CLAUDE.md and by the
AGENTS.md Documentation Guardrails table ("Never edit in a code PR"), and both name the same
exit: "Factual error on a releases page → dedicated docs-only PR or an issue, never a rider on
code changes."
This is that exit. The diff carries no code: one file, six inserted lines of
prose.

The problem

content/docs/releases/v17.mdx states the #4366 audit-label behaviour unqualified:

and a runAs: 'system' flow's writes are audited as svc:flow:FLOWNAME instead of
"Unknown user" (#4366).

About 790 lines later the same page carries the #5494 entry, which refines that behaviour —
elevation does not cost a run its operator. Read in page order, the later entry supersedes the
earlier one, and nothing connected them.

The fix — a qualifier and a pointer, not a rewrite

Per the triage ruling on the card, this is option 1: annotate, do not rewrite. The #4366
sentence is preserved exactly as shipped — this PR does not restate the historical entry as
though #5494 had already been true when #4366 landed, which would falsify what #4366 actually
shipped. Two sentences are appended: one qualifying the label as a fallback, one pointing at the
#5494 entry later on the page.

 (#4365); and a `runAs: 'system'` flow's writes are audited as
- `svc:flow:FLOWNAME` instead of "Unknown user" (#4366).+ `svc:flow:FLOWNAME` instead of "Unknown user" (#4366). That label is a+ fallback, not a replacement for the operator — it stands in only for a run+ that resolves no user at all (a schedule, or a system flow fired by a write+ that itself carried no user). Where the trigger does resolve a user, #5494+ later on this page carries that user through unchanged, so the audit row+ still names the human.

(The angle-bracket placeholder in the real file is spelled FLOWNAME here only to survive body
sanitisation; the file itself is unchanged in that respect.)

Why this wording

The semantics were read from the implementation, not inferred:
packages/services/service-automation/src/runtime-identity.ts — the #5494 — elevation is not anonymity block — carries the triggering user through whenever the trigger resolved one, and a
schedule-shaped trigger resolves none.

The wording deliberately mirrors the .d.ts face of the same false belief, #14011, which
landed via PR #14035 and whose prose lives on
packages/spec/src/contracts/automation-service.ts: "The label is a FALLBACK, not a
replacement"
, and "what a genuinely USER-LESS run falls back to — a schedule, or a
runAs:'system' flow fired by a write that itself carried no user"
. The ruling asked the two to
name each other so the two surfaces do not drift into separate phrasings; this PR is the release-
notes half of that pair. No source file is touched here.

Scope

Exactly one file: content/docs/releases/v17.mdx.

Deliberately not touched, per the ruling and the dispatch:

  • content/docs/releases/v15.mdx:863 — the card's own "not a defect" verdict was re-confirmed on
    review and stands.
  • packages/services/service-automation/src/runtime-identity.ts and
    packages/spec/src/contracts/automation-service.ts — read for semantics only.
  • The bare shorthand index later in v17 (#4365/#4366 (approval reassign + audit attribution))
    makes no substantive claim about the label and needs no qualifier.

Release-process fork clause — did not fire

The dispatch instructed a stop-and-report if any release-process rule forbids cross-links or
qualifiers in release notes. None exists. The opposite is documented:
docs/releases-maintenance.md §3 defines this layer as "The curated, developer-facing 'big
picture', written for third parties"
— a curated narrative, not a mechanical per-change ledger.
Intra-page pointers are established precedent on these pages (v13:69, v16:237, v17:682, v17:2311,
v17:2394 all use "see below"). No stop was warranted.

No changeset

Docs-only; nothing is published from any package. Requesting the skip-changeset label, which
exempts the changeset-check job wholesale.

Verification — head 5c6fb906b

Gate family derived by node scripts/pm/dispatch-gates.mjs, letting the script compute the
change set itself, re-derived after merging origin/main and re-run in full on the final head.

✓ dispatch-gates --ran: 32 derived famil(ies) accounted for — 31 run, 1 NOT-MEASURED.

ResultCountDetail
RAN-PASS31every derived family, exit 0 captured before any pipe
NOT-MEASURED1node scripts/check-test-completeness.mjs — exit 3, PREREQUISITE NOT MET
UNRUN0

The one NOT-MEASURED family is structurally unmeasurable locally: the derived family names that
script with no argument, it needs a saved turbo run test log it cannot itself produce, and its
own output prescribes recording it as NOT MEASURED rather than as a pass or a red. check:pm-dispatch-gates
has no path overlap with this diff and is declared UNRUN.

Four gates first returned a build-prerequisite refusal (three as exit 3, check:skill-examples as
exit 1 with a "package is not built" verdict line — a refusal, not a finding). All four were
re-run to a real green after building spec, lint, formula, client-react and client;
lint was rebuilt again after the origin/main merge moved packages/lint/src.

Declared narrowing — repo-wide pnpm lint. Not run locally; CI owns it. This is a measurement
rather than a skip: the population was read from eslint's own configuration, not guessed —
isPathIgnored('content/docs/releases/v17.mdx') returns true, so the edited file is outside
eslint's population entirely and no eslint verdict can move. This diff also touches no eslint
config, so no untouched file's judgement changes either.

A control-character scan over the edited file returned zero matches.


Generated by Claude Code

@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/xs documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 05:21
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit a69dfdeSep 2, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14039-v17-svc-flow-qualifier branch September 2, 2026 05:47
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@baozhoutao@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs(releases): qualify the #4366 svc:flow audit-label entry in v17 and link the #5494 refinement (#14039) - #14410

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-14039-v17-svc-flow-qualifier
Sep 2, 2026
Merged

docs(releases): qualify the #4366 svc:flow audit-label entry in v17 and link the #5494 refinement (#14039)#14410
baozhoutao merged 2 commits into
mainfrom
claude/issue-14039-v17-svc-flow-qualifier

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes#14039

What this is

A dedicated docs-only PR. content/docs/releases/ is fenced by CLAUDE.md and by the
AGENTS.md Documentation Guardrails table ("Never edit in a code PR"), and both name the same
exit: "Factual error on a releases page → dedicated docs-only PR or an issue, never a rider on
code changes."
This is that exit. The diff carries no code: one file, six inserted lines of
prose.

The problem

content/docs/releases/v17.mdx states the #4366 audit-label behaviour unqualified:

and a runAs: 'system' flow's writes are audited as svc:flow:FLOWNAME instead of
"Unknown user" (#4366).

About 790 lines later the same page carries the #5494 entry, which refines that behaviour —
elevation does not cost a run its operator. Read in page order, the later entry supersedes the
earlier one, and nothing connected them.

The fix — a qualifier and a pointer, not a rewrite

Per the triage ruling on the card, this is option 1: annotate, do not rewrite. The #4366
sentence is preserved exactly as shipped — this PR does not restate the historical entry as
though #5494 had already been true when #4366 landed, which would falsify what #4366 actually
shipped. Two sentences are appended: one qualifying the label as a fallback, one pointing at the
#5494 entry later on the page.

 (#4365); and a `runAs: 'system'` flow's writes are audited as
- `svc:flow:FLOWNAME` instead of "Unknown user" (#4366).+ `svc:flow:FLOWNAME` instead of "Unknown user" (#4366). That label is a+ fallback, not a replacement for the operator — it stands in only for a run+ that resolves no user at all (a schedule, or a system flow fired by a write+ that itself carried no user). Where the trigger does resolve a user, #5494+ later on this page carries that user through unchanged, so the audit row+ still names the human.

(The angle-bracket placeholder in the real file is spelled FLOWNAME here only to survive body
sanitisation; the file itself is unchanged in that respect.)

Why this wording

The semantics were read from the implementation, not inferred:
packages/services/service-automation/src/runtime-identity.ts — the #5494 — elevation is not anonymity block — carries the triggering user through whenever the trigger resolved one, and a
schedule-shaped trigger resolves none.

The wording deliberately mirrors the .d.ts face of the same false belief, #14011, which
landed via PR #14035 and whose prose lives on
packages/spec/src/contracts/automation-service.ts: "The label is a FALLBACK, not a
replacement"
, and "what a genuinely USER-LESS run falls back to — a schedule, or a
runAs:'system' flow fired by a write that itself carried no user"
. The ruling asked the two to
name each other so the two surfaces do not drift into separate phrasings; this PR is the release-
notes half of that pair. No source file is touched here.

Scope

Exactly one file: content/docs/releases/v17.mdx.

Deliberately not touched, per the ruling and the dispatch:

  • content/docs/releases/v15.mdx:863 — the card's own "not a defect" verdict was re-confirmed on
    review and stands.
  • packages/services/service-automation/src/runtime-identity.ts and
    packages/spec/src/contracts/automation-service.ts — read for semantics only.
  • The bare shorthand index later in v17 (#4365/#4366 (approval reassign + audit attribution))
    makes no substantive claim about the label and needs no qualifier.

Release-process fork clause — did not fire

The dispatch instructed a stop-and-report if any release-process rule forbids cross-links or
qualifiers in release notes. None exists. The opposite is documented:
docs/releases-maintenance.md §3 defines this layer as "The curated, developer-facing 'big
picture', written for third parties"
— a curated narrative, not a mechanical per-change ledger.
Intra-page pointers are established precedent on these pages (v13:69, v16:237, v17:682, v17:2311,
v17:2394 all use "see below"). No stop was warranted.

No changeset

Docs-only; nothing is published from any package. Requesting the skip-changeset label, which
exempts the changeset-check job wholesale.

Verification — head 5c6fb906b

Gate family derived by node scripts/pm/dispatch-gates.mjs, letting the script compute the
change set itself, re-derived after merging origin/main and re-run in full on the final head.

✓ dispatch-gates --ran: 32 derived famil(ies) accounted for — 31 run, 1 NOT-MEASURED.

ResultCountDetail
RAN-PASS31every derived family, exit 0 captured before any pipe
NOT-MEASURED1node scripts/check-test-completeness.mjs — exit 3, PREREQUISITE NOT MET
UNRUN0

The one NOT-MEASURED family is structurally unmeasurable locally: the derived family names that
script with no argument, it needs a saved turbo run test log it cannot itself produce, and its
own output prescribes recording it as NOT MEASURED rather than as a pass or a red. check:pm-dispatch-gates
has no path overlap with this diff and is declared UNRUN.

Four gates first returned a build-prerequisite refusal (three as exit 3, check:skill-examples as
exit 1 with a "package is not built" verdict line — a refusal, not a finding). All four were
re-run to a real green after building spec, lint, formula, client-react and client;
lint was rebuilt again after the origin/main merge moved packages/lint/src.

Declared narrowing — repo-wide pnpm lint. Not run locally; CI owns it. This is a measurement
rather than a skip: the population was read from eslint's own configuration, not guessed —
isPathIgnored('content/docs/releases/v17.mdx') returns true, so the edited file is outside
eslint's population entirely and no eslint verdict can move. This diff also touches no eslint
config, so no untouched file's judgement changes either.

A control-character scan over the edited file returned zero matches.


Generated by Claude Code

@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/xs documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 05:21
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit a69dfdeSep 2, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14039-v17-svc-flow-qualifier branch September 2, 2026 05:47
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@baozhoutao@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs(releases): qualify the #4366 svc:flow audit-label entry in v17 and link the #5494 refinement (#14039) - #14410

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-14039-v17-svc-flow-qualifier
Sep 2, 2026
Merged

docs(releases): qualify the #4366 svc:flow audit-label entry in v17 and link the #5494 refinement (#14039)#14410
baozhoutao merged 2 commits into
mainfrom
claude/issue-14039-v17-svc-flow-qualifier

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes#14039

What this is

A dedicated docs-only PR. content/docs/releases/ is fenced by CLAUDE.md and by the
AGENTS.md Documentation Guardrails table ("Never edit in a code PR"), and both name the same
exit: "Factual error on a releases page → dedicated docs-only PR or an issue, never a rider on
code changes."
This is that exit. The diff carries no code: one file, six inserted lines of
prose.

The problem

content/docs/releases/v17.mdx states the #4366 audit-label behaviour unqualified:

and a runAs: 'system' flow's writes are audited as svc:flow:FLOWNAME instead of
"Unknown user" (#4366).

About 790 lines later the same page carries the #5494 entry, which refines that behaviour —
elevation does not cost a run its operator. Read in page order, the later entry supersedes the
earlier one, and nothing connected them.

The fix — a qualifier and a pointer, not a rewrite

Per the triage ruling on the card, this is option 1: annotate, do not rewrite. The #4366
sentence is preserved exactly as shipped — this PR does not restate the historical entry as
though #5494 had already been true when #4366 landed, which would falsify what #4366 actually
shipped. Two sentences are appended: one qualifying the label as a fallback, one pointing at the
#5494 entry later on the page.

 (#4365); and a `runAs: 'system'` flow's writes are audited as
- `svc:flow:FLOWNAME` instead of "Unknown user" (#4366).+ `svc:flow:FLOWNAME` instead of "Unknown user" (#4366). That label is a+ fallback, not a replacement for the operator — it stands in only for a run+ that resolves no user at all (a schedule, or a system flow fired by a write+ that itself carried no user). Where the trigger does resolve a user, #5494+ later on this page carries that user through unchanged, so the audit row+ still names the human.

(The angle-bracket placeholder in the real file is spelled FLOWNAME here only to survive body
sanitisation; the file itself is unchanged in that respect.)

Why this wording

The semantics were read from the implementation, not inferred:
packages/services/service-automation/src/runtime-identity.ts — the #5494 — elevation is not anonymity block — carries the triggering user through whenever the trigger resolved one, and a
schedule-shaped trigger resolves none.

The wording deliberately mirrors the .d.ts face of the same false belief, #14011, which
landed via PR #14035 and whose prose lives on
packages/spec/src/contracts/automation-service.ts: "The label is a FALLBACK, not a
replacement"
, and "what a genuinely USER-LESS run falls back to — a schedule, or a
runAs:'system' flow fired by a write that itself carried no user"
. The ruling asked the two to
name each other so the two surfaces do not drift into separate phrasings; this PR is the release-
notes half of that pair. No source file is touched here.

Scope

Exactly one file: content/docs/releases/v17.mdx.

Deliberately not touched, per the ruling and the dispatch:

  • content/docs/releases/v15.mdx:863 — the card's own "not a defect" verdict was re-confirmed on
    review and stands.
  • packages/services/service-automation/src/runtime-identity.ts and
    packages/spec/src/contracts/automation-service.ts — read for semantics only.
  • The bare shorthand index later in v17 (#4365/#4366 (approval reassign + audit attribution))
    makes no substantive claim about the label and needs no qualifier.

Release-process fork clause — did not fire

The dispatch instructed a stop-and-report if any release-process rule forbids cross-links or
qualifiers in release notes. None exists. The opposite is documented:
docs/releases-maintenance.md §3 defines this layer as "The curated, developer-facing 'big
picture', written for third parties"
— a curated narrative, not a mechanical per-change ledger.
Intra-page pointers are established precedent on these pages (v13:69, v16:237, v17:682, v17:2311,
v17:2394 all use "see below"). No stop was warranted.

No changeset

Docs-only; nothing is published from any package. Requesting the skip-changeset label, which
exempts the changeset-check job wholesale.

Verification — head 5c6fb906b

Gate family derived by node scripts/pm/dispatch-gates.mjs, letting the script compute the
change set itself, re-derived after merging origin/main and re-run in full on the final head.

✓ dispatch-gates --ran: 32 derived famil(ies) accounted for — 31 run, 1 NOT-MEASURED.

ResultCountDetail
RAN-PASS31every derived family, exit 0 captured before any pipe
NOT-MEASURED1node scripts/check-test-completeness.mjs — exit 3, PREREQUISITE NOT MET
UNRUN0

The one NOT-MEASURED family is structurally unmeasurable locally: the derived family names that
script with no argument, it needs a saved turbo run test log it cannot itself produce, and its
own output prescribes recording it as NOT MEASURED rather than as a pass or a red. check:pm-dispatch-gates
has no path overlap with this diff and is declared UNRUN.

Four gates first returned a build-prerequisite refusal (three as exit 3, check:skill-examples as
exit 1 with a "package is not built" verdict line — a refusal, not a finding). All four were
re-run to a real green after building spec, lint, formula, client-react and client;
lint was rebuilt again after the origin/main merge moved packages/lint/src.

Declared narrowing — repo-wide pnpm lint. Not run locally; CI owns it. This is a measurement
rather than a skip: the population was read from eslint's own configuration, not guessed —
isPathIgnored('content/docs/releases/v17.mdx') returns true, so the edited file is outside
eslint's population entirely and no eslint verdict can move. This diff also touches no eslint
config, so no untouched file's judgement changes either.

A control-character scan over the edited file returned zero matches.


Generated by Claude Code

@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/xs documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 05:21
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit a69dfdeSep 2, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14039-v17-svc-flow-qualifier branch September 2, 2026 05:47
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@baozhoutao@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

docs(releases): qualify the #4366 svc:flow audit-label entry in v17 and link the #5494 refinement (#14039) - #14410

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-14039-v17-svc-flow-qualifier
Sep 2, 2026
Merged

docs(releases): qualify the #4366 svc:flow audit-label entry in v17 and link the #5494 refinement (#14039)#14410
baozhoutao merged 2 commits into
mainfrom
claude/issue-14039-v17-svc-flow-qualifier

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes#14039

What this is

A dedicated docs-only PR. content/docs/releases/ is fenced by CLAUDE.md and by the
AGENTS.md Documentation Guardrails table ("Never edit in a code PR"), and both name the same
exit: "Factual error on a releases page → dedicated docs-only PR or an issue, never a rider on
code changes."
This is that exit. The diff carries no code: one file, six inserted lines of
prose.

The problem

content/docs/releases/v17.mdx states the #4366 audit-label behaviour unqualified:

and a runAs: 'system' flow's writes are audited as svc:flow:FLOWNAME instead of
"Unknown user" (#4366).

About 790 lines later the same page carries the #5494 entry, which refines that behaviour —
elevation does not cost a run its operator. Read in page order, the later entry supersedes the
earlier one, and nothing connected them.

The fix — a qualifier and a pointer, not a rewrite

Per the triage ruling on the card, this is option 1: annotate, do not rewrite. The #4366
sentence is preserved exactly as shipped — this PR does not restate the historical entry as
though #5494 had already been true when #4366 landed, which would falsify what #4366 actually
shipped. Two sentences are appended: one qualifying the label as a fallback, one pointing at the
#5494 entry later on the page.

 (#4365); and a `runAs: 'system'` flow's writes are audited as
- `svc:flow:FLOWNAME` instead of "Unknown user" (#4366).+ `svc:flow:FLOWNAME` instead of "Unknown user" (#4366). That label is a+ fallback, not a replacement for the operator — it stands in only for a run+ that resolves no user at all (a schedule, or a system flow fired by a write+ that itself carried no user). Where the trigger does resolve a user, #5494+ later on this page carries that user through unchanged, so the audit row+ still names the human.

(The angle-bracket placeholder in the real file is spelled FLOWNAME here only to survive body
sanitisation; the file itself is unchanged in that respect.)

Why this wording

The semantics were read from the implementation, not inferred:
packages/services/service-automation/src/runtime-identity.ts — the #5494 — elevation is not anonymity block — carries the triggering user through whenever the trigger resolved one, and a
schedule-shaped trigger resolves none.

The wording deliberately mirrors the .d.ts face of the same false belief, #14011, which
landed via PR #14035 and whose prose lives on
packages/spec/src/contracts/automation-service.ts: "The label is a FALLBACK, not a
replacement"
, and "what a genuinely USER-LESS run falls back to — a schedule, or a
runAs:'system' flow fired by a write that itself carried no user"
. The ruling asked the two to
name each other so the two surfaces do not drift into separate phrasings; this PR is the release-
notes half of that pair. No source file is touched here.

Scope

Exactly one file: content/docs/releases/v17.mdx.

Deliberately not touched, per the ruling and the dispatch:

  • content/docs/releases/v15.mdx:863 — the card's own "not a defect" verdict was re-confirmed on
    review and stands.
  • packages/services/service-automation/src/runtime-identity.ts and
    packages/spec/src/contracts/automation-service.ts — read for semantics only.
  • The bare shorthand index later in v17 (#4365/#4366 (approval reassign + audit attribution))
    makes no substantive claim about the label and needs no qualifier.

Release-process fork clause — did not fire

The dispatch instructed a stop-and-report if any release-process rule forbids cross-links or
qualifiers in release notes. None exists. The opposite is documented:
docs/releases-maintenance.md §3 defines this layer as "The curated, developer-facing 'big
picture', written for third parties"
— a curated narrative, not a mechanical per-change ledger.
Intra-page pointers are established precedent on these pages (v13:69, v16:237, v17:682, v17:2311,
v17:2394 all use "see below"). No stop was warranted.

No changeset

Docs-only; nothing is published from any package. Requesting the skip-changeset label, which
exempts the changeset-check job wholesale.

Verification — head 5c6fb906b

Gate family derived by node scripts/pm/dispatch-gates.mjs, letting the script compute the
change set itself, re-derived after merging origin/main and re-run in full on the final head.

✓ dispatch-gates --ran: 32 derived famil(ies) accounted for — 31 run, 1 NOT-MEASURED.

ResultCountDetail
RAN-PASS31every derived family, exit 0 captured before any pipe
NOT-MEASURED1node scripts/check-test-completeness.mjs — exit 3, PREREQUISITE NOT MET
UNRUN0

The one NOT-MEASURED family is structurally unmeasurable locally: the derived family names that
script with no argument, it needs a saved turbo run test log it cannot itself produce, and its
own output prescribes recording it as NOT MEASURED rather than as a pass or a red. check:pm-dispatch-gates
has no path overlap with this diff and is declared UNRUN.

Four gates first returned a build-prerequisite refusal (three as exit 3, check:skill-examples as
exit 1 with a "package is not built" verdict line — a refusal, not a finding). All four were
re-run to a real green after building spec, lint, formula, client-react and client;
lint was rebuilt again after the origin/main merge moved packages/lint/src.

Declared narrowing — repo-wide pnpm lint. Not run locally; CI owns it. This is a measurement
rather than a skip: the population was read from eslint's own configuration, not guessed —
isPathIgnored('content/docs/releases/v17.mdx') returns true, so the edited file is outside
eslint's population entirely and no eslint verdict can move. This diff also touches no eslint
config, so no untouched file's judgement changes either.

A control-character scan over the edited file returned zero matches.


Generated by Claude Code

@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/xs documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 05:21
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit a69dfdeSep 2, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14039-v17-svc-flow-qualifier branch September 2, 2026 05:47
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@baozhoutao@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs(releases): qualify the #4366 svc:flow audit-label entry in v17 and link the #5494 refinement (#14039) - #14410

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-14039-v17-svc-flow-qualifier
Sep 2, 2026
Merged

docs(releases): qualify the #4366 svc:flow audit-label entry in v17 and link the #5494 refinement (#14039)#14410
baozhoutao merged 2 commits into
mainfrom
claude/issue-14039-v17-svc-flow-qualifier

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes#14039

What this is

A dedicated docs-only PR. content/docs/releases/ is fenced by CLAUDE.md and by the
AGENTS.md Documentation Guardrails table ("Never edit in a code PR"), and both name the same
exit: "Factual error on a releases page → dedicated docs-only PR or an issue, never a rider on
code changes."
This is that exit. The diff carries no code: one file, six inserted lines of
prose.

The problem

content/docs/releases/v17.mdx states the #4366 audit-label behaviour unqualified:

and a runAs: 'system' flow's writes are audited as svc:flow:FLOWNAME instead of
"Unknown user" (#4366).

About 790 lines later the same page carries the #5494 entry, which refines that behaviour —
elevation does not cost a run its operator. Read in page order, the later entry supersedes the
earlier one, and nothing connected them.

The fix — a qualifier and a pointer, not a rewrite

Per the triage ruling on the card, this is option 1: annotate, do not rewrite. The #4366
sentence is preserved exactly as shipped — this PR does not restate the historical entry as
though #5494 had already been true when #4366 landed, which would falsify what #4366 actually
shipped. Two sentences are appended: one qualifying the label as a fallback, one pointing at the
#5494 entry later on the page.

 (#4365); and a `runAs: 'system'` flow's writes are audited as
- `svc:flow:FLOWNAME` instead of "Unknown user" (#4366).+ `svc:flow:FLOWNAME` instead of "Unknown user" (#4366). That label is a+ fallback, not a replacement for the operator — it stands in only for a run+ that resolves no user at all (a schedule, or a system flow fired by a write+ that itself carried no user). Where the trigger does resolve a user, #5494+ later on this page carries that user through unchanged, so the audit row+ still names the human.

(The angle-bracket placeholder in the real file is spelled FLOWNAME here only to survive body
sanitisation; the file itself is unchanged in that respect.)

Why this wording

The semantics were read from the implementation, not inferred:
packages/services/service-automation/src/runtime-identity.ts — the #5494 — elevation is not anonymity block — carries the triggering user through whenever the trigger resolved one, and a
schedule-shaped trigger resolves none.

The wording deliberately mirrors the .d.ts face of the same false belief, #14011, which
landed via PR #14035 and whose prose lives on
packages/spec/src/contracts/automation-service.ts: "The label is a FALLBACK, not a
replacement"
, and "what a genuinely USER-LESS run falls back to — a schedule, or a
runAs:'system' flow fired by a write that itself carried no user"
. The ruling asked the two to
name each other so the two surfaces do not drift into separate phrasings; this PR is the release-
notes half of that pair. No source file is touched here.

Scope

Exactly one file: content/docs/releases/v17.mdx.

Deliberately not touched, per the ruling and the dispatch:

  • content/docs/releases/v15.mdx:863 — the card's own "not a defect" verdict was re-confirmed on
    review and stands.
  • packages/services/service-automation/src/runtime-identity.ts and
    packages/spec/src/contracts/automation-service.ts — read for semantics only.
  • The bare shorthand index later in v17 (#4365/#4366 (approval reassign + audit attribution))
    makes no substantive claim about the label and needs no qualifier.

Release-process fork clause — did not fire

The dispatch instructed a stop-and-report if any release-process rule forbids cross-links or
qualifiers in release notes. None exists. The opposite is documented:
docs/releases-maintenance.md §3 defines this layer as "The curated, developer-facing 'big
picture', written for third parties"
— a curated narrative, not a mechanical per-change ledger.
Intra-page pointers are established precedent on these pages (v13:69, v16:237, v17:682, v17:2311,
v17:2394 all use "see below"). No stop was warranted.

No changeset

Docs-only; nothing is published from any package. Requesting the skip-changeset label, which
exempts the changeset-check job wholesale.

Verification — head 5c6fb906b

Gate family derived by node scripts/pm/dispatch-gates.mjs, letting the script compute the
change set itself, re-derived after merging origin/main and re-run in full on the final head.

✓ dispatch-gates --ran: 32 derived famil(ies) accounted for — 31 run, 1 NOT-MEASURED.

ResultCountDetail
RAN-PASS31every derived family, exit 0 captured before any pipe
NOT-MEASURED1node scripts/check-test-completeness.mjs — exit 3, PREREQUISITE NOT MET
UNRUN0

The one NOT-MEASURED family is structurally unmeasurable locally: the derived family names that
script with no argument, it needs a saved turbo run test log it cannot itself produce, and its
own output prescribes recording it as NOT MEASURED rather than as a pass or a red. check:pm-dispatch-gates
has no path overlap with this diff and is declared UNRUN.

Four gates first returned a build-prerequisite refusal (three as exit 3, check:skill-examples as
exit 1 with a "package is not built" verdict line — a refusal, not a finding). All four were
re-run to a real green after building spec, lint, formula, client-react and client;
lint was rebuilt again after the origin/main merge moved packages/lint/src.

Declared narrowing — repo-wide pnpm lint. Not run locally; CI owns it. This is a measurement
rather than a skip: the population was read from eslint's own configuration, not guessed —
isPathIgnored('content/docs/releases/v17.mdx') returns true, so the edited file is outside
eslint's population entirely and no eslint verdict can move. This diff also touches no eslint
config, so no untouched file's judgement changes either.

A control-character scan over the edited file returned zero matches.


Generated by Claude Code

@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/xs documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 05:21
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit a69dfdeSep 2, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14039-v17-svc-flow-qualifier branch September 2, 2026 05:47
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@baozhoutao@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs(releases): qualify the #4366 svc:flow audit-label entry in v17 and link the #5494 refinement (#14039) - #14410

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-14039-v17-svc-flow-qualifier
Sep 2, 2026
Merged

docs(releases): qualify the #4366 svc:flow audit-label entry in v17 and link the #5494 refinement (#14039)#14410
baozhoutao merged 2 commits into
mainfrom
claude/issue-14039-v17-svc-flow-qualifier

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes#14039

What this is

A dedicated docs-only PR. content/docs/releases/ is fenced by CLAUDE.md and by the
AGENTS.md Documentation Guardrails table ("Never edit in a code PR"), and both name the same
exit: "Factual error on a releases page → dedicated docs-only PR or an issue, never a rider on
code changes."
This is that exit. The diff carries no code: one file, six inserted lines of
prose.

The problem

content/docs/releases/v17.mdx states the #4366 audit-label behaviour unqualified:

and a runAs: 'system' flow's writes are audited as svc:flow:FLOWNAME instead of
"Unknown user" (#4366).

About 790 lines later the same page carries the #5494 entry, which refines that behaviour —
elevation does not cost a run its operator. Read in page order, the later entry supersedes the
earlier one, and nothing connected them.

The fix — a qualifier and a pointer, not a rewrite

Per the triage ruling on the card, this is option 1: annotate, do not rewrite. The #4366
sentence is preserved exactly as shipped — this PR does not restate the historical entry as
though #5494 had already been true when #4366 landed, which would falsify what #4366 actually
shipped. Two sentences are appended: one qualifying the label as a fallback, one pointing at the
#5494 entry later on the page.

 (#4365); and a `runAs: 'system'` flow's writes are audited as
- `svc:flow:FLOWNAME` instead of "Unknown user" (#4366).+ `svc:flow:FLOWNAME` instead of "Unknown user" (#4366). That label is a+ fallback, not a replacement for the operator — it stands in only for a run+ that resolves no user at all (a schedule, or a system flow fired by a write+ that itself carried no user). Where the trigger does resolve a user, #5494+ later on this page carries that user through unchanged, so the audit row+ still names the human.

(The angle-bracket placeholder in the real file is spelled FLOWNAME here only to survive body
sanitisation; the file itself is unchanged in that respect.)

Why this wording

The semantics were read from the implementation, not inferred:
packages/services/service-automation/src/runtime-identity.ts — the #5494 — elevation is not anonymity block — carries the triggering user through whenever the trigger resolved one, and a
schedule-shaped trigger resolves none.

The wording deliberately mirrors the .d.ts face of the same false belief, #14011, which
landed via PR #14035 and whose prose lives on
packages/spec/src/contracts/automation-service.ts: "The label is a FALLBACK, not a
replacement"
, and "what a genuinely USER-LESS run falls back to — a schedule, or a
runAs:'system' flow fired by a write that itself carried no user"
. The ruling asked the two to
name each other so the two surfaces do not drift into separate phrasings; this PR is the release-
notes half of that pair. No source file is touched here.

Scope

Exactly one file: content/docs/releases/v17.mdx.

Deliberately not touched, per the ruling and the dispatch:

  • content/docs/releases/v15.mdx:863 — the card's own "not a defect" verdict was re-confirmed on
    review and stands.
  • packages/services/service-automation/src/runtime-identity.ts and
    packages/spec/src/contracts/automation-service.ts — read for semantics only.
  • The bare shorthand index later in v17 (#4365/#4366 (approval reassign + audit attribution))
    makes no substantive claim about the label and needs no qualifier.

Release-process fork clause — did not fire

The dispatch instructed a stop-and-report if any release-process rule forbids cross-links or
qualifiers in release notes. None exists. The opposite is documented:
docs/releases-maintenance.md §3 defines this layer as "The curated, developer-facing 'big
picture', written for third parties"
— a curated narrative, not a mechanical per-change ledger.
Intra-page pointers are established precedent on these pages (v13:69, v16:237, v17:682, v17:2311,
v17:2394 all use "see below"). No stop was warranted.

No changeset

Docs-only; nothing is published from any package. Requesting the skip-changeset label, which
exempts the changeset-check job wholesale.

Verification — head 5c6fb906b

Gate family derived by node scripts/pm/dispatch-gates.mjs, letting the script compute the
change set itself, re-derived after merging origin/main and re-run in full on the final head.

✓ dispatch-gates --ran: 32 derived famil(ies) accounted for — 31 run, 1 NOT-MEASURED.

ResultCountDetail
RAN-PASS31every derived family, exit 0 captured before any pipe
NOT-MEASURED1node scripts/check-test-completeness.mjs — exit 3, PREREQUISITE NOT MET
UNRUN0

The one NOT-MEASURED family is structurally unmeasurable locally: the derived family names that
script with no argument, it needs a saved turbo run test log it cannot itself produce, and its
own output prescribes recording it as NOT MEASURED rather than as a pass or a red. check:pm-dispatch-gates
has no path overlap with this diff and is declared UNRUN.

Four gates first returned a build-prerequisite refusal (three as exit 3, check:skill-examples as
exit 1 with a "package is not built" verdict line — a refusal, not a finding). All four were
re-run to a real green after building spec, lint, formula, client-react and client;
lint was rebuilt again after the origin/main merge moved packages/lint/src.

Declared narrowing — repo-wide pnpm lint. Not run locally; CI owns it. This is a measurement
rather than a skip: the population was read from eslint's own configuration, not guessed —
isPathIgnored('content/docs/releases/v17.mdx') returns true, so the edited file is outside
eslint's population entirely and no eslint verdict can move. This diff also touches no eslint
config, so no untouched file's judgement changes either.

A control-character scan over the edited file returned zero matches.


Generated by Claude Code

@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/xs documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 05:21
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit a69dfdeSep 2, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14039-v17-svc-flow-qualifier branch September 2, 2026 05:47
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@baozhoutao@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

docs(releases): qualify the #4366 svc:flow audit-label entry in v17 and link the #5494 refinement (#14039) - #14410

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-14039-v17-svc-flow-qualifier
Sep 2, 2026
Merged

docs(releases): qualify the #4366 svc:flow audit-label entry in v17 and link the #5494 refinement (#14039)#14410
baozhoutao merged 2 commits into
mainfrom
claude/issue-14039-v17-svc-flow-qualifier

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes#14039

What this is

A dedicated docs-only PR. content/docs/releases/ is fenced by CLAUDE.md and by the
AGENTS.md Documentation Guardrails table ("Never edit in a code PR"), and both name the same
exit: "Factual error on a releases page → dedicated docs-only PR or an issue, never a rider on
code changes."
This is that exit. The diff carries no code: one file, six inserted lines of
prose.

The problem

content/docs/releases/v17.mdx states the #4366 audit-label behaviour unqualified:

and a runAs: 'system' flow's writes are audited as svc:flow:FLOWNAME instead of
"Unknown user" (#4366).

About 790 lines later the same page carries the #5494 entry, which refines that behaviour —
elevation does not cost a run its operator. Read in page order, the later entry supersedes the
earlier one, and nothing connected them.

The fix — a qualifier and a pointer, not a rewrite

Per the triage ruling on the card, this is option 1: annotate, do not rewrite. The #4366
sentence is preserved exactly as shipped — this PR does not restate the historical entry as
though #5494 had already been true when #4366 landed, which would falsify what #4366 actually
shipped. Two sentences are appended: one qualifying the label as a fallback, one pointing at the
#5494 entry later on the page.

 (#4365); and a `runAs: 'system'` flow's writes are audited as
- `svc:flow:FLOWNAME` instead of "Unknown user" (#4366).+ `svc:flow:FLOWNAME` instead of "Unknown user" (#4366). That label is a+ fallback, not a replacement for the operator — it stands in only for a run+ that resolves no user at all (a schedule, or a system flow fired by a write+ that itself carried no user). Where the trigger does resolve a user, #5494+ later on this page carries that user through unchanged, so the audit row+ still names the human.

(The angle-bracket placeholder in the real file is spelled FLOWNAME here only to survive body
sanitisation; the file itself is unchanged in that respect.)

Why this wording

The semantics were read from the implementation, not inferred:
packages/services/service-automation/src/runtime-identity.ts — the #5494 — elevation is not anonymity block — carries the triggering user through whenever the trigger resolved one, and a
schedule-shaped trigger resolves none.

The wording deliberately mirrors the .d.ts face of the same false belief, #14011, which
landed via PR #14035 and whose prose lives on
packages/spec/src/contracts/automation-service.ts: "The label is a FALLBACK, not a
replacement"
, and "what a genuinely USER-LESS run falls back to — a schedule, or a
runAs:'system' flow fired by a write that itself carried no user"
. The ruling asked the two to
name each other so the two surfaces do not drift into separate phrasings; this PR is the release-
notes half of that pair. No source file is touched here.

Scope

Exactly one file: content/docs/releases/v17.mdx.

Deliberately not touched, per the ruling and the dispatch:

  • content/docs/releases/v15.mdx:863 — the card's own "not a defect" verdict was re-confirmed on
    review and stands.
  • packages/services/service-automation/src/runtime-identity.ts and
    packages/spec/src/contracts/automation-service.ts — read for semantics only.
  • The bare shorthand index later in v17 (#4365/#4366 (approval reassign + audit attribution))
    makes no substantive claim about the label and needs no qualifier.

Release-process fork clause — did not fire

The dispatch instructed a stop-and-report if any release-process rule forbids cross-links or
qualifiers in release notes. None exists. The opposite is documented:
docs/releases-maintenance.md §3 defines this layer as "The curated, developer-facing 'big
picture', written for third parties"
— a curated narrative, not a mechanical per-change ledger.
Intra-page pointers are established precedent on these pages (v13:69, v16:237, v17:682, v17:2311,
v17:2394 all use "see below"). No stop was warranted.

No changeset

Docs-only; nothing is published from any package. Requesting the skip-changeset label, which
exempts the changeset-check job wholesale.

Verification — head 5c6fb906b

Gate family derived by node scripts/pm/dispatch-gates.mjs, letting the script compute the
change set itself, re-derived after merging origin/main and re-run in full on the final head.

✓ dispatch-gates --ran: 32 derived famil(ies) accounted for — 31 run, 1 NOT-MEASURED.

ResultCountDetail
RAN-PASS31every derived family, exit 0 captured before any pipe
NOT-MEASURED1node scripts/check-test-completeness.mjs — exit 3, PREREQUISITE NOT MET
UNRUN0

The one NOT-MEASURED family is structurally unmeasurable locally: the derived family names that
script with no argument, it needs a saved turbo run test log it cannot itself produce, and its
own output prescribes recording it as NOT MEASURED rather than as a pass or a red. check:pm-dispatch-gates
has no path overlap with this diff and is declared UNRUN.

Four gates first returned a build-prerequisite refusal (three as exit 3, check:skill-examples as
exit 1 with a "package is not built" verdict line — a refusal, not a finding). All four were
re-run to a real green after building spec, lint, formula, client-react and client;
lint was rebuilt again after the origin/main merge moved packages/lint/src.

Declared narrowing — repo-wide pnpm lint. Not run locally; CI owns it. This is a measurement
rather than a skip: the population was read from eslint's own configuration, not guessed —
isPathIgnored('content/docs/releases/v17.mdx') returns true, so the edited file is outside
eslint's population entirely and no eslint verdict can move. This diff also touches no eslint
config, so no untouched file's judgement changes either.

A control-character scan over the edited file returned zero matches.


Generated by Claude Code

@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/xs documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 05:21
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit a69dfdeSep 2, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14039-v17-svc-flow-qualifier branch September 2, 2026 05:47
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@baozhoutao@claude