Skip to content

Commit f3d6e34

Browse files
hyperpolymathclaude
andcommitted
docs: launcher-standard review 2026-05-26 — prose + a2ml campaign manifest
Filed alongside the 8 launcher-standard PRs (#170, #171, #172, #173, #175, #176, #177, #179) so reviewers landing on any individual PR can find the full picture in one place. Two files following the existing `docs/audits/` convention: - `launcher-standard-review-2026-05-26.adoc` — prose narrative for humans. Headline findings table (class × finding × addressed-in PR), PR map (number, branch, files, class), what-this-campaign-produces summary, deferred follow-ups, method notes including the parallel-session amend incident and how recovery worked. - `launcher-standard-review-2026-05-26.a2ml` — machine-readable manifest for tooling (PR-batching bots, change-impact analyzers, launch-scaffolder regenerators). Same PR set as parseable A2ML: per-PR file lists, addressed-issues, new-files lists, new-a2ml-keys lists, plus coordination notes (spec-version conflict resolution, lock-step gate trigger map) and deferred-followups with gating conditions. Includes a session-lessons-captured block pointing at the two memory entries written during this campaign. Pattern matches existing `gap-matrix-2026-04-17.a2ml` (A2ML extension syntax including `@abstract:` block). Pure tomllib does NOT parse A2ML; the repo's A2ML tooling does. Independent of all 8 review PRs — touches only docs/audits/. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 431adbb commit f3d6e34

2 files changed

Lines changed: 490 additions & 0 deletions

File tree

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# Launcher Standard Review — 2026-05-26
3+
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath)
4+
#
5+
# Machine-readable manifest of the launcher-standard review campaign run
6+
# on 2026-05-26. Prose companion: launcher-standard-review-2026-05-26.adoc.
7+
#
8+
# Purpose: give tooling (PR-batching bots, change-impact analyzers,
9+
# launch-scaffolder regenerators) a single document to enumerate the
10+
# 8-PR set, their classes, their file footprints, and their merge
11+
# coordination constraints, without re-parsing 8 separate PR bodies.
12+
#
13+
# When all 8 PRs have merged this file becomes a historical record;
14+
# its `status = "open"` fields can be flipped to "merged" with the
15+
# merge SHA recorded.
16+
17+
@abstract:
18+
8-PR campaign reviewing and hardening the launcher standard. 3
19+
contradictions removed, 1 blocker fixed (hard-coded eclipse-mount
20+
literal replaced with a search ladder), 1 security issue closed
21+
(`/tmp/` symlink-attack on PID/log), 1 forcing-function CI gate added,
22+
2 new required behaviours specified (`--version`, NO_COLOR), 2 new
23+
contract areas given reference implementations (soft-attach +
24+
gui-error). All PRs independent off main, GPG-signed.
25+
@end
26+
27+
[campaign]
28+
id = "launcher-standard-review-2026-05-26"
29+
filed-date = "2026-05-26"
30+
scope = "launcher/ + docs/UX-standards/launcher-standard.adoc + LM-LA-LIFECYCLE-STANDARD.adoc"
31+
pr-count = 8
32+
status = "all-open-awaiting-owner-merge"
33+
prose-companion = "docs/audits/launcher-standard-review-2026-05-26.adoc"
34+
35+
[[pr]]
36+
number = 170
37+
branch = "fix/launcher-standard-contradictions"
38+
title = "fix(launcher-standard): resolve 3 cross-doc contradictions"
39+
class = "contradictions"
40+
files = [
41+
"launcher/launcher-standard.a2ml",
42+
"docs/UX-standards/LM-LA-LIFECYCLE-STANDARD.adoc",
43+
]
44+
touches-spec-version = true
45+
spec-version-target = "0.3.0"
46+
addresses = [
47+
"browser-alias-listed-as-required-mode",
48+
"integ-disinteg-supersedence-unmirrored",
49+
"sudo-vs-no-elevated-privileges-conflict",
50+
]
51+
status = "open"
52+
53+
[[pr]]
54+
number = 171
55+
branch = "fix/launcher-standard-path-resolution"
56+
title = "fix(launcher-standard): replace hard-coded /var/mnt/eclipse/... with a search-ladder"
57+
class = "blocker-path-resolution"
58+
files = [
59+
"launcher/launcher-standard.a2ml",
60+
"docs/UX-standards/launcher-standard.adoc",
61+
"launcher/README.adoc",
62+
"launcher/resolve-desktop-tools.sh", # new
63+
]
64+
touches-spec-version = false
65+
addresses = [
66+
"var-mnt-eclipse-literal-broken-on-other-hosts",
67+
"no-bash-reference-impl-for-resolution",
68+
]
69+
new-files = ["launcher/resolve-desktop-tools.sh"]
70+
status = "open"
71+
72+
[[pr]]
73+
number = 172
74+
branch = "ci/launcher-standard-lockstep"
75+
title = "ci: add launcher-standard prose↔a2ml lock-step gate"
76+
class = "ci-forcing-function"
77+
files = [
78+
".github/workflows/launcher-standard-lockstep.yml", # new
79+
]
80+
touches-spec-version = false
81+
addresses = [
82+
"prose-a2ml-drift-not-enforced",
83+
]
84+
new-files = [".github/workflows/launcher-standard-lockstep.yml"]
85+
fires-on = [
86+
"launcher/launcher-standard.a2ml",
87+
"docs/UX-standards/launcher-standard.adoc",
88+
]
89+
status = "open"
90+
91+
[[pr]]
92+
number = 173
93+
branch = "feat/launcher-version-mode"
94+
title = "feat(launcher-standard): require --version mode with machine-greppable format"
95+
class = "missing-mode"
96+
files = [
97+
"launcher/launcher-standard.a2ml",
98+
"docs/UX-standards/launcher-standard.adoc",
99+
]
100+
touches-spec-version = false
101+
addresses = [
102+
"no-version-mode-required",
103+
]
104+
required-format = "{app-name} {version} ({build-sha-short}) [{platform}]"
105+
status = "open"
106+
107+
[[pr]]
108+
number = 175
109+
branch = "fix/launcher-xdg-pid-log-paths"
110+
title = "fix(launcher-standard): move PID/log to XDG dirs (security: symlink-attack hardening)"
111+
class = "security-xdg-hardening"
112+
files = [
113+
"launcher/launcher-standard.a2ml",
114+
"docs/UX-standards/launcher-standard.adoc",
115+
]
116+
touches-spec-version = true
117+
spec-version-target = "0.4.0" # if landing after #170; else 0.3.0 and #170 bumps to 0.4.0
118+
addresses = [
119+
"tmp-pid-symlink-attack-vector",
120+
"tmp-log-symlink-attack-vector",
121+
]
122+
recovery-note = "PR #175 was re-pushed force-with-lease after a parallel-session amend incident contaminated the original commit with 327 lines of unrelated WIP. The final pushed commit (signed GPG) contains only the intended 2-file XDG change."
123+
status = "open"
124+
125+
[[pr]]
126+
number = 176
127+
branch = "fix/keepopen-honour-no-color"
128+
title = "fix(keepopen): honour NO_COLOR and auto-strip ANSI for non-TTY stdout"
129+
class = "ux-no-color"
130+
files = [
131+
"launcher/keepopen.sh",
132+
]
133+
touches-spec-version = false
134+
addresses = [
135+
"keepopen-emits-ansi-when-piped",
136+
"no-color-env-not-honoured",
137+
]
138+
triggers-lockstep-gate = false # not in the 2-file lock-step group
139+
status = "open"
140+
141+
[[pr]]
142+
number = 177
143+
branch = "feat/launcher-browser-and-wait-timing"
144+
title = "feat(launcher-standard): cross-platform browser launch + env-overridable wait timing"
145+
class = "cross-platform-and-tunable"
146+
files = [
147+
"launcher/launcher-standard.a2ml",
148+
"docs/UX-standards/launcher-standard.adoc",
149+
]
150+
touches-spec-version = false
151+
addresses = [
152+
"open-browser-linux-only-despite-stated-cross-platform",
153+
"no-BROWSER-env-honoured",
154+
"wait-for-url-timeout-constant-unread-by-template",
155+
"no-per-request-curl-timeout",
156+
]
157+
new-a2ml-tables = ["browser-launch"]
158+
new-a2ml-keys-in-runtime = [
159+
"wait-for-url-timeout-env-var",
160+
"wait-for-url-poll-interval-seconds",
161+
"wait-for-url-poll-interval-env-var",
162+
"wait-for-url-per-request-timeout-seconds",
163+
]
164+
status = "open"
165+
166+
[[pr]]
167+
number = 179
168+
branch = "feat/launcher-soft-attach-and-gui-error"
169+
title = "feat(launcher-standard): reference impls for soft-attach + gui-dialog-chain"
170+
class = "reference-impls"
171+
files = [
172+
"launcher/launcher-standard.a2ml",
173+
"docs/UX-standards/launcher-standard.adoc",
174+
"launcher/gui-error.sh", # new
175+
"launcher/soft-attach.sh", # new
176+
]
177+
touches-spec-version = false
178+
addresses = [
179+
"soft-attach-no-reference-impl-drift",
180+
"gui-dialog-chain-no-reference-impl-drift",
181+
"soft-attach-when-trigger-underspecified",
182+
]
183+
new-files = ["launcher/gui-error.sh", "launcher/soft-attach.sh"]
184+
new-a2ml-keys-in-error-visibility = ["reference-impl", "suppress-env-var"]
185+
new-a2ml-keys-in-soft-attach = ["reference-impl"]
186+
soft-attach-tools-extended-with = ["style", "trigger"]
187+
status = "open"
188+
189+
[coordination]
190+
# Notes the merger needs to follow.
191+
spec-version-conflict-resolution = """
192+
PRs #170 and #175 both bump [spec].version. They were filed with the
193+
same target (0.3.0); whichever lands second must conflict-resolve to
194+
the next bump (e.g. #175 → 0.4.0 if landing after #170). All other PRs
195+
deliberately did not touch [spec].version to leave the merger free to
196+
sequence.
197+
"""
198+
lockstep-gate-trigger = """
199+
Once #172 merges, PRs #170, #171, #173, #175, #177, #179 will all be
200+
checked by the gate on next push to their branches. All six touch both
201+
launcher-standard.a2ml AND docs/UX-standards/launcher-standard.adoc, so
202+
they pass. #176 (keepopen.sh only) and #172 itself touch neither group
203+
member, so the gate doesn't fire there.
204+
"""
205+
206+
[deferred-followups]
207+
# Items deliberately left out of the 8-PR campaign because they depend
208+
# on merges or live in other repos.
209+
210+
[[deferred]]
211+
id = "extend-lockstep-gate-to-helpers"
212+
description = "Add launcher/resolve-desktop-tools.sh, launcher/gui-error.sh, launcher/soft-attach.sh to the lock-step group in .github/workflows/launcher-standard-lockstep.yml"
213+
gated-on-merges = [171, 179]
214+
estimated-effort = "~10 lines workflow edit"
215+
216+
[[deferred]]
217+
id = "launch-scaffolder-loader-update"
218+
description = "Update the launch-scaffolder Rust loader to consume the new [resolution] / [browser-launch] / [aliases] / [soft-attach].style+trigger / [error-visibility].suppress-env-var tables. Until this lands, this campaign is documentation-and-helper only for the launch-scaffolder consumer — but it already unblocks any new launcher that sources resolve-desktop-tools.sh / gui-error.sh / soft-attach.sh directly."
219+
gated-on-merges = "all-8-merging-or-at-minimum-#171"
220+
repo = "launch-scaffolder"
221+
estimated-effort = "non-trivial — replace hard-coded fallback in Rust loader; respect aliases in mode dispatch; emit style/trigger-aware soft-attach call sites; thread NO_GUI_ERROR into error paths"
222+
223+
[session-lessons-captured]
224+
# Memory entries written during this campaign for future reference.
225+
files = [
226+
"~/.claude/projects/-home-hyperpolymath/memory/feedback_git_amend_swallows_parallel_staged.md",
227+
"~/.claude/projects/-home-hyperpolymath/memory/project_standards_launcher_campaign_2026_05_26.md",
228+
]
229+
key-lessons = [
230+
"git commit --amend without --only sweeps the entire index, including files staged by parallel sessions sharing the checkout. Always use --only <paths> when amending in a multi-session checkout.",
231+
"When force-pushing to recover from a parallel-session amend incident, use --force-with-lease=branch:explicit-remote-sha; plain --force-with-lease can fail with 'stale info' if local tracking is out of date.",
232+
]
233+
234+
[provenance]
235+
review-method = "manual top-to-bottom read of launcher/ + docs/UX-standards/launcher-standard.adoc + LM-LA-LIFECYCLE-STANDARD.adoc (~2,000 lines)"
236+
review-duration = "single session ~3 hours"
237+
all-prs-gpg-signed = true
238+
all-prs-independent-off-main = true
239+
git-signing-key = "9639451754496E51D6B537CAD119017EBF695AB1"

0 commit comments

Comments
 (0)