Skip to content

Trim the skill set; move what the skills summarized into the CLI - #436

Merged
bgmcmullen merged 11 commits into
masterfrom
skills/trim-and-cli-help
Jul 29, 2026
Merged

Trim the skill set; move what the skills summarized into the CLI#436
bgmcmullen merged 11 commits into
masterfrom
skills/trim-and-cli-help

Conversation

@bgmcmullen

@bgmcmullenbgmcmullen commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Trims the HypAware skill set and moves what the skills were carrying into the CLI, where it can stay true.

The through-line: a skill that summarizes something the CLI already knows will drift, and then mislead. Every deletion here is paired with the command that now answers the question.

1. Remove hypaware-sensitive-scan (11 → 10 Claude, 9 → 8 Codex)

The scan and hypaware-privacy split one job in half and had already drifted into contradicting each other on the question users care about most:

  • hypaware-sensitive-scan: "Retroactive purge is out of scope."
  • hypaware-privacy: "Step 6 - Apply only via hyp verbs, and offer purge for every ignore (R6, R7)."

hyp purge exists (LLP 0104) and LLP 0100 R7 mandates offering it, so a user who found a credential in their cache was told cleanup was impossible by one skill and offered it by the other.

hypaware-privacy keeps the consent protocol (LLP 0100 R3-R9), the three usage classes, and the purge offer. No LLP referenced the scan, so it removes cleanly. Both client trees, both manifests, both registration lists, and docs/PRIVACY.md.

Review follow-up (77d42fd, 4711975). Removing the scan exposed that hypaware-privacy's own description gated every trigger clause on the deferred first sync, so a never-enrolled machine - the default state - had no way to ask this question in plain language, and none of the scan's vocabulary (secrets, credentials, PII, "what should I hypignore") survived anywhere. The description is now written around the audit itself, with the first sync as the standard occasion rather than a gate. The six steps are unchanged.

That is not a new decision: LLP 0107#gating already held that "enrolled-ness gates behavior, not presence" and that the skill's deadline framing "simply does not arise without a pending first sync". The description had been out of step with it.

The scan's remote-server scan target is dropped on purpose, with no replacement. Scanning an org server's whole recorded history from one member's laptop is not practical: unbounded row volume, and the remedies (hyp policy set, hyp purge) are machine-local and cannot reach rows already forwarded. Server-side review is an operator concern and belongs behind an operator surface, not a client skill. The skill's description states the boundary so the gap is visible rather than assumed.

Both are recorded in LLP 0142, which also carries §4's policy.

2. CLI help gets bodies (attach, detach, status, init, sync)

Seven commands rendered as title-and-usage only. Five were exactly the ones whose behaviour lived nowhere but a client skill: invisible to anyone reading --help in a terminal, and Claude/Codex-only.

Top-level hyp --help also gains three facts a bare command list cannot convey: hyp and hypaware are the same binary; the list is install-specific because inactive plugins contribute nothing (pointing at the LLP 0098/0099 miss path); and hyp status answers whether the install works.

One correction found by verifying rather than transcribing:

  • hyp init --yes is real but was missing from its usage string.

Review follow-up (3e159cd). Fixing that surfaced a worse problem in the same line. hyp init states its interface in three reachable places: this registry entry, the non-TTY/unknown-flag hint (init.js:123,139), and the parser's own usage, which fires when --help is not the first token because dispatch intercepts only rest[0] while parseCommandArgv matches --help anywhere in argv. The other two were accurate; the registry string this PR wrote was not. It put --yes outside the brackets, implying it gates the non-interactive path (INIT_FLAG_NAMES routes on any of ten flags, so hyp init --dry-run needs no --yes), and listed four flags with no ellipsis, so it read as exhaustive while six were invisible.

usage is now hyp init [preset] [flags], with the full list in the help body this PR had just added, checked flag by flag against the parser (--from-file takes a v2 config, not answers; --force backs up before replacing). INIT_FLAG_NAMES is exported and test/core/cli/init-help-flags.test.js pins both properties, so the help body cannot drift from the dispatcher again.

hyp claude-desktop install does not exist - retracted, this claim was
wrong
(caught in review). It is registered unconditionally in the plugin's
activate() (hypaware-core/plugins-workspace/claude-desktop/src/index.js) as
the LLP 0135 picker's configure_command, with claude-desktop verify
alongside it, and it has its own test file. Only the statically declared
commands in hypaware.plugin.json were checked, which is where the false
negative came from. Fixed in 9deaac7: the hyp attach help body now names
hyp claude-desktop install and hyp claude-desktop verify directly, so the
CLI is at least as actionable as the skill text it replaced. The same commit
drops the "exposes no user-writable settings file" clause, which restated the
LLP 0115 premise that LLP 0133#plist-surface retires.

3. Shrink hypaware-reference (169 → 95 lines, 44%)

The skill's own preamble declared hyp --help authoritative over anything it summarized, then summarized it anyway in a 45-line command map. That map had drifted exactly as you'd predict: it omitted seven live commands (leave, plugin, policy, purge, report, skills, sync), listed smoke (internal), and routed to four report skills that no longer exist.

ContentNow lives in
CLI command maphyp --help / hyp <command> --help
"what is recording here"hyp status, hyp policy list
Codex Desktop specificshyp attach --help
Invariants, paths, opt-in boundarystays in the skill

Also corrects the enrollment story: hyp join is not superseded by hyp remote login. Per LLP 0063 they are two doors to the same enrolled state (unattended/MDM vs attended), and neither is deprecated; the emphasis now leads with remote login because LLP 0134 settled that the wizard wraps it and the token join never surfaces.

Review follow-up (9f47389). One surviving sentence quoted hyp status's output, and got it wrong three ways: a Unicode ellipsis where the repo wants ASCII, whitespace where status.js:358 emits -, and, worst, flatly as something hyp status prints. That write is guarded by if (report.clientSync), which is null on a solo host (LLP 0132 #never-silent), so the line never appears on the default install: a reader was being sent to look for output that is not there. It now describes what the command does instead of reproducing its output, which is the drift this PR is otherwise about, and avoids re-encoding the · list separator the real line also carries.

4. Hide user-triggered skills

disable-model-invocation: true on the three Claude skills where invoking the skill is itself the consequential act: hypaware-publish-report (makes a report org-visible), hypaware-apply-report-changes (mutates this machine's config), hypaware-report-to-html (rewrites a git working tree). Each is a step a person takes on purpose after reading something; none is an answer to a question. This removes their descriptions from context entirely while leaving /name in the slash menu.

Revised in review: hypaware-ignore / hypaware-unignore keep model invocation. The original argument here was that /name in the slash menu leaves the affordance unchanged. That holds for the three above; it does not hold for these two, where being reachable in the user's own words is the product. LLP 0066 is written around the utterance "don't record this conversation" and treats those skills as the contract the gateway implements, and LLP 0107#gating separately notes hypaware-ignore is useful unenrolled and that per-skill carve-outs lose to one rule. For a privacy opt-out, discovery is the feature. Their descriptions are restored.

The test is now written down in LLP 0142#user-invoked-only: mark a bundled skill user-invoked only when invoking it publishes, mutates, or spends. @refs on all five skill files.

hypaware-ai-usage-report stays visible on purpose: it is the read-only front door to the report pipeline, and hiding it would break asking for a usage report in plain language.

5. Review nits (3a78567)

  • The help epilogue cited (LLP 0098) in prose, which /ref-check cannot validate and which no longer resolves: llp/ holds two 0098s. An anchor was the obvious fix, except both docs also carry a ## Decision heading, so the #decision slug dispatch.js:250 was already using had the same defect. Adds an explicit unavailable-not-unknown anchor to the dispatch-miss doc (purely additive, no wording touched on an Accepted doc) and points both refs at it. The duplicate numbering itself is pre-existing and left alone.
  • The epilogue stacked three bare nouns before its verb ("running a command a disabled plugin provides names that plugin"). Rewritten as a conditional.

Deliberately not in this PR

Verification

  • CI is green at 3a78567: 8/8 checks, test and typecheck on Node 22 and 24.
  • Locally npm test reports 2786 tests, 2783 pass, 2 fail, 1 skip. Neither failure is this PR's and neither reproduces in CI, so both are local-environment artifacts: blob-store.test.js (all 14 subtests pass, the file itself exits nonzero, and it fails identically on a clean master worktree) and the query-sql-budget.test.js heap-growth test (7/7 in isolation across three runs, flaky under full-suite memory pressure).
  • New: test/core/cli/init-help-flags.test.js, 2 tests, both verified non-vacuous against the pre-fix strings.
  • No test asserts top-level help text; package_bin_boot only prefix-matches the header line, and it passes at this SHA.
  • git diff master...HEAD introduces zero em dashes and zero Unicode ellipses.
  • Smokes green: package_bin_boot, cli_bundled_plugins_activated, status_diagnostics, client_attach_idempotent (the last materializes skills at attach).
  • Manifest skill lists verified against the index.js registration lists (two separate lists that can drift): 10 and 8, matching.

Related

#431 (gateway port pin), #432 (hyp session verbs), #435 (collapse the opt-out skills onto them)

🤖 Generated with Claude Code

bgmcmullenand others added 4 commits July 28, 2026 17:46
The two skills split one job in half and had already drifted into
contradicting each other on the question users care about most. The scan
declared "Retroactive purge is out of scope", while hypaware-privacy is
required by LLP 0100 R7 to offer `hyp purge` for every directory marked
ignore. A user who found a credential in the cache was told cleanup was
impossible by one skill and offered it by the other.
hypaware-privacy keeps the consent protocol (LLP 0100 R3-R9), the three
usage classes, and the purge offer. The scan's ad-hoc framing and its
regex class table are dropped rather than folded in: privacy's step 3
already directs the reviewer to sample for credentials and personal
material, and adding a detection table to a consent flow would work
against its shape.
No LLP referenced the scan, so this removes cleanly. Also fixes adjacent
rot in the Codex plugin's JSDoc, which advertised three report skills
(adoption/spend, improvement, security) that no longer exist.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…evel epilogue
Seven commands rendered as title-and-usage only, with no help body at all.
Five of them were exactly the commands whose behaviour was documented
nowhere but a client skill, which is the wrong place for it: the skill is
Claude/Codex-only, drifts silently, and is invisible to anyone reading
--help in a terminal.
Adds bodies for attach, detach, status, init, and sync, covering what the
skill's command map carried: attach is idempotent and reversible and
covers Codex Desktop (LLP 0141), unattach is an alias, status is the
"is it working?" entry point whose diagnostics carry repair: lines, init
runs the walkthrough or --yes, and sync releases the first-sync hold
all-or-nothing (LLP 0101).
The top-level help gains three facts a bare command list cannot convey:
that `hyp` and `hypaware` are the same binary, that the list is
install-specific because inactive plugins contribute nothing (with a
pointer to the LLP 0098/0099 miss path that names the plugin and prints a
repair line), and that `hyp status` answers whether the install works.
Two corrections found while verifying rather than transcribing the skill:
`hyp claude-desktop install` does not exist (the subcommands are profile,
install-helper, status), and `hyp init --yes` was real but missing from
its usage string.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The skill's own preamble declared `hyp --help` authoritative over
anything it summarized, and then summarized it anyway across a 45-line
command map. That map had drifted exactly as predicted: it omitted seven
live commands (leave, plugin, policy, purge, report, skills, sync),
listed `smoke`, which is internal, and pointed at four report skills that
no longer exist.
Content moves to whichever source can keep it true:
- the command map to `hyp --help` / `hyp <command> --help`
- "what is recording here" to `hyp status` (per-client configured/attached
plus the syncing/local-only line) and `hyp policy list`
- Codex Desktop specifics to `hyp attach --help`
What stays is what no command prints: the data-flow invariants, the
HYP_HOME path layout, and the local-versus-opt-in boundary.
Also corrects the enrollment story. `hyp join` is not superseded by
`hyp remote login`; per LLP 0063 they are two doors to the same enrolled
state, attended versus unattended/MDM, and neither is deprecated. The
emphasis now leads with `hyp remote login` because LLP 0134 settled that
the wizard wraps it and the token join never surfaces.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Five Claude skills are things a person triggers, not things Claude should
decide to do: stopping and resuming recording, publishing a report to the
whole org, editing this machine's skills and CLAUDE.md, and building a
site in a git repo. Claude Code's docs recommend disable-model-invocation
for exactly this class, alongside /commit and /deploy.
Setting it removes each skill's description from context entirely while
leaving /name in the user's slash menu, so the affordance is unchanged and
the context cost goes to zero. Descriptions shrink to one line each,
because with the skill out of context that text is no longer doing routing
work; it is just the label in the menu.
hypaware-ai-usage-report stays visible on purpose: it is the read-only
front door to the report pipeline, and hiding it would break asking for a
usage report in plain language.
Left to the Codex tree deliberately. disable-model-invocation is a Claude
Code extension to the Agent Skills standard, and a strict parser could
reject the file outright rather than ignore the key, so it needs testing
against Codex before being applied there.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@bgmcmullenbgmcmullen added the neutral:review Delegate this PR to neutral for a review pass (approve or request changes; never merges) label Jul 29, 2026
@philcunliffe

Copy link
Copy Markdown
Contributor

neutral review - PR #436 @ 357f55c

Verdict: request-changes (3 medium, 2 low, 3 nits)

Reviewed in an isolated worktree at 357f55c74fd0d0ce9a470a0a1f83365febb1f2f8. Codex was not available on this host, so this is a single-family (Claude) review.

The shape of the PR is right: the mechanical parts are clean. Manifest / index.js / on-disk skill-directory parity verified programmatically in both trees (claude 10/10/10, codex 8/8/8, no set differences either direction). No dangling reference to hypaware-sensitive-scan survives anywhere in the tree. No em dash (U+2014) is introduced, and one is removed from hypaware-unignore. test/core/command-dispatch.test.js + test/core/cli/stream-errors.test.js pass 32/32 on the head SHA, and hypaware-core/smoke/flows/package_bin_boot.js:68 asserts only the hyp - HypAware kernel CLI prefix, so the dispatch.js header change does not break it. Every CLI fact newly asserted in the help bodies that I could check holds: hyp init's --yes/--client/--source/--force (src/core/commands/init.js:406-413), unattach as a detach alias, hyp purge, hyp policy list/set, hyp plugin list/install, the s3 / completion-* / embedder-openai plugin names, LLP 0063 / 0134 for the two-doors enrollment story, and the all-or-nothing first-sync hold (src/core/commands/sync.js:90-99, LLP 0101#hold).

Three things are worth blocking on, because in each case the PR removes information on a premise that does not survive checking.


1. [Medium] hyp claude-desktop install does exist - the "correction" is itself wrong, and it removes the useful pointer

The PR description states this as a verified finding:

hyp claude-desktop installdoes not exist - the subcommands are profile, install-helper, status. The skill had been advertising a nonexistent command.

It does exist. hypaware-core/plugins-workspace/claude-desktop/src/index.js:109-121 registers it unconditionally inside activate(), with its own help body, and the comment above it names it as the picker's configure_command per LLP 0135 / LLP 0133#one-surface. It has a dedicated test file, test/plugins/claude-desktop-install.test.js. claude-desktop verify (:123) exists too, and is likewise absent from the PR's list.

Consequence in the shipped diff: master's hypaware-reference told a Claude Desktop user the exact command to run; the replacement at src/core/cli/core_commands.js:272-274 only says "handled by hyp claude-desktop instead (see hyp claude-desktop --help)". That is strictly less actionable than what was deleted, and it was traded away on a false premise.

Second, smaller inaccuracy in the same sentence, src/core/cli/core_commands.js:272-273:

'Claude Desktop exposes no user-writable settings file and is handled by hyp claude-desktop'

The claude-desktop plugin's own activate() docblock opens by retiring exactly that premise (hypaware-core/plugins-workspace/claude-desktop/src/index.js:41-45):

Corrects LLP 0115's "no writable settings file" premise: the live-test findings in LLP 0133 identify the managed-preferences plist [...] as a real local surface

Ask: name hyp claude-desktop install in the hyp attach help body, drop or soften the "no user-writable settings file" clause to match LLP 0133, and correct the PR description - a claim presented as "found by verifying rather than transcribing" should not be the one claim in the PR that was not verified.


2. [Medium] Deleting hypaware-sensitive-scan drops a trigger surface hypaware-privacy does not cover

The argument that the two skills contradicted each other on purge is correct and worth acting on. But the chosen fix removes one and leaves the survivor's contract untouched: hypaware-privacy/SKILL.md is not modified by this PR at all.

hypaware-core/plugins-workspace/claude/skills/hypaware-privacy/SKILL.md:3 is scoped to enrollment:

Review this machine's captured Claude/Codex history with the user before it first syncs to the org server. Use when the user says "review before sync", "privacy review", "what will ship to the server", after a hyp remote login printed a first-sync deadline [...]

and the body (:11) opens "When hyp remote login enrolls this machine, the first sync to the org server is held until a printed deadline", then runs six steps built around that hold (Step 2 waits for backfill to settle, Step 5 marks directories for the deferred sync).

The deleted skill's description carried a different, non-enrollment surface: "scan my logs for secrets", "what should I hypignore", "did I record anything sensitive", plus "Asks which source to scan (local logs or a remote server) first". After this PR:

  • a local-only, never-enrolled user asking "did I record anything sensitive?" matches no skill description;
  • scanning a remote server's rows has no entry point at all (hypaware-privacy is local-machine only).

docs/PRIVACY.md was updated to fold the sampling language into hypaware-privacy (and that text is accurate - Step 3 does sample, Step 5 does redact), but the skill's own frontmatter, which is what actually triggers it, was not.

Ask: broaden hypaware-privacy's description to absorb the any-time-audit triggers and drop the "before first sync" gating from it, or state in the PR that the local-only and remote-scan cases are deliberately dropped.


3. [Medium] disable-model-invocation on hypaware-ignore / hypaware-unignore removes the natural-language opt-out LLP 0066 is written around

hypaware-core/plugins-workspace/claude/skills/hypaware-ignore/SKILL.md:3-4 and .../hypaware-unignore/SKILL.md:3-4.

The PR argues "the affordance is unchanged" because /name stays in the slash menu. That holds for the other three (publish-report, apply-report-changes, report-to-html - genuinely deliberate, user-initiated pipeline steps; no objection there). It does not hold for this pair, which is the one case where the natural-language trigger was the product. The descriptions being deleted are exactly those utterances:

  • master hypaware-ignore: Use when the user says "don't record this", "ignore this session", "pause logging", or otherwise asks to opt this conversation out
  • master hypaware-unignore: Use when the user says "resume recording", "unignore this session"

And llp/0066-session-opt-out.spec.md:10-13 opens on that utterance and treats the skills as the contract:

"Don't record this conversation": a temporary, in-memory, session-scoped drop [...] The @hypaware/claudehypaware-ignore / hypaware-unignore skills already specify the contract

:28 - "This spec closes that gap without changing the skills. The skills are the contract."

After this change, a user who says "don't record this" gets nothing; they have to already know /hypaware-ignore exists. For a privacy opt-out, discovery is the feature.

Secondary, and it applies to all five: grep -rn "disable-model-invocation" llp/ returns nothing. Hiding five shipped skills from model invocation is a non-obvious design decision in the Plugins/Skills system, and CLAUDE.md asks for the LLP edit to land in the same commit as the code, with an @ref where the decision is realized. Neither is here.

Ask: keep model invocation enabled for hypaware-ignore / hypaware-unignore, and land an LLP decision recording the policy for the remaining three (hypaware-privacy cites the /hypaware-ignore mechanism at LLP 0100 R3, so the interaction deserves to be written down either way).


4. [Low] hyp init now has two usage strings that disagree

src/core/cli/core_commands.js:233:

usage: 'hyp init [preset] | hyp init --yes [--client <name>] [--source <name>] [--force]',

--yes reads as required in the second form and only three flags exist. Neither is true. src/core/commands/init.js:406-413 enters the non-interactive path on any of --yes -y --no-daemon --dry-run --client --source --export --retention-days --from-file --bin --force, and the command's own error-path usage (src/core/commands/init.js:188) is:

usage: hyp init [--yes] [--client <name>] [--source <name>] [--export <choice>] [--retention-days <n>] [--from-file <path>] [--no-daemon] [--dry-run] [--force] [--bin <path>]

A user who reads --help and a user who fumbles a flag now get different answers for the same command. Prefer making the registry usage match the parser's, or reduce both to a common short form and let the help body carry the rest.

5. [Low] Unicode ellipsis introduced, and it misquotes the line it is quoting

hypaware-core/plugins-workspace/claude/skills/hypaware-reference/SKILL.md:24 and the codex copy at :24:

hyp status marks each client configured/attached and prints a syncing: … local-only: … line

Two things: the repo's style is ASCII punctuation in runtime strings and docs (CLAUDE.md bans U+2014 for the same reason; is the same class of character), and the real line is --separated, not space-separated - src/core/commands/status.js:358 emits syncing: ${...} - local-only: ${...}. Rendering it as syncing: ... - local-only: ... would be both ASCII and accurate.

6. [Nit] LLP 0098 is an ambiguous citation, and not in @ref form

src/core/cli/dispatch.js:643-645 cites (LLP 0098) in prose. llp/ currently holds two 0098s - 0098-inactive-not-unknown-dispatch-miss.decision.md (the one meant) and 0098-scancolumn-where-pushdown.decision.md. The duplicate numbering is pre-existing and not this PR's fault, but a bare number no longer resolves. CLAUDE.md's form is // @ref LLP 0098#anchor: gloss, which /ref-check can validate; prose parentheses cannot.

7. [Nit] The new help epilogue garden-paths

src/core/cli/dispatch.js:646-647:

running a command a disabled plugin provides names that plugin and prints how to enable it

Three bare nouns in a row before the verb arrives. Something like "if a command is missing, run it anyway - hyp names the plugin that provides it and prints how to enable it" carries the same fact.

8. [Nit] PR body arithmetic

"npm test: 2781/2784. The two failures are pre-existing" - that leaves one of the three unaccounted for. Probably a skip, but worth naming so the next reader does not re-derive it.


Review-only rung (LLP 0032): no push to skills/trim-and-cli-help, no ready/merge. Findings above are for the author to act on.

@philcunliffephilcunliffe added the neutral:changes-requested neutral reviewed an adopted PR and requests changes (non-binding; maintainer decides) label Jul 29, 2026

@philcunliffephilcunliffe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes. Full review record with evidence: #436 (comment)

Three blocking items, each a place where the PR removes information on a premise that does not survive checking:

  1. hyp claude-desktop install does exist. It is registered at hypaware-core/plugins-workspace/claude-desktop/src/index.js:109-121 (the LLP 0135 picker configure_command) and tested in test/plugins/claude-desktop-install.test.js. The PR description presents its nonexistence as a verified correction; the effect in the diff is that the concrete command a Claude Desktop user needs is replaced by a vaguer pointer at hyp claude-desktop --help. Also, src/core/cli/core_commands.js:272-273 asserts Claude Desktop "exposes no user-writable settings file", which is the premise LLP 0133 retires (see the activate() docblock at .../claude-desktop/src/index.js:41-45).

  2. Deleting hypaware-sensitive-scan drops a surface hypaware-privacy does not cover.hypaware-privacy/SKILL.md is unmodified by this PR, and both its description (:3) and body (:11) are gated on the pre-first-sync enrollment review. A local-only, never-enrolled user asking "did I record anything sensitive?" now matches no skill, and the deleted skill's remote-server scan target has no replacement. docs/PRIVACY.md was updated; the frontmatter that actually triggers the skill was not.

  3. disable-model-invocation: true on hypaware-ignore / hypaware-unignore removes the natural-language opt-out. The deleted descriptions were exactly the utterances LLP 0066 is written around ("don't record this", "ignore this session"); llp/0066-session-opt-out.spec.md:10-13,28 treats those skills as the contract and says the spec closes the gap without changing the skills. "The affordance is unchanged" holds for the slash menu only. For a privacy opt-out, discovery is the feature. No objection to the same key on the three report skills, but nothing in llp/ records the decision and no @ref was added.

Plus two low (hyp init now carries two disagreeing usage strings; a Unicode ellipsis that also misquotes the syncing: ... - local-only: ... line it cites) and three nits, detailed in the record comment.

The mechanical work is clean and verified: manifest / index.js / on-disk skill parity holds in both trees (10/10/10 and 8/8/8), no dangling hypaware-sensitive-scan reference survives, no em dash is introduced, dispatch tests pass 32/32 at this SHA, and the package_bin_boot smoke only prefix-matches the header line the PR edits.

bgmcmullenand others added 6 commits July 29, 2026 10:41
The attach help pointed at `hyp claude-desktop --help` on the premise that
`hyp claude-desktop install` did not exist. It does: it is registered in
`activate()` (claude-desktop/src/index.js) as the LLP 0135 picker's
`configure_command`, alongside `claude-desktop verify`.
Also drops the "exposes no user-writable settings file" clause, which is
the LLP 0115 premise LLP 0133#plist-surface retires: Desktop does have a
real local surface, the root-owned managed-preferences plist.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The six steps always ran any time (the skill's own closing note says
re-running later is safe and idempotent), but the description gated every
trigger clause on the deferred first sync, and it carried none of the
vocabulary the retired hypaware-sensitive-scan used to answer: secrets,
credentials, PII, "did I record anything sensitive", "what should I
hypignore". A never-enrolled machine is the default state, so that left
the most common way to ask for this review matching nothing.
Rewrites the description around the audit itself and keeps the enrollment
triggers as what they are: the standard time to run it, not a gate. Also
reframes the title, intro, Step 2 and the closing notes so an unenrolled
reader is not told about a deadline that does not apply to them. No step
changes.
States the local-cache-only scope explicitly. Scanning a remote server's
rows, which hypaware-sensitive-scan offered, has no replacement.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Records two decisions this branch was making implicitly.
One privacy surface: hypaware-sensitive-scan shipped without an LLP and
contradicted LLP 0100 R7 on purge (it promised prospective opt-outs only;
0100 requires purge be offered for every `ignore`). Retiring it needed no
supersede or tombstone since nothing in llp/ referenced it, but the
resulting scope does need recording: hypaware-privacy is local-cache only,
and dropping the remote-server scan is deliberate. Scanning an org server
from a member's laptop is impractical and the remedies are machine-local
anyway; server-side review belongs behind an operator surface.
Model invocation: mark a bundled skill user-invoked only when invoking it
publishes, mutates, or spends. That holds for the three report pipeline
steps. It does not hold for hypaware-ignore / hypaware-unignore, so this
restores their descriptions and drops the key: LLP 0066 is written around
the spoken "don't record this conversation", and LLP 0107#gating already
says hypaware-ignore is useful unenrolled and that per-skill carve-outs
lose to one rule. For a privacy opt-out, discovery is the feature.
Also refs the ungating in 0142#any-time back to 0107#gating, which had
already decided it, and notes the any-time framing in docs/PRIVACY.md.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The registry usage string said `hyp init [preset] | hyp init --yes
[--client <name>] [--source <name>] [--force]`, which states two false
things: that --yes is a required prefix for the non-interactive path, and
that four flags exist. Neither holds. INIT_FLAG_NAMES routes to the
non-interactive path on any of ten flags, so `hyp init --dry-run` needs no
--yes, and six flags were invisible to anyone reading --help.
`hyp init` states its interface in three reachable places: this registry
entry, the non-TTY/unknown-flag hint (init.js:123,139), and the parser's
own usage, which fires when --help is not the first token because dispatch
intercepts only rest[0] while parseCommandArgv matches --help anywhere.
The other two were already accurate; only this one was wrong.
Shortens usage to `hyp init [preset] [flags]` and moves the full list into
the help body the PR had just given this command, checked flag by flag
against the parser (--from-file takes a v2 config, not answers; --force
backs up before replacing; --yes supplies claude + otel only when no
--source is given).
Exports INIT_FLAG_NAMES and pins both properties in a test, so the help
body cannot drift from the dispatcher again.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The sentence quoted a `syncing: ... local-only: ...` line three ways wrong:
a Unicode ellipsis where the repo wants ASCII, whitespace where
status.js:358 emits ` - `, and, worst, flatly as something `hyp status`
prints. That write is guarded by `if (report.clientSync)`, which is null on
a solo host (LLP 0132 #never-silent), so the line never appears for the
default install. A reader was being sent to look for output that is not
there.
Describes what the command does instead of reproducing its output, which
is the drift this PR is otherwise about, and avoids re-encoding the ` · `
list separator the real line also carries.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two nits from review.
The epilogue cited `(LLP 0098)` in prose, which /ref-check cannot validate
and which no longer resolves: llp/ holds two 0098s (dispatch-miss and
scancolumn-where-pushdown), pre-existing duplicate numbering. An anchor was
the obvious fix, except both docs also have a `## Decision` heading, so the
`#decision` slug dispatch.js:250 already used was ambiguous too. Adds an
explicit `unavailable-not-unknown` anchor to the dispatch-miss doc (purely
additive; no wording touched on an Accepted doc) and points both refs at it.
The epilogue itself stacked three bare nouns before its verb: "running a
command a disabled plugin provides names that plugin". Rewritten as a
conditional the reader can follow on one pass. Nothing asserts this text;
package_bin_boot only prefix-matches the header line, and it passes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@bgmcmullenbgmcmullen removed the neutral:changes-requested neutral reviewed an adopted PR and requests changes (non-binding; maintainer decides) label Jul 29, 2026
@bgmcmullen

Copy link
Copy Markdown
ContributorAuthor

Thanks, this was a good catch list. All seven findings are addressed at 3a78567; CI is green (8/8). Walking them in order, including three places where the fix differs from what was asked.

1. hyp claude-desktop install (medium) - fixed, 9deaac7

You're right and the PR description was wrong. The command is registered in activate(), and claude-desktop verify next to it. The false negative came from checking only the statically declared commands in hypaware.plugin.json and never reading the runtime registrations, which is exactly the failure mode this PR is supposed to be about.

hyp attach --help now names both commands directly, so the CLI is more actionable than the skill text it replaced rather than less. The "exposes no user-writable settings file" clause is gone, replaced by the root-owned managed-preferences plist per LLP 0133#plist-surface. PR description retracted in place.

2. hypaware-sensitive-scan trigger surface (medium) - fixed, 77d42fd + 4711975

Took the broaden-the-description branch. Two refinements to the framing:

It wasn't a new concession. LLP 0107#gating already held that "enrolled-ness gates behavior, not presence" and that the skill's deadline framing "simply does not arise without a pending first sync". The description had been out of step with an Accepted decision since before this PR. The six steps are unchanged; the title, intro, Step 2 and closing notes are reframed so an unenrolled reader isn't told about a deadline that can't apply to them.

The remote-server scan is a deliberate drop, not an oversight. Scanning an org server's whole history from one member's laptop isn't practical: unbounded row volume, and the remedies (hyp policy set, hyp purge) are machine-local and can't reach forwarded rows anyway. Server-side review is an operator concern and belongs behind an operator surface. That's recorded in LLP 0142#local-cache-scope, and the skill's description states the boundary so the gap is visible rather than assumed.

One thing that strengthens the original retire: the two skills didn't just overlap, they disagreed against a spec. hypaware-sensitive-scan promised "PROSPECTIVE opt-outs only ... it does NOT purge already-recorded rows" while LLP 0100 R7 requires the review offer hyp purge for every ignore. The undocumented skill was the one out of step.

3. disable-model-invocation (medium) - fixed, 4711975

Agreed, and reverted for hypaware-ignore / hypaware-unignore with their descriptions restored. Your LLP 0066 argument is right, and LLP 0107#gating supports it independently: it names hypaware-ignore as useful unenrolled and says per-skill carve-outs lose to one rule.

LLP 0142 now records the policy, with the test written as: mark a bundled skill user-invoked only when invoking it publishes, mutates, or spends. That keeps the key on the three report skills and off these two. @refs on all five files. The doc also notes the asymmetry you'd otherwise hit next: the key is Claude Code only, so the Codex copies of the report skills stay model-invocable regardless, which is tolerable because it's a discoverability preference and not a safety control.

4. hyp init usage strings (low) - fixed, 3e159cd, with a correction

The finding is right, the specifics are slightly off. There are three reachable strings, not two:

  1. the registry entry, rendered by hyp init --help
  2. the non-TTY / unknown-flag hint at init.js:123,139
  3. the parser's own usage at init.js:188

A user who fumbles a flag gets #2, not #3. #3 fires only when --help is not the first token, because dispatch.js:343 intercepts only rest[0] while parseCommandArgv (verb_codec.js:222) matches --help anywhere in argv, so hyp init --yes --help reaches it. Of the three, only the registry entry was wrong, in the two ways you identified.

usage is now hyp init [preset] [flags] and the full list moved into the help body, checked flag by flag against the parser (two of my first-pass descriptions were wrong: --from-file takes a complete v2 config rather than "the answers", and --force backs up before replacing). INIT_FLAG_NAMES is exported and test/core/cli/init-help-flags.test.js pins both properties, so this can't drift again. Both assertions verified non-vacuous against the pre-fix strings.

5. Unicode ellipsis and the misquote (low) - fixed, 9f47389

Both correct, and there's a third error in the same sentence: the line is guarded by if (report.clientSync), which is null on a solo host (LLP 0132 #never-silent). So it never prints on the default install, and the skill was flatly telling readers to look for output that isn't there.

Rather than quote it accurately I dropped the literal quote and described the behaviour. A skill reproducing exact CLI output is the drift this PR exists to remove, so a corrected quote just resets the clock. It also avoids re-encoding the · separator the real line carries inside each half.

6. LLP 0098 citation (nit) - fixed, 3a78567, with a wrinkle

An anchor alone doesn't fix this: both 0098s also have a ## Decision heading, so the #decision slug dispatch.js:250 was already using had exactly the same ambiguity. Added an explicit unavailable-not-unknown anchor to the dispatch-miss doc (purely additive, no wording touched on an Accepted doc) and repointed both refs at it. The duplicate numbering itself is left alone as pre-existing.

7. Epilogue phrasing (nit) - fixed, 3a78567

Rewritten close to your suggestion:

This list reflects the plugins active in your config. If a command you
expect is missing, run it anyway: hyp names the plugin that provides it
and prints how to enable it.

8. Arithmetic (nit)

The missing third was the skip. Current local numbers: 2786 tests, 2783 pass, 2 fail, 1 skip. The two failures are blob-store.test.js (all 14 subtests pass, the file exits nonzero) and query-sql-budget.test.js's heap-growth test (7/7 in isolation, flaky under full-suite memory pressure). Neither reproduces in CI, which is green at this SHA, so both look like local-environment artifacts on my machine rather than repo state.

@philcunliffe

Copy link
Copy Markdown
Contributor

neutral re-review - PR #436 @ 3a78567

Verdict: request-changes (0 medium, 1 low)

Re-reviewed in an isolated detached worktree at 3a785678093ba393a8d34305f2e1128a98d0f793, judging the six new commits (9deaac7 .. 3a78567) against the eight findings recorded at 357f55c. Codex is not available on this host, so this is again a single-family (Claude) review.

All eight prior findings are addressed, and in three places the fix is better than what was asked for because the author found a further error while making it (the if (report.clientSync) guard, the shared #decision ambiguity across both 0098s, and the two wrong flag descriptions in the first-pass help body). The new llp/0142 is a real decision doc, not a rubber stamp: it names the test, records the asymmetry it creates, and says what a future reinstatement would have to be.

One thing is left, and it is one line in two files. It is a residue of finding 2 rather than a new topic, and it is the reason this is request-changes rather than approve. There is no other objection: fix that line and I will approve.


Prior findings at this head

#Finding (@ 357f55c)Status @ 3a78567
1[Med] hyp claude-desktop install does exist; "no user-writable settings file" restates a retired premiseADDRESSED
2[Med] Deleting hypaware-sensitive-scan drops a surface hypaware-privacy does not coverADDRESSED (one residue, see New/L1)
3[Med] disable-model-invocation on hypaware-ignore / hypaware-unignoreADDRESSED
4[Low] hyp init carries two disagreeing usage stringsADDRESSED
5[Low] Unicode ellipsis that also misquotes the syncing: ... - local-only: ... lineADDRESSED
6[Nit] Bare LLP 0098 citation, ambiguous and not in @ref formADDRESSED
7[Nit] Help epilogue garden-pathsADDRESSED
8[Nit] PR body test arithmeticADDRESSED

1 - ADDRESSED (9deaac7)

The command exists, and it still exists on today's master: hypaware-core/plugins-workspace/claude-desktop/src/index.js:118 (claude-desktop install) and :132 (claude-desktop verify), both registered unconditionally in activate(). PR #445 (74aea66) removed only the manifest attach_probe; it did not touch these registrations, so the finding's premise is intact against current master.

src/core/cli/core_commands.js:284-295 now names both commands. Rendered:

Claude Desktop has no
such settings file: its configuration surface is a root-owned
managed-preferences plist. Set it up with hyp claude-desktop install
(attended, with a sudo prompt) and check it with hyp claude-desktop
verify, when that plugin is active.

The retired premise is gone and what replaces it matches the plugin's own account line for line: index.js:41-50 gives the managed-preferences plist as the real surface per LLP 0133, and "the plist is placed only via the explicit claude-desktop install command, attended, with its own sudo prompt". The help is now strictly more actionable than the hypaware-reference text it replaced, which was the ask. It also does not claim attach-on-join for Claude Desktop, so it reads correctly against #445's landed state (llp/0115#no-attach-on-join, restored at index.js:54-60).

2 - ADDRESSED (77d42fd, 4711975), with one residue

hypaware-privacy/SKILL.md:3 (both trees) now leads with the audit and carries the deleted skill's vocabulary verbatim: "did I record anything sensitive", "scan my logs for secrets", "what should I hypignore", plus an explicit "Runs any time". The first sync is retained as the standard occasion rather than the gate, which is the shape llp/0107#gating asks for, and I confirmed that anchor and both quoted sentences are real: llp/0107-skills-ride-attach.decision.md:75 is - **Enrolled-ness gates behavior, not presence** {#gating}: and :79-81 carries "the skill's deadline framing simply does not arise without a pending first sync" and "hypaware-ignore are useful unenrolled, and one install rule beats per-skill carve-outs". So the claim that the description had been out of step with an Accepted decision holds; it is not a retrofit.

The body follows the description rather than lagging it: the intro, the Step 2 settlement note, and both "After the review" bullets now branch on enrolled vs not. The remote-server drop is stated in the description's last clause and reasoned in llp/0142#local-cache-scope, so it is a visible boundary. That satisfies the ask as written ("or state in the PR that the local-only and remote-scan cases are deliberately dropped") and does better by stating it in the artifact rather than only in the PR.

Not a regression, for the record: the privacy skill body contains no newest-rollout-by-mtime session resolution, so this PR is neutral to issue #452 and to PR #450's CODEX_THREAD_ID change.

3 - ADDRESSED (4711975)

Fully reverted. git diff <merge-base>..HEAD on hypaware-ignore/SKILL.md and hypaware-unignore/SKILL.md shows the descriptions byte-identical to master, the key gone, and the net change reduced to an added @ref (plus one em dash removed from hypaware-unignore). llp/0142#user-invoked-only records the policy with the test stated as publishes / mutates / spends, names all three skills it does cover and why it does not cover these two, and calls out the Claude-only nature of the key. @refs are on all five files.

4 - ADDRESSED (3e159cd)

usage is now hyp init [preset] [flags] and the flag list moved into the help body. I checked all ten descriptions against the parser rather than against the old string:

  • --yes "captures claude + otel when no --source is given" matches init.js:247-251 (the push happens only when sources.length === 0 && flags.yes).
  • --client "claude, codex" matches the enum at init.js:179.
  • --export choices match init.js:181.
  • --from-file "write a v2 config read from this JSON file" matches runInitFromFile at init.js:303-325 (read, JSON.parse, validateConfig), not "the answers".
  • --force "backed up first" matches prepareLocalConfigWrite / guard.backupPath at init.js:356-362.

The help body's framing sentence is precise about the routing rather than overclaiming: "the non-interactive path is chosen by the presence of a flag, so --yes is a way to ask for it with no other options, not a prefix the other flags need". That is exactly hasInitFlags (init.js:145-153). The two new tests in test/core/cli/init-help-flags.test.js both ran and passed in my run (ok 297, ok 298), and the second one is a real property test, not a string echo. The registry usage no longer disagrees with the init.js:123,139 hint (which carries a trailing ... and so claims nothing exhaustive) or with init.js:188.

5 - ADDRESSED (9f47389)

The quote is gone in both trees. The replacement at hypaware-reference/SKILL.md:22-25 is accurate: "on a fleet-managed host also splits them into what the fleet forwards and what stays local, so a local addition is never invisible" is the report.clientSync branch at src/core/commands/status.js:349-360, including the guard the author found, and "them" correctly refers to clients, which is what that block splits. No · re-encoding, and no exact-output reproduction to go stale.

Whole-diff character check: git diff <merge-base>..HEAD introduces zero non-ASCII bytes of any kind, so no em dash, no Unicode ellipsis, no middle dot. That is stronger than the PR body's claim and I verified it directly.

6 - ADDRESSED (3a78567)

llp/0098-inactive-not-unknown-dispatch-miss.decision.md:22 gains <a id="unavailable-not-unknown"></a>, purely additive above the existing ## Decision. <a id=...> is established convention here (29 files in llp/ use it). Both refs repoint: dispatch.js:250 and the new dispatch.js:645. The author's extra point is correct and was worth making: an anchor of #decision would not have disambiguated, because 0098-scancolumn-where-pushdown.decision.md also has a ## Decision.

I validated every anchored @ref in the repo at this head and at master with the same checker (<a id> plus {#anchor} plus heading slugs). Head: 1075 anchored refs. Master: 1118. Set difference of broken refs, head minus master, path-normalized: empty. This PR introduces no broken @ref, and all nine of its new ones resolve.

7 - ADDRESSED (3a78567)

Rendered from a real hyp --help run in the worktree:

This list reflects the plugins active in your config. If a command you
expect is missing, run it anyway: hyp names the plugin that provides it
and prints how to enable it.

8 - ADDRESSED

2786 tests, 2783 pass, 2 fail, 1 skip is self-consistent. Different numbers here for environment reasons, also self-consistent: 2785 tests, 2776 pass, 8 fail, 1 skip, and all eight failures are the known pre-existing test/core/leave-command.test.js baseline (not ok 803, 804, 805, 807, 808, 809, 810, 811). Nothing this PR touches fails.


New findings

L1 [Low] The hypaware-reference hand-off still gates hypaware-privacy on the first sync, contradicting llp/0142#any-time that this PR lands

hypaware-core/plugins-workspace/claude/skills/hypaware-reference/SKILL.md:82-83 and the codex copy at the same lines:

- Review captured history before it first syncs to an org server - use the
**hypaware-privacy** skill.

This line is added by this PR (2acca60); master's hypaware-reference has no hypaware-privacy hand-off at all. Three commits later, 77d42fd / 4711975 removed exactly that gating from the privacy skill's own description and wrote the reason into llp/0142#any-time: "only the description and the surrounding prose stop implying the flow is unavailable to an unenrolled machine, which is the default state".

Two reasons this is worth one more line of work rather than a follow-up:

  1. It is the residue of finding 2, in the surface that finding was about. With hypaware-sensitive-scan deleted, this hand-off is the only cross-skill pointer from the orientation skill to the privacy audit, and it points there only for the pre-sync case. A model reading hypaware-reference to route "did I record anything sensitive?" on an unenrolled machine, which is the default state, is told this is the enrollment skill.
  2. The sweep was done and this spot was missed, which shows the intent. docs/PRIVACY.md:124-127 got the correction in 77d42fd: "The first sync is the moment this matters most, but it is not a precondition: run hypaware-privacy whenever you want to know what has been captured here, enrolled or not." The reference skill did not.

I swept every other hypaware-privacy mention in the tree and this is the only inconsistent one. src/core/cli/wizard/index.js:330, src/core/cli/remote_commands.js:229, src/core/commands/status.js:385 and README.md:124 are all inside enrollment flows, where llp/0142#any-time explicitly keeps the framing ("the enrollment framing is retained where it applies").

Ask: reword that bullet to lead with the audit, in both trees. Something like "See what was captured here, and mark or purge it - use the hypaware-privacy skill (also the review before an enrolled machine's first sync)."


Also checked, no finding


Review-only rung (LLP 0032): no push to skills/trim-and-cli-help, no ready, no merge. Remote head is unchanged at 3a78567. L1 is the only blocker; it is a one-line prose fix in two files.

@philcunliffephilcunliffe added the neutral:changes-requested neutral reviewed an adopted PR and requests changes (non-binding; maintainer decides) label Jul 29, 2026

@philcunliffephilcunliffe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed at 3a78567. Full record with evidence: #436 (comment)

All eight prior findings are addressed. All three mediums are properly closed, and in three places the fix is better than what I asked for because you found a further error while making it: the if (report.clientSync) guard, the shared ## Decision heading that made an #decision anchor no better than a bare 0098, and the two wrong flag descriptions in the first-pass init help. llp/0142 is a real decision doc rather than a rubber stamp: it states the test, records the Claude-only asymmetry it creates, and says what a future reinstatement would have to be. I also verified your llp/0107#gating citation rather than taking it: the anchor is real (llp/0107-skills-ride-attach.decision.md:75, {#gating} form) and both quoted sentences are verbatim at :79-81, so the "this was already Accepted" framing holds.

Verification I ran independently: every anchored @ref in the tree resolves, and the set of broken refs at this head minus the set at master is empty, so the PR introduces none (1075 anchored refs checked). The whole diff introduces zero non-ASCII bytes, which is stronger than the PR body's em-dash claim. Both new init-help-flags tests ran and passed, and all ten flag descriptions check out against the parser, not against the old string. All eight test failures in my worktree are the known pre-existing leave-command.test.js baseline. The branch merges cleanly against today's master: the only shared file is claude/src/index.js, in disjoint regions. And finding 1's premise still holds after #445, which removed only the manifest attach_probe and left claude-desktop install / verify registered at index.js:118,132.

One thing left, and it is one line in two files.

[Low] The hypaware-reference hand-off still gates hypaware-privacy on the first sync

hypaware-core/plugins-workspace/{claude,codex}/skills/hypaware-reference/SKILL.md:82-83:

- Review captured history before it first syncs to an org server - use the
**hypaware-privacy** skill.

This bullet is added by this PR (2acca60); master's hypaware-reference has no privacy hand-off at all. Three commits later 77d42fd / 4711975 removed exactly that gating from the privacy skill's own description and wrote the reason into llp/0142#any-time: "only the description and the surrounding prose stop implying the flow is unavailable to an unenrolled machine, which is the default state."

Two reasons I would rather see it fixed here than tracked:

  1. It is the residue of finding 2, in the surface finding 2 was about. With hypaware-sensitive-scan gone, this is the only cross-skill pointer from the orientation skill to the privacy audit, and it points there only for the pre-sync case. A model reading hypaware-reference to route "did I record anything sensitive?" on an unenrolled machine, the default state, is told this is the enrollment skill.
  2. The sweep was done and this is the one spot it missed. docs/PRIVACY.md:124-127 got the correction in the same commit: "The first sync is the moment this matters most, but it is not a precondition."

I swept every other hypaware-privacy mention in the tree; this is the only inconsistent one. The wizard, remote_commands.js, status.js and README.md mentions all sit inside enrollment flows, where llp/0142#any-time explicitly keeps the framing.

Suggested reword, both trees: "See what was captured here, and mark or purge it - use the hypaware-privacy skill (also the review before an enrolled machine's first sync)."

No other objection. Fix that bullet and I will approve.

Review-only rung (LLP 0032): no push to skills/trim-and-cli-help, no ready, no merge.

… sync
The bullet added in 2acca60 gated the hypaware-privacy hand-off on the
first sync to an org server, which is exactly the framing 77d42fd and
LLP 0142#any-time removed from the skill itself. Reword it to lead with
the any-time audit and keep the pre-first-sync review as the
parenthetical occasion, in both trees.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@philcunliffe

Copy link
Copy Markdown
Contributor

Neutral review record - round 3, head e81e5eae

Previously reviewed head: 3a785678. The push is a single commit,
e81e5ea hypaware-reference: lead the privacy hand-off with the audit, not the sync,
touching exactly two files (both hypaware-reference/SKILL.md copies).

L1 (Low, round 2's only outstanding finding): ADDRESSED

hypaware-core/plugins-workspace/claude/skills/hypaware-reference/SKILL.md:82-84
and hypaware-core/plugins-workspace/codex/skills/hypaware-reference/SKILL.md:82-84
now read:

- See what was captured here, and mark or purge it - use the
**hypaware-privacy** skill (also the review before an enrolled machine's
first sync).

This is the right correction, for the right reason:

  • The bullet now leads with the audit itself and demotes the first sync to a
    parenthetical occasion, which is exactly llp/0142#any-time: "the description
    advertises the any-time audit; the first sync is the standard occasion, not a
    gate" (llp/0142-privacy-surface-and-skill-discoverability.decision.md:53-60).
  • It matches the wording the privacy skill applies to itself -
    hypaware-core/plugins-workspace/claude/skills/hypaware-privacy/SKILL.md:3
    ("Runs any time. ... It is also the standard review before an enrolled
    machine's first fleet sync") - and the correction already made in
    docs/PRIVACY.md:124-127 ("The first sync is the moment this matters most,
    but it is not a precondition").
  • With hypaware-sensitive-scan deleted, this is the only cross-skill pointer
    to the privacy audit, and it no longer routes only the pre-sync case.
  • grep -rn "before it first syncs" over the tree at this head returns nothing:
    no stale copy of the old gating phrasing survives anywhere.

Not raised as a finding: the bullet does not restate llp/0142#local-cache-scope
(local cache only, no remote-server scan). Stating that boundary is the privacy
skill's own description job per that section, and a one-line hand-off pointer
restating it would be noise.

Nothing new introduced by the push

Verdict

All eight round-1 findings were confirmed addressed at 3a785678; the sole
remaining Low is now addressed with an accurate one-line prose fix, and the push
introduced nothing new. Approving, as round 2 said it would.

@philcunliffephilcunliffe added the neutral:approved neutral reviewed this and holds it for a maintainer merge (own or adopted PR; LLP 0025/0030) label Jul 29, 2026
@philcunliffe

Copy link
Copy Markdown
Contributor

Verdict at e81e5eae9621db0c32c36da9017576a1d84338c1: approved (neutral:approved).

Round 2's single outstanding Low is addressed: the hypaware-reference hand-off bullet now leads with the any-time audit and treats the first sync as an occasion rather than a gate, matching llp/0142#any-time, the hypaware-privacy skill's own description, and docs/PRIVACY.md:124-127. The push added no non-ASCII, no new broken @refs, and left the test baseline unchanged (8 known leave-command failures only). Full evidence in the review record comment above.

Review-only per LLP 0032: nothing pushed to skills/trim-and-cli-help, no ready/merge action taken.

@bgmcmullen
bgmcmullen merged commit f9b9667 into masterJul 29, 2026
8 checks passed
@bgmcmullen
bgmcmullen deleted the skills/trim-and-cli-help branch July 29, 2026 22:09
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

neutral:approvedneutral reviewed this and holds it for a maintainer merge (own or adopted PR; LLP 0025/0030)neutral:reviewDelegate this PR to neutral for a review pass (approve or request changes; never merges)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bgmcmullen@philcunliffe