Commit Graph
2282 Commits
Author SHA1 Message Date
thePR0M3TH3ANandClaude Opus 5 e873f7f5ec Remove TORCH -- no longer used
Deletes torch/ (5947 tracked files, 86M) and everything that existed only to
wire it up: torch-config.json, the root package.json and package-lock.json
-- whose sole dependency was torch-lock and whose six scripts were all
torch:* -- and the TORCH Memory Integration sections of CLAUDE.md and
AGENTS.md.

Nothing functional referenced it. No CI workflow mentions torch, no Python
or JS source imports torch-lock, and the only remaining occurrence outside
historical logs is a stray comment in perf/perf_agent.py. The determinism
gate is green after removal.

Two entropy-audit findings disappear with it rather than needing fixes: the
predictable temp filename and the Math.random value misnamed `nonce` (L4,
already fixed in 7047a5d but now moot), and the 18 test failures that bare
`node --test` produced by discovering stale code under torch/_backups/.

Kept deliberately: .scheduler-memory/, memory-update.md and memory-updates/.
Those are accumulated notes rather than tooling, and deleting someone's
notes is a different decision from deleting the tool that wrote them. They
can go separately if wanted.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01HtNMsKzzFTPURemX7tT19u
2026-07-31 22:35:10 -04:00
thePR0M3TH3ANandClaude Opus 5 9e0f045ccb Stop the test suite exiting 0 after 10% of its tests
`pytest src/tests` died at 123 of 1170 tests with exit code 0 -- no summary,
no coverage report, and a shell that saw success. Four tests reach code
paths that call os._exit(0), which skips interpreter finalization and takes
pytest with it.

The os._exit is deliberate and stays: some builds with native extensions
intermittently SIGSEGV during teardown after an otherwise clean shutdown,
which is why _exit_as_main_process exists. But that reasoning applies to the
real process exit, not to a function under test. Adds _terminate(), which
raises SystemExit when PYTEST_CURRENT_TEST is set and calls os._exit
otherwise, and routes the three in-process exit paths through it.

This restores a contract the tests already assumed:
test_auto_sync_triggers_post asserts `pytest.raises(SystemExit)`. It was
written when display_menu raised, and the later switch to os._exit did not
fail that test -- it killed the runner instead, which is why nobody noticed.

The suite now runs to completion: 1160 passed, 15 failed, 16 skipped, and it
exits 1 rather than claiming success.

Those 15 were always failing; they were simply never reached. Five of them
were mine, and this is the uncomfortable part: the gen_version argument
added in 2aed95a broke more FakePasswordGenerator doubles than I found,
because the earlier regression run stopped before reaching them and I
concluded "no new failures" from a truncated result. All 20 remaining
doubles now take **_, so they absorb gen_version and anything added later
rather than needing a sweep each time the real signature grows.

The other 10 are pre-existing and unrelated -- legacy-migration and
checksum-backup failures, an index0.py int-parsing bug
(`invalid literal for int() with base 10: 'temp'`), and one that needs a TTY
this environment lacks.

Determinism gate still green.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01HtNMsKzzFTPURemX7tT19u
2026-07-31 22:31:19 -04:00
thePR0M3TH3ANandClaude Opus 5 3192c9f306 Offer a 24-word master seed, and put the entropy draw beyond reach of any handler
L2: generate_bip85_seed and create_profile_from_generated_seed now take
words_num, accepting 12 or 24 and rejecting anything else with a clear
message. The default stays 12 -- every existing profile uses it, 128 bits is
entirely adequate, and moving the default would change nothing about
existing vaults while surprising anyone creating a new one. 24 is offered
because the master seed protects the whole vault and was the one secret
shorter than the seeds derived beneath it, which already default to 24.

L3: fixed structurally rather than by narrowing exception types.
os.urandom(32) now sits OUTSIDE the try block, so no handler can stand
between the entropy draw and the caller -- an entropy failure is unreachable
by anything that could substitute a value. Also removes a redundant
`except Exception` whose body was identical to the `Bip85Error` branch above
it.

The structural form is stronger than an exception list, and the test says so
precisely: it asserts the OSError reaching the caller is the SAME OBJECT
os.urandom threw, which holds only if nothing caught and repackaged it.
Listing exception types would still leave a handler in the path for someone
to widen later.

Adds five tests: the identity assertion above, 12- and 24-word generation,
the default staying 12, and rejection of 0/11/18/25/-12.

Determinism gate green (89 tests, up from 84). The seed/profile regression
subset is 143 passed with one failure --
test_profile_export_import_round_trip -- confirmed against the pre-change
baseline as pre-existing.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01HtNMsKzzFTPURemX7tT19u
2026-07-31 17:43:24 -04:00
thePR0M3TH3ANandClaude Opus 5 6ac40d2e15 TODO: the versioning constraint now describes what shipped
The intro still said entries carry no algorithm version, which stopped being
true when gen_version landed. Restates the rule in its permanent form -- never
alter the output of a version already in the wild -- rather than as a
description of a gap that is now closed.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01HtNMsKzzFTPURemX7tT19u
2026-07-31 17:35:06 -04:00
thePR0M3TH3ANandClaude Opus 5 7047a5dfed Add an SBOM, and fix the torch randomness nits (L4, L5)
L5: dependency-audit.yml now generates a CycloneDX SBOM from
requirements.lock and uploads it. pip-audit answers "are there known CVEs
today"; an SBOM answers "which exact versions were in this build", which is
the question that arises when something is disclosed later against a release
already in the wild.

Verified against the real tool rather than written from memory -- the first
flag spelling (--output-format / --outfile) does not exist in cyclonedx-py
and would have failed in CI. The working form is
`--of json --output-reproducible -o <file>`, which emits CycloneDX 1.6 with
96 components and records [email protected], [email protected],
[email protected], [email protected], [email protected], [email protected] and
[email protected].0 at exact versions.

L4: torch/services/memory/index.js built its temp filename from Date.now()
plus Math.random() before an atomic rename -- predictable enough to
pre-create or symlink between the write and the rename. Now randomBytes(8).

Also renames the Math.random-derived value in relay-health.mjs from `nonce`
to `probeSuffix` and draws it from randomBytes(6). It is a public probe tag
used to correlate a publish with its readback, not a cryptographic nonce,
and nothing was wrong with it -- but the name invited someone to copy the
pattern somewhere it would matter.

torch has no test/ directory in the repo, so there is no suite to run for
these two files; both were syntax-checked and confirmed to import cleanly.
The SeedPass determinism gate is green (84 tests).

Not done, and recorded as a decision in TODO.md instead: torch/_backups/
holds 5240 tracked files across six dated snapshots. Untracking them is a
large deletion and not something to do as a side effect of an entropy audit.
They currently duplicate every security-relevant grep hit, and bare
`node --test` in torch/ discovers them and fails 18 tests from stale
snapshot code.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01HtNMsKzzFTPURemX7tT19u
2026-07-31 17:34:45 -04:00
thePR0M3TH3ANandClaude Opus 5 2aed95a687 Version password generation; freeze v1, add v2 without the class quota
Passwords are never stored -- they are re-derived on demand from
(seed, index, length, policy) -- and entries carried no algorithm version.
Any change to generate_password therefore changed every existing password in
every vault, unrecoverably. This adds the version field that makes such
changes possible at all, then makes three.

Safety net first (M4). test_entropy_integrity.py freezes 18 v1 vectors
spanning every policy and both sides of the 32-byte stream-wrap boundary,
and asserts the RNG fails closed: os.urandom raising must abort seed
generation, short reads must abort, AES-GCM nonces must be fresh. Each guard
was mutation-verified rather than assumed -- removing _balance_distribution,
perturbing the stream wrap, or altering the character mapping each turns all
18 vectors red, and adding a hash-of-timestamp fallback to
generate_bip85_seed turns the fail-closed test red.

generate_password now takes gen_version, defaulting to 1. Existing entries
carry no field and keep deriving v1 byte-identically; the argument is only
forwarded when non-legacy, so all 13 call sites across CLI, API and both
TUIs are untouched. New password entries are stamped gen_version 2. An
unreadable version raises rather than guessing which algorithm produced a
password.

v2 fixes three findings:
- M1: drops the forced equal-quarters class quota. 1 -> 82 distinct class
  compositions at length 16 over 200 samples; per-character entropy
  6.42 -> 6.53 bits against a 6.555 ceiling.
- M2: rejection sampling instead of byte % len(alphabet). Chi-square 96.1
  against df=93 (p<0.001 critical value ~147).
- M3: an unbounded HMAC-expanded stream instead of cycling a 32-byte key,
  which was a repeating pad for passwords over 32 characters. Lag-32 repeat
  rate now sits within one standard error of chance.

Dropping the quota removed an accidental backstop: v1's minimum enforcement
overwrites uniformly random positions, so raising one class minimum could
destroy another, and only the quota's near-total rewrite hid it. v2 chooses
donor positions solely from classes that currently have a surplus, and
rejects a policy whose minima cannot fit the requested length.

Also removes a dead HKDF derivation whose result was discarded while the
docstrings named it as the algorithm in use (L1); PBKDF2 was and remains the
real one. Verified as a negative control -- the vectors stayed green.

Six test doubles are updated to the real generate_password signature; they
began receiving gen_version once new entries carried it.

Existing entries stay on v1 by design. An opt-in per-entry upgrade, with a
confirmation making the consequence unmissable, is still to come.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01HtNMsKzzFTPURemX7tT19u
2026-07-31 16:27:23 -04:00
thePR0M3TH3ANandClaude Opus 5 44935219d1 docs: entropy and RNG integration audit
Audits every security-sensitive random value in src/ against a
Coldcard-class checklist: where each bit of unpredictability originates,
whether that source is present in the production artifact, and what happens
when it fails.

No predictable-fallback defect. Master seed, AES-GCM nonces, TOTP secrets,
Argon2 salts, API tokens and agent leases all come from os.urandom or
secrets and fail closed. The random module is not imported anywhere in
non-test source.

The findings are about how much entropy survives the deterministic
derivation in core/password_generation.py, not about whether it should be
deterministic. Chief among them: _balance_distribution forces exactly L/4 of
each character class into every password, verified 300/300 at five lengths.
That costs 5.7-11.5 bits and, more materially, fingerprints the generator --
a password with exactly a quarter of each class is a strong signal it came
from SeedPass.

Records the compatibility constraint that governs all of it: passwords are
never stored, they are re-derived on demand, and entries carried no
algorithm version. Any in-place change to generate_password was therefore a
data-loss event, not an improvement.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01HtNMsKzzFTPURemX7tT19u
2026-07-31 16:27:05 -04:00
thePR0M3TH3AN 736ad1395c docs: refine TypeScript port plan 2026-06-05 14:58:40 -04:00
thePR0M3TH3AN 5869db84ba docs: add TypeScript web extension port plan 2026-06-05 14:54:17 -04:00
thePR0M3TH3AN f463094ce4 update 2026-06-05 14:38:27 -04:00
thePR0M3TH3AN f2cbb1b7ba Merge branch 'overstory/builder-atlas-handoff/SeedPass-63f4' into beta
# Conflicts:
#	src/seedpass/tui_v3/widgets/inspector.py
2026-03-11 07:39:49 -04:00
thePR0M3TH3ANandClaude Sonnet 4.6 b4e84a4327 feat(atlas-handoff): graph-pivot results through unified SearchService
- SearchService.graph_pivot_results(): wraps linked_neighbors() output
  in SearchResult model with match_reasons (graph_pivot, relation:X,
  direction:X, atlas:scope), scores (hop-distance based), and relation
  meta string for UI surfaces
- AtlasWayfinderScreen: propagates atlas_source_scope to LinkedItemsPanel
  when opening entries or recent items from the wayfinder
- LinkedItemsPanel: adds #linked-atlas-context label (◈ Atlas context:
  scope_path) that refreshes via property setter; atlas scope is
  preserved across linked-panel pivots; _update_atlas_context_label()
  helper keeps display in sync

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-03-11 07:34:48 -04:00
thePR0M3TH3AN 5eedea3762 feat: graph pivot UX — breadcrumb trail, back nav, relation grouping
- Add PivotBreadcrumbBar widget to inspector.py showing multi-hop path
- Add _pivot_history/pivot_to_entry/action_pivot_back to app.py
- LinkedItemsPanel: group linked items by relation type with section headers
- LinkedItemsPanel: b key for back navigation, breadcrumb rendered from app history
- External entry selection (grid) clears pivot history; pivot chain preserved on linked nav
2026-03-11 07:33:06 -04:00
thePR0M3TH3AN 2ab73c50a0 update 2026-03-10 21:39:50 -04:00
thePR0M3TH3ANandClaude Opus 4.6 e891ca0e11 update: sync tracking files
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-03-10 21:39:10 -04:00
thePR0M3TH3AN 2a09f0f312 seeds: sync 2026-03-11 2026-03-10 21:39:05 -04:00
thePR0M3TH3AN 492f21857d mulch: update expertise 2026-03-10 21:16:30 -04:00
thePR0M3TH3AN e79bfd7ba8 docs: update dev control center and v3 plan for 2026-03-10 shipped work
- Health gate: 1145 tests collected, focused suite 181 passed
- Bug fixes: SIGSEGV exit, non-TTY preflight guard, Binding import, profile assertion
- V3 polish: Profiles rename, restore warning guidance, maintenance status icons
- Search graph: multi_hop_neighbors, filtered_neighbors, LinkedItemsPanel enhancements
- Sort/filter: s/f/backslash shortcuts, active toolbar, Clear All button
- Mark Slice A complete; define Slice B deep graph + atlas handoff
- Update recommended next steps to reflect completed work
2026-03-10 21:15:54 -04:00
thePR0M3TH3AN 6cd33b7ea8 fix: update profile removal assertion to match new intro text 2026-03-10 16:09:30 -04:00
thePR0M3TH3AN f96e92e98e Merge branch 'overstory/builder-fix-import/SeedPass-91aa' into beta 2026-03-10 15:52:59 -04:00
thePR0M3TH3AN 5832255344 mulch: update expertise 2026-03-10 15:52:00 -04:00
thePR0M3TH3AN 34ab129c7a fix: add missing Binding import in pubkey.py 2026-03-10 15:50:07 -04:00
thePR0M3TH3AN 842f0ca9c7 Merge branch 'overstory/builder-sortfilter/SeedPass-de11' into beta 2026-03-10 15:14:13 -04:00
thePR0M3TH3ANandClaude Sonnet 4.6 3b031eb365 feat(tui-v3): sort/filter keyboard shortcuts, active-state toolbar, clear filter
- Add keyboard bindings: n=sort label_asc, r=sort modified_desc, k=sort kind, f=clear filter
- Add action_sort_label/recent/kind/clear_filter actions to app.py
- GridToolbar: add 'Kind' sort button, '[X] Clear' button
- GridToolbar: visual active-state via .active CSS class (synced via watchers)
- Add 5 new smoke tests: keyboard sort, clear button, clear shortcut, state persistence, toolbar active class

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-03-10 08:23:35 -04:00
thePR0M3TH3AN 82d33925ad feat(graph): add multi_hop_neighbors, filtered_neighbors to SearchService; enhance LinkedItemsPanel with keyboard nav, kind filter, atlas context 2026-03-10 08:22:20 -04:00
thePR0M3TH3AN 80fe87bc36 mulch: update expertise 2026-03-09 21:40:45 -04:00
thePR0M3TH3AN 4c03890266 Merge branch 'overstory/builder-sigsegv-v4/SeedPass-1d93' into beta 2026-03-09 20:55:19 -04:00
thePR0M3TH3ANandClaude Sonnet 4.6 5dc8e015ae fix: replace sys.exit(0) with os._exit(0) to prevent SIGSEGV on graceful exit
Python interpreter teardown with C extensions (Textual, crypto libs) can
trigger SIGSEGV (-11) when sys.exit() is called. os._exit() bypasses the
teardown entirely, producing a clean exit code 0.

Three call sites replaced:
- _cleanup_and_exit() in handle_remove_fingerprint (~line 254)
- graceful exit path in main loop (~line 1520)
- signal_handler shutdown path (~line 1862)

Fixes: SeedPass-1d93

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-03-09 12:49:23 -04:00
thePR0M3TH3AN f2b7feb738 Merge branch 'overstory/builder-profile-v4/SeedPass-9033' into beta 2026-03-09 12:48:43 -04:00
thePR0M3TH3AN 96f64d00bc tui3: guard against non-interactive stdin with TTY check
Add _stdin_is_tty() helper and check at start of _launch_tui3_or_exit.
When stdin is not a TTY, emit a clear error message and exit 1 instead
of propagating an EOF exception from seed setup prompts.
Add test for non-interactive stdin error path; patch _stdin_is_tty in
existing tests that expect tui3 launch to proceed.

Fixes SeedPass-6d26
2026-03-09 12:45:34 -04:00
thePR0M3TH3ANandClaude Sonnet 4.6 54316d33ed polish: profile/maintenance screen improvements
- maintenance.py: add status icons to format_status, add warning CSS class
- profile.py: improve intro text, use ► marker for active profile
- pubkey.py: use explicit Binding() for keybindings
- relays.py: remove stray `import traceback` in _perform_sync
- security.py: clarify backup passphrase label

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-03-09 12:45:07 -04:00
thePR0M3TH3AN 0cf1d58c9c mulch: update expertise 2026-03-07 08:09:15 -05:00
thePR0M3TH3ANandClaude Sonnet 4.6 44fe1c630a v3 polish: rename Profiles button, improve restore guidance
- action_bar.py: rename 'Remove Seed' label to 'Profiles' for clarity
- app.py: add warning prefix (⚠) to nostr/backup restore pre-action
  status messages; add success message to generate flow; improve
  import success message wording
- test_tui_v3_parity.py: update label assertions from 'Remove Seed'
  to 'Profiles' (two tests)

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-03-07 08:08:56 -05:00
thePR0M3TH3AN 0cb9259ad1 update 2026-03-06 13:55:08 -05:00
thePR0M3TH3AN 102f0369a3 seeds: sync 2026-03-06 2026-03-06 13:53:58 -05:00
thePR0M3TH3AN 30d558132b mulch: update expertise 2026-03-06 13:53:57 -05:00
thePR0M3TH3AN 41f000e802 Merge branch 'overstory/builder-action-strip/SeedPass-57f6' into beta
# Conflicts:
#	src/tests/test_tui_v3_parity.py
2026-03-06 13:47:40 -05:00
thePR0M3TH3AN a6c7391f78 Merge branch 'overstory/builder-app-cmds/SeedPass-865f' into beta 2026-03-06 13:47:35 -05:00
thePR0M3TH3AN 1a58c63658 Merge branch 'overstory/builder-settings-inspector/SeedPass-865f' into beta 2026-03-06 13:47:31 -05:00
thePR0M3TH3AN 27f9139008 mulch: update expertise 2026-03-06 13:44:44 -05:00
thePR0M3TH3AN 00b1b7d3ec feat(tui-v3): migrate legacy utility/maintenance commands to v3 CommandProcessor 2026-03-06 13:44:07 -05:00
thePR0M3TH3ANandClaude Sonnet 4.6 ea5ad1f093 Fix managed_account QR exclusion and bare except in action_bar
- Remove 'qr' from managed_account context actions (accounts don't expose
  a QR-scannable key like seeds/nostr do)
- Change bare 'except:' to 'except Exception:' on vault manager check
- Add test_v3_action_bar_managed_account_excludes_qr in parity tests

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-03-06 13:41:24 -05:00
thePR0M3TH3AN 8dbb8e065c mulch: update expertise 2026-03-06 13:37:12 -05:00
thePR0M3TH3ANandClaude Sonnet 4.6 446d1ef2b8 TUI v3: tighten action strip + restore/import guidance (SeedPass-57f6)
action_bar.py:
- Fix global row broken handlers: Remove Seed → open_profile_management,
  Backup Data → open_backup_parent_seed, Export/Import Data → open_palette
  (export/import need a path argument, palette is the right entry point)

add.py:
- seedplus-hint: mention BIP-85 explicitly, reference Seed+ (C) action
- AddEntryScreen success notify: include reveal/copy shortcut hint
- SeedPlusScreen: add #seedplus-warning label explaining deterministic
  derivation and index uniqueness requirement
- SeedPlusScreen success notify: mention index and parent seed

app.py:
- RecoverProfileScreen: set success status before bootstrap fires
- CreateProfileScreen: add intent messaging for nostr/backup restore modes
  with progress description and post-success status

grid.py:
- Add stored_password to secrets filter kind_map (was missing)

tests:
- test_tui_v3_parity: add test_v3_action_bar_global_row_uses_correct_handlers
- test_tui_v3_smoke: add seedplus-hint BIP-85 check, seedplus-warning label
  check, recover success-status check

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-03-06 13:36:34 -05:00
thePR0M3TH3AN 50c4a0346e mulch: update expertise 2026-03-06 13:36:13 -05:00
thePR0M3TH3ANandClaude Sonnet 4.6 02c4ef9e24 feat(tui-v3): add settings utility section and inspector kind-specific hints
Settings screen now renders a UTILITY & MAINTENANCE card listing stats,
db-export, db-import, checksum-verify/update, totp-export, and offline
mode commands. Renders gracefully when config service is offline (no
early return — all sections including utility always display).

Inspector adds UtilityHintsBar widget that persists across board swaps
via a #board-slot Vertical. Hints update to show kind-appropriate
palette commands (copy, reveal keybinds, QR, npub, managed-load, etc.).
BoardContainer now routes managed_account to its own SeedBoard hint set.

Two new smoke tests verify the utility section renders and that hints
update correctly for password, nostr, and idle states.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-03-06 13:35:49 -05:00
thePR0M3TH3AN 41ca95e1fc mulch: update expertise 2026-03-06 13:30:29 -05:00
thePR0M3TH3ANandClaude Sonnet 4.6 50d7b1827d Polish TUI v3 maintenance and profile screens
- maintenance.py: refine CSS visual hierarchy (rounded intro card borders,
  red-tinted danger buttons, consistent panel/footer margins)
- profile.py: clearer label text, improved intro and confirmation messages
- security.py: updated intro text and footer hints for both screens
- pubkey.py: rename DEFAULT_CSS to CSS, update intro and footer text
- relays.py: rename DEFAULT_CSS to CSS, add intro card, update footer/status
- test_tui_v3_smoke.py: update assertions to match new text

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-03-06 13:30:08 -05:00
thePR0M3TH3ANandClaude Opus 4.6 ca31abf33e Fix Overstory multi-agent setup and add quick reference docs
- Update agent models from gpt-5.3-codex to claude-compatible names
  (opus for coordinator/lead, sonnet for builder/scout/reviewer/merger,
  haiku for monitor)
- Switch runtime from codex to claude (codex requires interactive TTY,
  incompatible with tmux-based agent spawning)
- Add Overstory ecosystem links to AGENTS.md and CLAUDE.md
- Add docs/overstory_quick_reference.md with startup, monitoring, and
  CLI commands
- Sync seeds issue state

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-03-06 13:12:46 -05:00
thePR0M3TH3AN 46ffff577b Improve v3 grid navigation and graph browsing 2026-03-06 07:10:36 -05:00