Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ WHERE cwd = '<dir>' ORDER BY date DESC LIMIT 40" --format json --output /tmp/sam

Before you propose or apply **anything**, explain the classes in plain language, including what the org can and cannot see in each case:

- **ignore** (`hyp ignore --private <dir>`): never recorded going forward; the machine-local rule stops capture at the source. Existing cached rows are **purgeable** (Step 6) but are not removed by marking alone. The org sees **nothing** from this directory.
- **local-only** (`hyp ignore --local-only <dir>`): recorded and queryable **here** on this machine, but **never forwarded**. Withheld at the export seam. The org sees **nothing**, while you keep local history.
- **sync** (`hyp ignore --sync <dir>`): the explicit "this ships" choice - forwarded to the org server like the default. Marking `--sync` records an explicit decision so this directory is not asked about again. The org sees this directory's captured exchanges.
- **ignore** (`hyp policy set <dir> ignore`): never recorded going forward; the machine-local rule stops capture at the source. Existing cached rows are **purgeable** (Step 6) but are not removed by marking alone. The org sees **nothing** from this directory.
- **local-only** (`hyp policy set <dir> local-only`): recorded and queryable **here** on this machine, but **never forwarded**. Withheld at the export seam. The org sees **nothing**, while you keep local history.
- **sync** (`hyp policy set <dir> sync`): the explicit "this ships" choice - forwarded to the org server like the default. Marking it `sync` records an explicit decision so this directory is not asked about again. The org sees this directory's captured exchanges.

Name the trade honestly: `local-only` keeps your history usable locally; `ignore` is stronger (nothing is even recorded once marked) but you lose local queryability too.

Expand All @@ -112,14 +112,14 @@ Then **apply nothing without per-item user confirmation.** Propose, wait for a y
Apply each confirmed decision **only** through the `hyp` verbs below. **Never** author policy files or write anything into the user's repositories - the machine-local store is the only target.

```bash
hyp ignore --private <dir> # class: ignore (stop recording this dir)
hyp ignore --local-only <dir> # class: local-only (record here, never forward)
hyp ignore --sync <dir> # class: sync (explicit "this ships")
hyp ignore --check <dir> # report the governing source + class, and residual cached rows; never writes
hyp unignore --private|--local-only|--sync <dir> # symmetric removal per class
hyp policy set <dir> ignore # class: ignore (stop recording this dir)
hyp policy set <dir> local-only # class: local-only (record here, never forward)
hyp policy set <dir> sync # class: sync (explicit "this ships")
hyp policy show <dir> # report the governing source + class, and residual cached rows; never writes
hyp policy unset <dir> [class] # remove markings (class-neutral by default; a trailing class scopes it)
```

`hyp ignore --check <dir>` names **which source governs** (a committed `.hypignore` dotfile vs a machine-local entry) and the entry's class, and reports how many already-cached rows still sit under it - the residue that purge (below) clears. Marking is always **non-destructive**: it changes future capture/forwarding, not existing cached rows.
`hyp policy show <dir>` names **which source governs** (a committed `.hypignore` dotfile vs a machine-local entry) and the entry's class, and reports how many already-cached rows still sit under it - the residue that purge (below) clears. Marking is always **non-destructive**: it changes future capture/forwarding, not existing cached rows.

**For every directory you mark `ignore`, and every session you flag as sensitive, offer `hyp purge` as a separately confirmed step** so that "completely ignored" also means "not sitting in the cache". Purge is destructive and cache-only (it never contacts the server); confirm each purge on its own.

Expand All @@ -129,10 +129,10 @@ hyp purge --session <id> # delete all cached rows for one session (cheapest:
hyp purge --ignored # sweep every cached row whose cwd currently resolves to `ignore`
```

Purge prompts for confirmation on a TTY; it errors on a bare `hyp purge` with no target. Sequencing matters: **mark `--private` first, then purge** - purging a directory that still resolves to `sync`/default warns that the next backfill will re-import it. Once a directory is `ignore`d, the capture seam blocks re-import, so the purge is durable. A common close-out for a directory the user wants fully gone:
Purge prompts for confirmation on a TTY; it errors on a bare `hyp purge` with no target. Sequencing matters: **mark the directory `ignore` first, then purge** - purging a directory that still resolves to `sync`/default warns that the next backfill will re-import it. Once a directory is `ignore`d, the capture seam blocks re-import, so the purge is durable. A common close-out for a directory the user wants fully gone:

```bash
hyp ignore --private <dir> && hyp purge <dir>
hyp policy set <dir> ignore && hyp purge <dir>
```

## After the review
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ WHERE cwd = '<dir>' ORDER BY date DESC LIMIT 40" --format json --output /tmp/sam

Before you propose or apply **anything**, explain the classes in plain language, including what the org can and cannot see in each case:

- **ignore** (`hyp ignore --private <dir>`): never recorded going forward; the machine-local rule stops capture at the source. Existing cached rows are **purgeable** (Step 6) but are not removed by marking alone. The org sees **nothing** from this directory.
- **local-only** (`hyp ignore --local-only <dir>`): recorded and queryable **here** on this machine, but **never forwarded**. Withheld at the export seam. The org sees **nothing**, while you keep local history.
- **sync** (`hyp ignore --sync <dir>`): the explicit "this ships" choice - forwarded to the org server like the default. Marking `--sync` records an explicit decision so this directory is not asked about again. The org sees this directory's captured exchanges.
- **ignore** (`hyp policy set <dir> ignore`): never recorded going forward; the machine-local rule stops capture at the source. Existing cached rows are **purgeable** (Step 6) but are not removed by marking alone. The org sees **nothing** from this directory.
- **local-only** (`hyp policy set <dir> local-only`): recorded and queryable **here** on this machine, but **never forwarded**. Withheld at the export seam. The org sees **nothing**, while you keep local history.
- **sync** (`hyp policy set <dir> sync`): the explicit "this ships" choice - forwarded to the org server like the default. Marking it `sync` records an explicit decision so this directory is not asked about again. The org sees this directory's captured exchanges.

Name the trade honestly: `local-only` keeps your history usable locally; `ignore` is stronger (nothing is even recorded once marked) but you lose local queryability too.

Expand All @@ -140,14 +140,14 @@ Then **apply nothing without per-item user confirmation.** Propose, wait for a y
Apply each confirmed decision **only** through the `hyp` verbs below. **Never** author policy files or write anything into the user's repositories - the machine-local store is the only target.

```bash
hyp ignore --private <dir> # class: ignore (stop recording this dir)
hyp ignore --local-only <dir> # class: local-only (record here, never forward)
hyp ignore --sync <dir> # class: sync (explicit "this ships")
hyp ignore --check <dir> # report the governing source + class, and residual cached rows; never writes
hyp unignore --private|--local-only|--sync <dir> # symmetric removal per class
hyp policy set <dir> ignore # class: ignore (stop recording this dir)
hyp policy set <dir> local-only # class: local-only (record here, never forward)
hyp policy set <dir> sync # class: sync (explicit "this ships")
hyp policy show <dir> # report the governing source + class, and residual cached rows; never writes
hyp policy unset <dir> [class] # remove markings (class-neutral by default; a trailing class scopes it)
```

`hyp ignore --check <dir>` names **which source governs** (a committed `.hypignore` dotfile vs a machine-local entry) and the entry's class, and reports how many already-cached rows still sit under it - the residue that purge (below) clears. Marking is always **non-destructive**: it changes future capture/forwarding, not existing cached rows.
`hyp policy show <dir>` names **which source governs** (a committed `.hypignore` dotfile vs a machine-local entry) and the entry's class, and reports how many already-cached rows still sit under it - the residue that purge (below) clears. Marking is always **non-destructive**: it changes future capture/forwarding, not existing cached rows.

**For every directory you mark `ignore`, and every session you flag as sensitive, offer `hyp purge` as a separately confirmed step** so that "completely ignored" also means "not sitting in the cache". Purge is destructive and cache-only (it never contacts the server); confirm each purge on its own.

Expand All @@ -157,10 +157,10 @@ hyp purge --session <id> # delete all cached rows for one session (cheapest:
hyp purge --ignored # sweep every cached row whose cwd currently resolves to `ignore`
```

Purge prompts for confirmation on a TTY; it errors on a bare `hyp purge` with no target. Sequencing matters: **mark `--private` first, then purge** - purging a directory that still resolves to `sync`/default warns that the next backfill will re-import it. Once a directory is `ignore`d, the capture seam blocks re-import, so the purge is durable. A common close-out for a directory the user wants fully gone:
Purge prompts for confirmation on a TTY; it errors on a bare `hyp purge` with no target. Sequencing matters: **mark the directory `ignore` first, then purge** - purging a directory that still resolves to `sync`/default warns that the next backfill will re-import it. Once a directory is `ignore`d, the capture seam blocks re-import, so the purge is durable. A common close-out for a directory the user wants fully gone:

```bash
hyp ignore --private <dir> && hyp purge <dir>
hyp policy set <dir> ignore && hyp purge <dir>
```

## After the review
Expand Down
3 changes: 2 additions & 1 deletion src/core/cli/remote_commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,8 @@ async function runBrowserLogin(name, { org, host, noBrowser, noForward, noDaemon
// privacy refinement is now the first-sync review window plus the
// hypaware-privacy skill, run afterwards against a settled cache. Login
// finishes fast; each fork prints the durable-command hint so the CLI floor
// (`hyp ignore --local-only`, `hyp ignore --private`) stays discoverable.
// (`hyp policy set [path] local-only`, `hyp policy set [path] ignore`) stays
// discoverable.

// No sink targets this server yet: provision one so login forwards from one
// command (LLP 0063 D2/D5). enrollCentralSink writes join's sink block, seeds
Expand Down
2 changes: 1 addition & 1 deletion src/core/commands/local_only.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { executeQuerySql } from '../query/sql.js'
// after the in-login picker's retirement (LLP 0102): the review window plus
// the hypaware-privacy skill are the enrollment-time refinement now, and this
// command is the client-independent way to withhold a directory at any time.
export const DURABLE_HINT = "tip: mark a directory local-only anytime with 'hyp ignore --local-only [path]'\n"
export const DURABLE_HINT = "tip: mark a directory local-only anytime with 'hyp policy set [path] local-only'\n"

// The dataset the captured-directory enumeration reads. Exported so the
// hypaware-privacy skill's survey (LLP 0069 #enumerate, LLP 0100 §skill) and
Expand Down
2 changes: 1 addition & 1 deletion src/core/commands/purge.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export async function runPurge(argv, ctx) {
`still record and will be re-imported by the next backfill:\n`
)
for (const dir of resurrectable) ctx.stderr.write(` ${dir}\n`)
ctx.stderr.write("tip: mark them ignored first with 'hyp ignore --private <path>' so the purge is durable\n")
ctx.stderr.write("tip: mark them ignored first with 'hyp policy set <path> ignore' so the purge is durable\n")
}

return 0
Expand Down
2 changes: 1 addition & 1 deletion test/core/purge-command.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ test('runPurge subtree warns about resurrection when the dir still resolves full
assert.equal(code, 0)
assert.match(stderr.text, /still record and will be re-imported/)
assert.match(stderr.text, /home\/u\/repoA/)
assert.match(stderr.text, /hyp ignore --private/)
assert.match(stderr.text, /hyp policy set <path> ignore/)
} finally {
await fs.rm(cacheRoot, { recursive: true, force: true })
await fs.rm(hypHome, { recursive: true, force: true })
Expand Down
8 changes: 4 additions & 4 deletions test/core/remote-login-command.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ test('a --no-daemon login prints the durable hint and provisions the sink (LLP 0

const code = await runRemoteLogin(['prod', '--no-daemon'], ctx, { login })
assert.equal(code, 0)
assert.match(err.join(''), /hyp ignore --local-only/, 'the durable command stays discoverable')
assert.match(err.join(''), /hyp policy set \[path\] local-only/, 'the durable command stays discoverable')
await fs.access(seedPath) // the sink is still provisioned
assert.match(out.join(''), /forwarding logs to https:\/\/hyp\.internal/)
})
Expand All @@ -766,7 +766,7 @@ test('a fresh enroll prints the durable hint and never polls a capture wait (LLP

const code = await runRemoteLogin(['prod'], ctx, { login, enroll, waitForAttach })
assert.equal(code, 0)
assert.match(err.join(''), /hyp ignore --local-only/)
assert.match(err.join(''), /hyp policy set \[path\] local-only/)
assert.match(out.join(''), /capturing @hypaware\/claude/)
})

Expand All @@ -781,7 +781,7 @@ test('a failed daemon install still prints the durable hint before returning (LL
const code = await runRemoteLogin(['prod'], ctx, { login, enroll, waitForAttach })
assert.equal(code, 3)
assert.equal(waited, false, 'a failed install does not wait for attach')
assert.match(err.join(''), /hyp ignore --local-only/)
assert.match(err.join(''), /hyp policy set \[path\] local-only/)
assert.match(err.join(''), /the daemon install did not finish/)
})

Expand All @@ -795,7 +795,7 @@ test('a re-login (already-enrolled, re-seed path) prints the durable hint (LLP 0

const code = await runRemoteLogin(['prod'], ctx, { login })
assert.equal(code, 0)
assert.match(err.join(''), /hyp ignore --local-only/)
assert.match(err.join(''), /hyp policy set \[path\] local-only/)
assert.match(out.join(''), /seeded forwarding identity for sink 'fwd'/)
})

Expand Down