Skip to content

DARK-24: preserve tag-store and CLI changes - #34

Draft
cooper (czxtm) wants to merge 4 commits into
mainfrom
audit/DARK-24-existing-work
Draft

DARK-24: preserve tag-store and CLI changes#34
cooper (czxtm) wants to merge 4 commits into
mainfrom
audit/DARK-24-existing-work

Conversation

@czxtm

@czxtm cooper (czxtm) commented Sep 10, 2026

Copy link
Copy Markdown
Member

Parked after Cooper narrowed DARK-20 to pre-existing workspace issue work. This repository discovery has an audit-created tracking issue and is outside the active merge recommendation; source and validation below are preserved records.

Adds reference-expression parsing and tag-definition storage foundations, fuzzy completion, stdin path handling, file-based secret input, and store-filter UI changes. The parser/storage APIs remain separate from runtime resolution; key-provider and codegen designs are proposals. Retains Cooper’s two existing commits and the working-copy changes published under DARK-24/DARK-20.

Readiness cleanup removes two Clippy failures without changing generated Bash or Zsh completion behavior. On macOS at c833567, cargo fmt --all -- --check, cargo clippy --workspace --all-targets --locked --offline -- -D warnings, and cargo test --workspace --locked --offline pass: 730 tests in each lib/bin target and 161 integration tests; existing ignored tests unchanged. CI is running for the pushed fix. Validation used isolated test stores; no live secret-store operations.

cooper and others added 4 commits August 19, 2026 11:20
- KeyAction::CycleStore added to keymap.rs with default Ctrl+I binding
- SearchView.selected_store field (Option<String>) filters results by store
- cycle_store() cycles None → first → ... → last → None
- store_color() in theme.rs: 10-color palette, deterministic per-slug hash
- Non-default store secrets colored distinctly in draw_results
- Header shows colored filter pill when store filter is active
- InfoMode set to always All (both health pills visible); cycle removed
- SwitchStore handler sets selected_store from picker selection
- App.selected_store preserved across fresh_search() calls
- Autocomplete widget removed (hm-s12/hm-p3n)
- Footer label: ^i info → ^i store (hm-3id)
- Codegen design doc: docs/CODEGEN_DESIGN.md (hm-fcb)
- bump-version.sh script (hm-0a2)

Closes hm-3id, hm-ebs, hm-s12, hm-p3n, hm-5t6, hm-cqk, hm-bw5,
hm-y3v, hm-661, hm-d3k, hm-0a2, hm-fcb
hm-qlh implementation blocked on design approval (HARD-GATE)
Preserves existing working-copy changes for review during DARK-20.
Co-authored-by: multica-agent <github@multica.ai>
@czxtm
cooper (czxtm) marked this pull request as ready for review September 10, 2026 05:38
Copilot AI lite review requested due to automatic review settings September 10, 2026 05:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved completion, reference parsing, and TUI store-filter issues remain.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds reference parsing, tag-definition storage, file/stdin secret handling, fuzzy completion, and TUI store filtering.

Changes:

  • Adds parser and tag-store foundations.
  • Updates CLI input handling and completions.
  • Updates TUI filtering, documentation, release tooling, and tests.
File summaries
File Summary
tests/integration/cli_test.rs Tests file input and stdin paths
scripts/bump-version.sh Updates release version workflow
rust/src/tui/widgets/secret_ref_autocomplete.rs Removes obsolete autocomplete widget
rust/src/tui/widgets/mod.rs Unregisters removed widget
rust/src/tui/views/search.rs Implements store filtering
rust/src/tui/theme.rs Adds store colors
rust/src/tui/keymap.rs Updates key bindings and help
rust/src/tui/app.rs Adds store-filter state handling
rust/src/remote/tag_store.rs Adds tag-definition persistence
rust/src/remote/mod.rs Exposes tag storage
rust/src/reference.rs Adds reference-expression parsing
rust/src/error.rs Adds tag-storage errors
rust/src/cli/set.rs Adds file-backed secret input
rust/src/cli/get.rs Adds stdin path handling
rust/src/cli/completions.rs Adds fuzzy path completion
README.md Documents CLI and TUI changes
docs/KEY_PROVIDERS_DESIGN.md Adds provider design proposal
docs/CODEGEN_DESIGN.md Documents parser and tag storage
docs/adr/0002-hard-error-on-duplicate-env-keys-under-tag-model.md Documents duplicate-key behavior
docs/adr/0001-keep-last-wins-collapse-in-file-generators.md Records generator behavior
CONTEXT.md Updates domain terminology
CHANGELOG.md Records new functionality
.gitignore Ignores local direnv overrides
.envrc Loads optional local environment
.beads/dolt-fsqlite-ns-gate Adds Beads gate marker
Review details

Suppressed comments (6)

docs/adr/0002-hard-error-on-duplicate-env-keys-under-tag-model.md:24

  • This ADR is marked accepted and says every consumer must hard-error on duplicate Env Keys, but the unchanged generate/codegen loops still warn and keep the last value (for example, rust/src/cli/codegen.rs:165-174). Since this PR explicitly leaves runtime/codegen behavior unchanged, the accepted decision makes the repository's documented behavior contradictory; implement it in the consumers or mark it proposed/future until that migration lands.
A resolved Tag whose members produce the same Env Key is a hard error in
every consumer — `exec`, `generate`, `codegen` (sops materialization and
typed stubs alike). No consumer collapses duplicates. The error names

rust/src/cli/completions.rs:316

  • Applying --fuzzy to every secret-path subcommand changes the documented completion contract: docs/ARCHITECTURE.md currently specifies fuzzy subsequence matching only for exec and exact-prefix matching for the other commands. Update that contract if this broad change is intentional, or retain the per-subcommand distinction.
    for sub in SECRET_PATH_SUBCOMMANDS {
        out.push_str(&format!(
            "complete -c himitsu -n \"__fish_seen_subcommand_from {sub}\" -f -a \"(himitsu __complete-paths --fuzzy 2>/dev/null)\"\n"

rust/src/cli/completions.rs:316

  • These Fish directives are gated only by __fish_seen_subcommand_from, so secret-path candidates are offered for every token in set/write (including the secret value) and for option values, not just the positional path. Add an argument-position/flag-aware condition or a subcommand-specific helper before attaching __complete-paths.
    for sub in SECRET_PATH_SUBCOMMANDS {
        out.push_str(&format!(
            "complete -c himitsu -n \"__fish_seen_subcommand_from {sub}\" -f -a \"(himitsu __complete-paths --fuzzy 2>/dev/null)\"\n"

rust/src/tui/keymap.rs:714

  • CycleStore is now bound to Ctrl+I and help_rows adds a live cycle store filter entry, but the search help still appends a static ^i row describing the old header-status cycle. The help overlay will show two contradictory descriptions for the same key; remove or update the static row.
            cycle_store: vec![ctrl('i')],

rust/src/tui/views/search.rs:472

  • The contract immediately above says cycling is a no-op when there is only one store, but this branch still changes None to Some(stores.first()) for a one-store corpus, showing a filter pill and requiring another Ctrl+I to clear it. Guard the one-store case if the documented behavior is intended.
        if stores.is_empty() {

rust/src/tui/views/search.rs:234

  • This initializes selected_store from default_store, but App::new starts its persisted filter as None and fresh_search overwrites this value. Consequently the initial view can show only the configured default store while returning/rebuilding the view shows all stores; the field documentation also says None is the default all-store state. Make the initialization source and intended default consistent.
            selected_store: default_store,
  • Files reviewed: 23/26 changed files
  • Comments generated: 7
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

};
out.push_str(&format!(
"complete -c himitsu -n \"__fish_seen_subcommand_from {sub}\" -f -a \"(himitsu __complete-paths {fuzzy_flag}2>/dev/null)\"\n"
"complete -c himitsu -n \"__fish_seen_subcommand_from {sub}\" -f -a \"(himitsu __complete-paths --fuzzy 2>/dev/null)\"\n"
Comment thread rust/src/reference.rs
Comment on lines +369 to +374
if let Some(prefix) = raw.strip_suffix('/') {
return Ok(ReferenceExpr::PathPrefix(normalize_path(prefix)?));
}
if let Some(prefix) = raw.strip_suffix("/*") {
return Ok(ReferenceExpr::PathPrefix(normalize_path(prefix)?));
}
Comment thread rust/src/tui/app.rs
pending_chord: Vec::new(),
pending_chord_deadline: None,
chord_breadcrumb_active: false,
selected_store: None,
Comment on lines +465 to +471
let stores: Vec<String> = self
.candidates
.iter()
.map(|r| r.store.clone())
.collect::<std::collections::BTreeSet<_>>()
.into_iter()
.collect();
Comment thread CONTEXT.md
- **Selector** — a query over secrets: `tag:pci`, `prod/*`, `tag:A+tag:B`
- **Reference** — a string that identifies a secret: path, qualified ref (`github:org/repo/path`), or selector
- **Tag** — a named group of secrets; the only grouping entity (replaces the former Output/env/label concept). A Tag lives in a Store, exactly like a Secret. Its members are the secrets tagged with it plus what the Tag's own references resolve to, counted once. A Tag groups secrets, never other Tags — shared membership is co-tagging. Referenced bare (`web-prod`) or explicitly (`tag:web-prod`).
- **Reference** — a string that identifies secrets. Bare: a path (`prod/api-key`), a path prefix (`prod/`), or a tag name (`web-prod`; a path beats a tag on name collision). Forced: `tag:web-prod`, `path:prod/api-key`, `regex:<pattern>` (anchored match over paths), or a qualified cross-store ref (`github:org/repo#path`).
Comment thread README.md
`quit`, `help`, `command_palette`, `new_secret`, `switch_store`,
`copy_selected`, `copy_ref_selected`, `codegen` (legacy aliases: `outputs`, `envs`),
`collapse_paths`, `expand_paths`, `toggle_autocomplete`, `refine_tag`,
`collapse_paths`, `expand_paths`, `refine_tag`,
("enter".into(), "open selection".into()),
("backspace".into(), "delete char".into()),
("i".into(), "cycle header status (info)".into()),
("^i".into(), "cycle header status (info)".into()),
@czxtm
cooper (czxtm) marked this pull request as draft September 10, 2026 05:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants