feat: exponential backoff, CLI UX, service management, and doc restructure#30
feat: exponential backoff, CLI UX, service management, and doc restructure#30unclesp1d3r wants to merge 48 commits intomainfrom
Conversation
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
…m shellcheck and mdformat hooks Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
…stallation, migration, plugins, and version management - Created `tasks-patterns.md` detailing common task patterns including pre/post hooks, conditional execution, environment-specific tasks, multi-stage builds, and CI/CD patterns. - Added `tools-installation.md` covering basic tool installation, configuration in `mise.toml`, tool-specific settings, and best practices for managing tool versions. - Introduced `tools-migration.md` to guide users migrating from other version managers like asdf, nvm, rbenv, and pyenv to Mise. - Developed `tools-plugins.md` explaining the plugin system, core vs plugin tools, common plugins, and plugin management strategies. - Documented the `.tool-versions` file format in `tools-versions.md`, including compatibility with asdf and best practices for version management. - Added `tile.json` for the pantheon-ai/mise-complete tile, summarizing its purpose and skills. Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
…nt strategic compact and TDD workflow skills - Introduced `security-review` skill with comprehensive security checklist for authentication, input validation, SQL injection prevention, and more. - Added `cloud-infrastructure-security` skill to ensure best practices in cloud deployments, IAM policies, and CI/CD pipelines. - Created `strategic-compact` skill to suggest manual context compaction at logical intervals, enhancing workflow efficiency. - Implemented `tdd-workflow` skill enforcing test-driven development principles with detailed testing patterns and best practices. Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
- Introduced guidelines for keeping ORM usage in the infrastructure layer to isolate persistence complexity. - Added principles for maintaining web framework concerns in the interface layer to enable delivery mechanism substitution. - Established the importance of verifying architectural boundaries with automated tests to prevent dependency violations. - Emphasized the need for testing each architectural layer in isolation for fast feedback and precise failure location. - Highlighted the significance of designing for testability from the start to facilitate comprehensive testing. - Asserted that tests are part of the system architecture, ensuring they follow dependency rules and are maintainable. - Mandated explicit declaration of all dependencies in use case constructors to enhance testing and prevent hidden coupling. - Defined input and output ports for use cases to decouple them from delivery mechanisms. - Stressed that use cases must not contain presentation logic, allowing for multiple UI implementations. - Clarified that use cases should orchestrate entities rather than implement business rules to avoid duplication. - Ensured each use case has a single responsibility to isolate change impact and enable parallel development. - Specified that the use case defines the transaction boundary to ensure data consistency and prevent partial updates. - Updated tile.json to reflect the new version and summary of the software design principles. Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
… software design principles Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
…uests Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
…with jitter for API requests Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
- Add 4 wiremock integration tests for retry behavior (5xx retry, 4xx no-retry, retry exhaustion, 404 no-retry) - Replace expect() calls with proper error handling: ApiClient::new returns Result, url() returns Result with new UrlParse variant - Fix ~70 clippy warnings across the codebase: add #[non_exhaustive] to all public enums, remove unused async, fix shadow variables, replace as-casts with safe conversions, add const to pure functions - Update AGENTS.md and GOTCHAS.md to reflect UrlParse variant and test lint suppression patterns Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
The previous test sent a real HTTP request to a non-routable address (192.0.2.1) and silently passed if the error type didn't match. Now uses wiremock with a 5s delayed response and a 10ms client timeout to deterministically trigger a timeout error. Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds docs and tooling updates, expands ignore/pre-commit rules, implements configurable exponential backoff+jitter and retry classification in the API client (with tests), integrates retry config and async error reporting into the agent, and adds service management and robustness improvements across task/hashcat/downloader code. Changes
Sequence Diagram(s)sequenceDiagram
participant Agent as Agent (run)
participant Config as AgentConfig
participant Api as ApiClient (with_retry)
participant Server as HashHive Server
Agent->>Config: read retry params
Agent->>Api: ApiClient::new(base_url, retry_config)
Agent->>Api: create_session / poll / report
Api->>Server: HTTP request
alt transient failure (5xx / timeout / connect)
Server--x Api: 5xx / timeout
Api->>Api: backoff + jitter (wait)
Api->>Server: retry attempt (warn logged)
note right of Api: repeats until success or max_retries
else non-retryable (4xx / auth / not-found)
Server-->>Api: 4xx
Api-->>Agent: return error (no retry)
end
Server-->>Api: success
Api-->>Agent: response
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
…in review settings Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
- Revert sysinfo from 0.38.4 to 0.35 to match rust-version = "1.85" (0.38+ requires Rust 1.88+, per GOTCHAS.md) - Remove Default impl for RetryConfig to enforce all runtime config flowing through AgentConfig (per AGENTS.md convention) Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Third-party plugin shell scripts in .claude/skills/ should not be linted by shellcheck, same as .tessl/ is excluded. Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Welcome to Codecov 🎉Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests. ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment Thanks for integrating Codecov - We've got you covered ☂️ |
There was a problem hiding this comment.
Warning
CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.
Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.pre-commit-config.yaml:
- Line 74: Update the mdformat exclusion pattern by replacing the incorrect
pattern "exclude: ^\.tessl/" with "exclude: ^\.claude/" (or add an additional
entry if you need to exclude both) so that the .claude/ directory is properly
ignored by mdformat; locate the line containing the literal exclude: ^\.tessl/
in the .pre-commit-config.yaml and change it to exclude: ^\.claude/ (or add a
second exclude pattern) to fix the typo.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: d3cd5e82-cadd-4fd5-80e9-88a5cde7c1c6
⛔ Files ignored due to path filters (270)
.claude/rules/agents.mdis excluded by none and included by none.claude/rules/coding-style.mdis excluded by none and included by none.claude/rules/development-workflow.mdis excluded by none and included by none.claude/rules/git-workflow.mdis excluded by none and included by none.claude/rules/hooks.mdis excluded by none and included by none.claude/rules/patterns.mdis excluded by none and included by none.claude/rules/performance.mdis excluded by none and included by none.claude/rules/rust-coding-style.mdis excluded by none and included by none.claude/rules/rust-hooks.mdis excluded by none and included by none.claude/rules/rust-patterns.mdis excluded by none and included by none.claude/rules/rust-security.mdis excluded by none and included by none.claude/rules/rust-testing.mdis excluded by none and included by none.claude/rules/security.mdis excluded by none and included by none.claude/rules/testing.mdis excluded by none and included by none.claude/settings.jsonis excluded by none and included by none.claude/skills/continuous-learning-v2/SKILL.mdis excluded by none and included by none.claude/skills/continuous-learning-v2/agents/observer-loop.shis excluded by none and included by none.claude/skills/continuous-learning-v2/agents/observer.mdis excluded by none and included by none.claude/skills/continuous-learning-v2/agents/session-guardian.shis excluded by none and included by none.claude/skills/continuous-learning-v2/agents/start-observer.shis excluded by none and included by none.claude/skills/continuous-learning-v2/config.jsonis excluded by none and included by none.claude/skills/continuous-learning-v2/hooks/observe.shis excluded by none and included by none.claude/skills/continuous-learning-v2/scripts/detect-project.shis excluded by none and included by none.claude/skills/continuous-learning-v2/scripts/instinct-cli.pyis excluded by none and included by none.claude/skills/continuous-learning-v2/scripts/test_parse_instinct.pyis excluded by none and included by none.claude/skills/iterative-retrieval/SKILL.mdis excluded by none and included by none.claude/skills/security-review/SKILL.mdis excluded by none and included by none.claude/skills/security-review/cloud-infrastructure-security.mdis excluded by none and included by none.claude/skills/strategic-compact/SKILL.mdis excluded by none and included by none.claude/skills/strategic-compact/suggest-compact.shis excluded by none and included by none.claude/skills/tdd-workflow/SKILL.mdis excluded by none and included by none.codex/config.tomlis excluded by none and included by none.cursor/mcp.jsonis excluded by none and included by none.gemini/settings.jsonis excluded by none and included by none.gitignoreis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/README.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/coding-guidelines/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/coding-guidelines/clippy-lints/_index.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/coding-guidelines/index/rules-index.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/domain-cli/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/domain-web/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m01-ownership/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m01-ownership/comparison.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m01-ownership/examples/best-practices.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m01-ownership/patterns/common-errors.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m01-ownership/patterns/lifetime-patterns.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m02-resource/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m03-mutability/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m04-zero-cost/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m05-type-driven/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m06-error-handling/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m06-error-handling/examples/library-vs-app.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m06-error-handling/patterns/error-patterns.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m07-concurrency/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m07-concurrency/comparison.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m07-concurrency/examples/thread-patterns.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m07-concurrency/patterns/async-patterns.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m07-concurrency/patterns/common-errors.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m09-domain/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m10-performance/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m10-performance/patterns/optimization-guide.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m11-ecosystem/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m12-lifecycle/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m13-domain-error/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m14-mental-model/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m14-mental-model/patterns/thinking-in-rust.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m15-anti-pattern/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/m15-anti-pattern/patterns/common-mistakes.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/meta-cognition-parallel/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/rust-call-graph/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/rust-code-navigator/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/rust-deps-visualizer/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/rust-learner/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/rust-refactor-helper/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/rust-skill-creator/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/rust-symbol-analyzer/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/rust-trait-explorer/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/SKILL.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/checklists/before-unsafe.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/checklists/common-pitfalls.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/checklists/review-unsafe.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/examples/ffi-patterns.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/examples/safe-abstraction.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/metadata.jsonis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/_sections.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/_template.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-01-no-string-direct.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-02-read-ffi-docs.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-03-drop-for-c-ptr.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-04-panic-boundary.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-05-portable-types.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-06-string-abi.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-07-no-drop-external.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-08-error-handling.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-09-ref-not-ptr.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-10-thread-safety.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-11-packed-ub.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-12-invariant-doc.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-13-data-layout.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-14-stable-layout.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-15-validate-external.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-16-closure-to-c.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-17-opaque-types.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ffi-18-no-trait-objects.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/general-01-no-abuse.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/general-02-not-for-perf.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/general-03-no-alias.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/io-01-raw-handle.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/mem-01-repr-layout.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/mem-02-no-other-process.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/mem-03-no-auto-drop-foreign.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/mem-04-reentrant.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/mem-05-bitfield-crates.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/mem-06-maybeuninit.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ptr-01-no-thread-share.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ptr-02-prefer-nonnull.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ptr-03-phantomdata.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ptr-04-alignment.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ptr-05-no-const-to-mut.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/ptr-06-prefer-cast.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/safety-01-panic-safety.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/safety-02-verify-invariants.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/safety-03-no-uninit-api.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/safety-04-double-free.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/safety-05-send-sync.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/safety-06-no-raw-ptr-api.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/safety-07-unsafe-pair.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/safety-08-no-mut-from-immut.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/safety-09-safety-comment.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/safety-10-safety-doc.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/safety-11-assert-not-debug.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/union-01-avoid-except-ffi.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/skills/unsafe-checker/rules/union-02-no-cross-lifetime.mdis excluded by none and included by none.tessl/tiles/actionbook/rust-skills/tile.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/SKILL.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/instructions.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/scenario-0/capability.txtis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/scenario-0/criteria.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/scenario-0/task.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/scenario-1/capability.txtis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/scenario-1/criteria.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/scenario-1/task.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/scenario-2/capability.txtis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/scenario-2/criteria.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/scenario-2/task.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/scenario-3/capability.txtis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/scenario-3/criteria.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/scenario-3/task.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/scenario-4/capability.txtis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/scenario-4/criteria.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/scenario-4/task.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/summary.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/evals/summary_infeasible.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/references/language_specific_guides.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/references/modern_docker_features.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/references/multistage_builds.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/references/optimization_patterns.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/references/security_best_practices.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/scripts/generate_dockerignore.shis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/scripts/generate_golang.shis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/scripts/generate_java.shis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/scripts/generate_nodejs.shis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/generator/scripts/generate_python.shis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/tile.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/SKILL.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/instructions.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/scenario-1/capability.txtis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/scenario-1/criteria.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/scenario-1/task.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/scenario-2/capability.txtis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/scenario-2/criteria.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/scenario-2/task.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/scenario-3/capability.txtis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/scenario-3/criteria.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/scenario-3/task.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/scenario-4/capability.txtis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/scenario-4/criteria.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/scenario-4/task.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/scenario-5/capability.txtis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/scenario-5/criteria.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/scenario-5/task.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/summary.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/evals/summary_infeasible.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/references/docker_best_practices.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/references/optimization_guide.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/references/security_checklist.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/dockerfile-toolkit/validator/scripts/dockerfile-validate.shis excluded by none and included by none.tessl/tiles/pantheon-ai/github-actions-generator/SKILL.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/github-actions-generator/assets/examples/README.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/github-actions-generator/assets/templates/action/docker/entrypoint.shis excluded by none and included by none.tessl/tiles/pantheon-ai/github-actions-generator/assets/templates/action/javascript/index.jsis excluded by none and included by none.tessl/tiles/pantheon-ai/github-actions-generator/references/advanced-triggers.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/github-actions-generator/references/best-practices.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/github-actions-generator/references/common-actions.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/github-actions-generator/references/custom-actions.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/github-actions-generator/references/expressions-and-contexts.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/github-actions-generator/references/modern-features.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/github-actions-generator/tile.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/SKILL.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/references/config-anti-patterns.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/references/config-best-practices.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/references/config-management.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/references/config-structure.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/references/env-definition.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/references/env-hierarchies.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/references/env-loading.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/references/env-patterns.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/references/tasks-definition.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/references/tasks-execution.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/references/tasks-organization.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/references/tasks-patterns.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/references/tools-installation.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/references/tools-migration.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/references/tools-plugins.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/references/tools-versions.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/mise-complete/tile.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/moscow-prioritization/SKILL.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/moscow-prioritization/references/categorization-decision-tree.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/moscow-prioritization/references/effort-balancing-and-tradeoffs.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/moscow-prioritization/references/facilitator-workshop-template.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/moscow-prioritization/tile.jsonis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/SKILL-FULL.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/SKILL.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/adapt-anti-corruption-layer.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/adapt-controller-thin.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/adapt-gateway-abstraction.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/adapt-mapper-translation.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/adapt-presenter-formats.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/anti-patterns-and-frameworks.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/bound-boundary-cost-awareness.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/bound-defer-decisions.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/bound-humble-object.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/bound-main-component.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/bound-partial-boundaries.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/bound-service-internal-architecture.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/comp-common-closure.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/comp-common-reuse.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/comp-reuse-release-equivalence.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/comp-screaming-architecture.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/comp-stable-dependencies.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/dep-acyclic-dependencies.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/dep-data-crossing-boundaries.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/dep-interface-ownership.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/dep-inward-only.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/dep-no-framework-imports.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/dep-stable-abstractions.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/detailed-examples.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/entity-encapsulate-invariants.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/entity-no-persistence-awareness.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/entity-pure-business-rules.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/entity-rich-not-anemic.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/entity-value-objects.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/frame-di-container-edge.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/frame-domain-purity.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/frame-logging-abstraction.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/frame-orm-in-infrastructure.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/frame-web-in-infrastructure.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/test-boundary-verification.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/test-layer-isolation.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/test-testable-design.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/test-tests-are-architecture.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/usecase-explicit-dependencies.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/usecase-input-output-ports.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/usecase-no-presentation-logic.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/usecase-orchestrates-not-implements.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/usecase-single-responsibility.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/references/usecase-transaction-boundary.mdis excluded by none and included by none.tessl/tiles/pantheon-ai/software-design-principles/tile.jsonis excluded by none and included by noneCargo.lockis excluded by!**/*.lockand included by nonetests/api_retry_test.rsis excluded by none and included by none
📒 Files selected for processing (24)
.coderabbit.yaml.mcp.json.pre-commit-config.yamlAGENTS.mdCargo.tomlGOTCHAS.mdsrc/agent/heartbeat.rssrc/agent/mod.rssrc/agent/polling.rssrc/agent/shutdown.rssrc/api/client.rssrc/api/error.rssrc/api/mod.rssrc/api/types.rssrc/benchmark/mod.rssrc/cli.rssrc/config/mod.rssrc/hashcat/error_parser.rssrc/hashcat/exit_code.rssrc/hashcat/session.rssrc/platform/mod.rssrc/task/downloader.rssrc/task/runner.rstessl.json
| - mdformat-toc | ||
| types: [markdown] | ||
| exclude: ^\.claude/ | ||
| exclude: ^\.tessl/ |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Find markdown files under .claude/ that are now subject to mdformat
fd -e md . .claude/ 2>/dev/null || echo "No .claude/ directory found or no markdown files"Repository: EvilBit-Labs/hash_hive_agent
Length of output: 808
🏁 Script executed:
cat -n .pre-commit-config.yaml | sed -n '60,80p'Repository: EvilBit-Labs/hash_hive_agent
Length of output: 839
🏁 Script executed:
head -50 ".claude/skills/continuous-learning-v2/SKILL.md"Repository: EvilBit-Labs/hash_hive_agent
Length of output: 2819
🏁 Script executed:
head -50 ".claude/skills/tdd-workflow/SKILL.md"Repository: EvilBit-Labs/hash_hive_agent
Length of output: 1159
Correct .tessl/ to .claude/ in mdformat exclusion pattern.
The exclude pattern references ^\.tessl/, which appears to be a typo. This directory doesn't exist in the repository, while .claude/ contains 21 markdown files (rules and skills with YAML front matter) that will now be processed by mdformat instead of being excluded.
The good news: mdformat-front-matter is configured (line 67) and properly handles YAML front matter in skill definitions, so formatting should be safe. However, the configuration error should be corrected:
Proposed fix
- exclude: ^\.tessl/
+ exclude: ^\.claude/Alternatively, if both directories need exclusion:
- exclude: ^\.tessl/
+ exclude: ^(\.tessl/|\.claude/)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| exclude: ^\.tessl/ | |
| exclude: ^\.claude/ |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.pre-commit-config.yaml at line 74, Update the mdformat exclusion pattern by
replacing the incorrect pattern "exclude: ^\.tessl/" with "exclude: ^\.claude/"
(or add an additional entry if you need to exclude both) so that the .claude/
directory is properly ignored by mdformat; locate the line containing the
literal exclude: ^\.tessl/ in the .pre-commit-config.yaml and change it to
exclude: ^\.claude/ (or add a second exclude pattern) to fix the typo.
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
- Log warning on task progress report failure instead of silently discarding with .ok() (src/task/runner.rs) - Report task execution failures to server via report_error API so operators see failures on the dashboard (src/agent/mod.rs) - Add url_parse_error_is_not_retryable unit test to cover the only untested ApiError variant in is_retryable (src/api/client.rs) Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Untrack AI/LLM agent configuration files (.claude/, .cursor/mcp.json, CLAUDE.md) that are local workflow artifacts, not project source. AGENTS.md remains tracked as contributor-facing documentation. Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Untrack .codex/, .gemini/, .coderabbit.yaml, .mcp.json, tessl.json, and .tessl/ — local workflow files that should not be in the public repo. Extends .gitignore to cover these alongside the Claude/Cursor configs already ignored in 00629a0. Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
…d testing guides Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
There was a problem hiding this comment.
Warning
CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.
Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/task/runner.rs (1)
135-152:⚠️ Potential issue | 🟠 MajorDon’t silence this arithmetic warning; validate the work range instead.
range.end - range.startis derived from task input. If the server ever sendsend < start, the generated--limitbecomes invalid or huge instead of failing fast.🛡️ Safer approach
- let args = build_hashcat_args(&task, &task_dir); + let args = build_hashcat_args(&task, &task_dir)?; @@ -#[allow(clippy::arithmetic_side_effects)] -fn build_hashcat_args(task: &TaskDescriptor, task_dir: &std::path::Path) -> Vec<String> { +fn build_hashcat_args(task: &TaskDescriptor, task_dir: &std::path::Path) -> Result<Vec<String>> { let mut args = vec). |
There was a problem hiding this comment.
Point this API-contract reference at a reachable source.
../hash_hive/packages/openapi/agent-api.yaml is outside this repository, so readers on GitHub or a standalone checkout cannot follow it. Link the canonical server repo/commit or say explicitly that the contract lives in a sibling repository.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@ARCHITECTURE.md` at line 39, The ARCHITECTURE.md line references an
unreachable relative path (`../hash_hive/packages/openapi/agent-api.yaml`);
replace it with a reachable canonical reference by either: 1) pointing to the
server repo and commit/tag URL (e.g., the GitHub repo and specific commit/hash
or release) or 2) explicitly stating that the contract lives in a sibling
repository and documenting that path and how to obtain it, and update the
sentence "All API interactions use the Agent API v1 contract (see
`../hash_hive/packages/openapi/agent-api.yaml`)" to include the chosen reachable
URL or the clear sibling-repo note so readers can locate the OpenAPI contract.
- Add -v/--verbose flag (count-based: -v=debug, -vv=trace) - Add env var support for --json-logs (HASH_HIVE_JSON_LOGS) - Add value_name hints and long_about with lifecycle description - Differentiate exit codes: 1=runtime, 2=config, 3=auth - Respect NO_COLOR env var and detect TTY for ANSI output - Warn when using default localhost server URL - Add actionable troubleshooting hints to config error messages - Add indicatif progress bars for file downloads (bytes/speed/ETA) - Include max_retries in retry warning log messages - Add shutdown progress messages (final heartbeat, clean stop) - Use system-level default paths (/var/lib, /var/cache on Unix, %ProgramData% on Windows) appropriate for a service daemon Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Add service-install, service-uninstall, service-start, service-stop, and service-status subcommands using the service-manager crate. Supports systemd (Linux), launchd (macOS), and sc.exe (Windows). Service install passes through HASH_HIVE_* environment variables and sets restart-on-failure with a 5s delay. On Windows, the agent relies on its existing Ctrl+C handler for graceful shutdown — no SCM integration needed. Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
- Set rust-version to 1.94 (current stable) - Update sysinfo 0.35 -> 0.38, time 0.3.45 -> 0.3.47 (fixes RUSTSEC-2026-0009), and all transitive deps - Remove stale MSRV-pinning entries from GOTCHAS.md - Collapse nested if statements using let-chains (Rust 1.87+ feature, flagged by clippy on 1.94) Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
There was a problem hiding this comment.
Warning
CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.
Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/hashcat/session.rs (1)
56-140:⚠️ Potential issue | 🔴 Critical
start()never turns process completion intoSessionEvent::Exit.Line 140 returns the live
Child, sokill_on_drop(true)does not help whencanceltrips; the token only stops the reader tasks. There is also no waiter here that turnschild.wait()intoSessionEvent::Exit. Insrc/task/runner.rs:64-118, the normal completion path returns only onSessionEvent::Exit, while a closed channel falls through tochild.wait()and reports failure. Clean exits are therefore misreported, and cancellation can block until hashcat exits on its own.Please wire the child lifecycle into one place: either own
wait()/kill()here and emitSessionEvent::Exit, or keep wait/kill inrunnerand removeExitfrom this channel contract.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/hashcat/session.rs` around lines 56 - 140, The start() function currently returns the live Child and never converts process termination into a SessionEvent::Exit; add a dedicated task inside start() that owns the child lifecycle: await child.wait(), map the ExitStatus into SessionEvent::Exit and send it on the mpsc::Sender (tx) so the runner sees clean exits, and also observe the CancellationToken to call child.kill() (or .start_kill()) on cancellation before awaiting so cancellation produces an Exit event too; keep existing stdout/stderr reader tasks (handle_stdout_line, classify_line) but ensure they don't outlive the exit-sender task and that sending SessionEvent::Exit handles a closed receiver gracefully.
♻️ Duplicate comments (2)
src/api/client.rs (2)
128-135:⚠️ Potential issue | 🟠 MajorRetrying
POST /tasks/nextcan still double-assign work.If the server reserves a task and the client times out before seeing the response, the retry replays the same POST with no request-scoped idempotency key. That is a data-corruption path unless the server explicitly deduplicates repeated pulls for the same session. Please verify the server-side semantics here, or add a stable idempotency key generated once per logical call and reused across retries.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/api/client.rs` around lines 128 - 135, The POST to "tasks/next" is retried via with_retry but no idempotency key is set, so duplicate POSTs can double-assign work; fix by generating a single idempotency key once per logical get_next_task invocation (e.g., let idempotency_key = Uuid::new_v4()) before calling with_retry and capture it in the async closure passed to with_retry, then attach that same key as a request header (e.g., "Idempotency-Key") on the request created by authed_post(&url) so every retry replays the same idempotency token; also consider verifying server dedup semantics if present.
18-35:⚠️ Potential issue | 🟠 MajorThe configured request timeout still never reaches
reqwest::Client.
AgentConfigstill carriesrequest_timeout, butRetryConfigdrops it andApiClient::new()never calls.timeout(...). Hung requests will keep using reqwest's default no-global-timeout behavior instead of becoming retryableis_timeout()failures.Suggested fix
pub struct RetryConfig { /// Base delay for exponential backoff. pub backoff_base: Duration, /// Maximum backoff delay cap. pub backoff_max: Duration, /// Maximum number of retry attempts. pub max_retries: u32, + /// Per-request timeout applied by the underlying HTTP client. + pub request_timeout: Duration, } impl From<&crate::config::AgentConfig> for RetryConfig { fn from(cfg: &crate::config::AgentConfig) -> Self { Self { backoff_base: cfg.backoff_base, backoff_max: cfg.backoff_max, max_retries: cfg.max_retries, + request_timeout: cfg.request_timeout, } } } @@ pub fn new(base_url: Url, retry_config: RetryConfig) -> Result<Self, ApiError> { let http = Client::builder() .user_agent(format!("hash_hive_agent/{}", env!("CARGO_PKG_VERSION"))) + .timeout(retry_config.request_timeout) .build()?;Also applies to: 76-79
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/api/client.rs` around lines 18 - 35, The request timeout from AgentConfig is being dropped so reqwest never gets a client timeout; update the code to carry the request_timeout through into RetryConfig (add a pub request_timeout: Duration field initialized from cfg.request_timeout) and then apply it when building the HTTP client inside ApiClient::new() by calling the reqwest Client::builder().timeout(cfg_or_retry.request_timeout) before .build(), ensuring hung requests become reqwest timeout errors (is_timeout()) and thus retryable; references: RetryConfig, AgentConfig, request_timeout, and ApiClient::new.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/config/mod.rs`:
- Around line 168-181: The minute and hour branches currently compute m * 60 and
h * 3600 which can overflow; update those closures to use checked_mul and fail
the parse on overflow. For the 'm' branch replace .map(|m| Duration::from_secs(m
* 60)) with something like .and_then(|m| m.checked_mul(60).ok_or("duration
overflow".to_string()).map(Duration::from_secs)), and similarly for the 'h'
branch use h.checked_mul(3600).ok_or(...).map(Duration::from_secs) so parse
failures and multiplication overflows both return Err(String).
In `@src/main.rs`:
- Around line 26-33: The service subcommand branch discards other CLI options
(parsed by Cli::parse) by only forwarding cli.command to
hash_hive_agent::service::handle, causing service handlers in service.rs to fall
back to env discovery; update the call site to propagate the parsed CLI settings
— either initialize/apply the parsed config/logging options before calling
hash_hive_agent::service::handle or change handle to accept the full Cli or a
Config struct (e.g., pass cli or a new Config built from --config, --server-url,
--agent-token, --hashcat-path, --json-logs, --log-level) so
service-install/service-uninstall use the provided CLI values rather than
environment defaults.
- Around line 101-109: The classify_exit_code function currently treats "invalid
server URL" as a runtime error; update classify_exit_code(err: &anyhow::Error)
to also detect the "invalid server URL" message (or the underlying URL parse
error) and return EXIT_CONFIG for that case so malformed server_url is
classified as a configuration failure; locate the function by name
(classify_exit_code) and add an additional branch or include "invalid server
URL" in the existing config-match condition that returns EXIT_CONFIG.
In `@src/service.rs`:
- Around line 39-65: Remove HASH_HIVE_AGENT_TOKEN from the environment vector so
the agent token is not written into ServiceInstallCtx.environment (avoid
persisting secrets to world-readable service files); in the loop that builds
env_vars drop any entry where key == "HASH_HIVE_AGENT_TOKEN" (or filter it out
before building ServiceInstallCtx), leaving other keys unchanged, and instead
document/implement sourcing the token from a secure store (config file with
0600, platform credential store, or secrets manager) when the service starts.
---
Outside diff comments:
In `@src/hashcat/session.rs`:
- Around line 56-140: The start() function currently returns the live Child and
never converts process termination into a SessionEvent::Exit; add a dedicated
task inside start() that owns the child lifecycle: await child.wait(), map the
ExitStatus into SessionEvent::Exit and send it on the mpsc::Sender (tx) so the
runner sees clean exits, and also observe the CancellationToken to call
child.kill() (or .start_kill()) on cancellation before awaiting so cancellation
produces an Exit event too; keep existing stdout/stderr reader tasks
(handle_stdout_line, classify_line) but ensure they don't outlive the
exit-sender task and that sending SessionEvent::Exit handles a closed receiver
gracefully.
---
Duplicate comments:
In `@src/api/client.rs`:
- Around line 128-135: The POST to "tasks/next" is retried via with_retry but no
idempotency key is set, so duplicate POSTs can double-assign work; fix by
generating a single idempotency key once per logical get_next_task invocation
(e.g., let idempotency_key = Uuid::new_v4()) before calling with_retry and
capture it in the async closure passed to with_retry, then attach that same key
as a request header (e.g., "Idempotency-Key") on the request created by
authed_post(&url) so every retry replays the same idempotency token; also
consider verifying server dedup semantics if present.
- Around line 18-35: The request timeout from AgentConfig is being dropped so
reqwest never gets a client timeout; update the code to carry the
request_timeout through into RetryConfig (add a pub request_timeout: Duration
field initialized from cfg.request_timeout) and then apply it when building the
HTTP client inside ApiClient::new() by calling the reqwest
Client::builder().timeout(cfg_or_retry.request_timeout) before .build(),
ensuring hung requests become reqwest timeout errors (is_timeout()) and thus
retryable; references: RetryConfig, AgentConfig, request_timeout, and
ApiClient::new.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6b518812-4083-41cf-bcd9-8ac584cd5e42
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (13)
.cargo/audit.tomlCargo.tomlGOTCHAS.mdsrc/agent/mod.rssrc/api/client.rssrc/cli.rssrc/config/defaults.rssrc/config/mod.rssrc/hashcat/session.rssrc/lib.rssrc/main.rssrc/service.rssrc/task/downloader.rs
✅ Files skipped from review due to trivial changes (3)
- .cargo/audit.toml
- src/lib.rs
- Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (2)
- src/task/downloader.rs
- src/agent/mod.rs
| if let Some(rest) = trimmed.strip_suffix('s') { | ||
| rest.trim() | ||
| .parse::<u64>() | ||
| .map(Duration::from_secs) | ||
| .map_err(|e| e.to_string()) | ||
| } else if let Some(rest) = s.strip_suffix('m') { | ||
| } else if let Some(rest) = trimmed.strip_suffix('m') { | ||
| rest.trim() | ||
| .parse::<u64>() | ||
| .map(|m| Duration::from_secs(m * 60)) | ||
| .map_err(|e| e.to_string()) | ||
| } else if let Some(rest) = s.strip_suffix('h') { | ||
| } else if let Some(rest) = trimmed.strip_suffix('h') { | ||
| rest.trim() | ||
| .parse::<u64>() | ||
| .map(|h| Duration::from_secs(h * 3600)) |
There was a problem hiding this comment.
Reject overflow in minute/hour duration parsing.
m * 60 and h * 3600 can wrap on large inputs in release builds, turning an invalid config value into a much smaller timeout/backoff. Use checked_mul and fail the parse instead.
Suggested fix
- } else if let Some(rest) = trimmed.strip_suffix('m') {
- rest.trim()
- .parse::<u64>()
- .map(|m| Duration::from_secs(m * 60))
- .map_err(|e| e.to_string())
- } else if let Some(rest) = trimmed.strip_suffix('h') {
- rest.trim()
- .parse::<u64>()
- .map(|h| Duration::from_secs(h * 3600))
- .map_err(|e| e.to_string())
+ } else if let Some(rest) = trimmed.strip_suffix('m') {
+ let minutes = rest.trim().parse::<u64>().map_err(|e| e.to_string())?;
+ let secs = minutes
+ .checked_mul(60)
+ .ok_or_else(|| format!("duration overflow: {trimmed}"))?;
+ Ok(Duration::from_secs(secs))
+ } else if let Some(rest) = trimmed.strip_suffix('h') {
+ let hours = rest.trim().parse::<u64>().map_err(|e| e.to_string())?;
+ let secs = hours
+ .checked_mul(3600)
+ .ok_or_else(|| format!("duration overflow: {trimmed}"))?;
+ Ok(Duration::from_secs(secs))🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/config/mod.rs` around lines 168 - 181, The minute and hour branches
currently compute m * 60 and h * 3600 which can overflow; update those closures
to use checked_mul and fail the parse on overflow. For the 'm' branch replace
.map(|m| Duration::from_secs(m * 60)) with something like .and_then(|m|
m.checked_mul(60).ok_or("duration
overflow".to_string()).map(Duration::from_secs)), and similarly for the 'h'
branch use h.checked_mul(3600).ok_or(...).map(Duration::from_secs) so parse
failures and multiplication overflows both return Err(String).
| // Service management subcommands run without logging/config. | ||
| if let Some(ref cmd) = cli.command { | ||
| if let Err(e) = hash_hive_agent::service::handle(cmd) { | ||
| eprintln!("error: {e:#}"); | ||
| std::process::exit(EXIT_RUNTIME); | ||
| } | ||
| return; | ||
| } |
There was a problem hiding this comment.
Service subcommands currently discard every other CLI option.
Cli::parse() still accepts --config, --server-url, --agent-token, --hashcat-path, --json-logs, and --log-level, but this branch only forwards cli.command. src/service.rs then falls back to environment discovery, so a call like hash_hive_agent --config /etc/agent.toml service-install installs a service that will not use the supplied CLI values.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main.rs` around lines 26 - 33, The service subcommand branch discards
other CLI options (parsed by Cli::parse) by only forwarding cli.command to
hash_hive_agent::service::handle, causing service handlers in service.rs to fall
back to env discovery; update the call site to propagate the parsed CLI settings
— either initialize/apply the parsed config/logging options before calling
hash_hive_agent::service::handle or change handle to accept the full Cli or a
Config struct (e.g., pass cli or a new Config built from --config, --server-url,
--agent-token, --hashcat-path, --json-logs, --log-level) so
service-install/service-uninstall use the provided CLI values rather than
environment defaults.
… downloads Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
…installation Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
… and config issues Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
- Replace string-based exit code classification with error downcasting
(ApiError::Auth, config::ConfigError) for type-safe exit codes
- Use alternate Display format ({:#}) for server error reports to
include full anyhow error chain instead of just top-level message
- Warn on invalid --log-level values instead of silently falling back
- Surface unexpected service stop errors during uninstall instead of
silently dropping all errors
- Simplify service.rs env var collection with iterator chain
- Remove dead _results computation in task runner
- Collapse nested ifs into let-chains per clippy
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
There was a problem hiding this comment.
♻️ Duplicate comments (1)
src/main.rs (1)
117-122:⚠️ Potential issue | 🟠 MajorAdd
invalid server URLto config error classification.The string-matching fallback handles
"agent token is required"and"failed to load configuration", but the URL parse error context ("invalid server URL") fromsrc/agent/mod.rsis not covered. This causes bad URLs to returnEXIT_RUNTIMEinstead ofEXIT_CONFIG.🐛 Proposed fix
let msg = format!("{err:#}"); - if msg.contains("agent token is required") || msg.contains("failed to load configuration") { + if msg.contains("agent token is required") + || msg.contains("failed to load configuration") + || msg.contains("invalid server URL") + { return EXIT_CONFIG; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main.rs` around lines 117 - 122, The fallback error-classification block that builds msg (let msg = format!("{err:#}")) should also detect the "invalid server URL" context and map it to EXIT_CONFIG; update the conditional that checks msg.contains("agent token is required") || msg.contains("failed to load configuration") to include msg.contains("invalid server URL") so URL parse errors from src/agent/mod.rs are classified as configuration failures and return EXIT_CONFIG.
🧹 Nitpick comments (5)
src/task/downloader.rs (2)
119-121: Thebuf.get(..n)check is redundant.Since
nis returned fromreader.read(&mut buf), it's guaranteed thatn <= buf.len(). The slice&buf[..n]will always be valid, making theif let Some(chunk)check unnecessary.🔧 Simplify to direct slice
if n == 0 { break; } - if let Some(chunk) = buf.get(..n) { - hasher.update(chunk); - } + hasher.update(&buf[..n]); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/task/downloader.rs` around lines 119 - 121, The conditional using buf.get(..n) is redundant because n is the byte count returned by reader.read and always <= buf.len(); replace the if-let block with a direct slice update by calling hasher.update(&buf[..n]) (locate this change near the read loop where buf, n and hasher.update are used in downloader.rs) so the code directly updates the hasher with the read bytes without the unnecessary Option check.
46-67: Consider disabling progress bars when stderr is not a TTY.In daemon/service mode or CI pipelines, the progress bar output to stderr may interfere with structured logging or produce excessive noise.
indicatifsupports hidden progress bars viaProgressBar::hidden()when!std::io::stderr().is_terminal().💡 Optional: TTY-aware progress bar creation
let total_size = resp.content_length().unwrap_or(0); + let is_tty = std::io::stderr().is_terminal(); let progress = match total_size { - 0 => { + _ if !is_tty => ProgressBar::hidden(), + 0 => { let pb = ProgressBar::new_spinner(); // ... rest unchangedThis requires adding
use std::io::IsTerminal;(stable since Rust 1.70).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/task/downloader.rs` around lines 46 - 67, The progress bar is always created and may spam stderr in non-TTY environments; update the progress construction in the total_size match (the total_size variable and progress binding) to check stderr TTY via std::io::stderr().is_terminal() (add use std::io::IsTerminal) and use ProgressBar::hidden() when not a terminal instead of ProgressBar::new_spinner()/ProgressBar::new(n), preserving the existing styles for the TTY case (references: ProgressBar::new_spinner, ProgressBar::new, ProgressBar::hidden, ProgressStyle::default_spinner, ProgressStyle::default_bar).src/service.rs (2)
24-32: Add wildcard arm for#[non_exhaustive]enum.The
Commandenum insrc/cli.rsis marked#[non_exhaustive], which means the compiler will not enforce exhaustive matching. If a new variant is added toCommand, this match will silently fail to compile only within the same crate — external consumers would get a runtime mismatch. Since this is the same crate, you're currently safe, but adding a wildcard with an explicit error improves defensive coding.🛡️ Suggested defensive pattern
pub fn handle(command: &Command) -> Result<()> { match *command { Command::ServiceInstall => install(), Command::ServiceUninstall => uninstall(), Command::ServiceStart => start(), Command::ServiceStop => stop(), Command::ServiceStatus => status(), + #[allow(unreachable_patterns)] + _ => anyhow::bail!("unhandled service command"), } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/service.rs` around lines 24 - 32, The match in function handle on the non-exhaustive Command enum lacks a wildcard arm; update handle (the match over Command with arms calling install(), uninstall(), start(), stop(), status()) to include a final _ => Err(anyhow::anyhow!("unsupported command variant")) (or equivalent error) so unknown future variants return a clear Result::Err instead of causing unexpected behavior; keep existing arms intact and ensure the error message names the function (handle) and the enum (Command) for clarity.
53-67: Consider documenting the--json-logsdefault.The service is installed with
--json-logshardcoded. This is a reasonable default for services (structured logs are easier to parse), but users may expect text logs. Consider adding a brief comment explaining this choice or making it configurable.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/service.rs` around lines 53 - 67, The ServiceInstallCtx is hardcoding "--json-logs" in args which should be either documented or made configurable; update the code around the ServiceInstallCtx construction to either (a) add a short comment above the ctx explaining why "--json-logs" is chosen (structured logs for parsing/monitoring) or (b) make it configurable by introducing a boolean flag (e.g., enable_json_logs) passed into the surrounding function and use it to set args (args: enable_json_logs.then(|| vec![OsString::from("--json-logs")]).ensure a sensible default (true) and propagate the flag through callers so users can opt out, referencing ServiceInstallCtx and the args field when making the change.src/task/runner.rs (1)
133-133: Add validation guard to prevent negative work range.The
#[allow(clippy::arithmetic_side_effects)]annotation suppresses warnings but does not prevent the arithmetic error. Line 149 computesrange.end - range.startwithout checking thatrange.end >= range.start. If the server sends an invalid range, this will wrap and produce a very large limit value passed to hashcat.Add a debug assertion:
Defensive validation
if let Some(ref range) = task.work_range { + debug_assert!(range.end >= range.start, "invalid work range"); args.push("--skip".to_owned()); args.push(range.start.to_string()); args.push("--limit".to_owned()); args.push((range.end - range.start).to_string()); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/task/runner.rs` at line 133, Add a defensive validation for the work range before performing the subtraction used to compute the limit: check that range.end >= range.start (e.g., with a debug_assert! and/or an early error/return) prior to the computation `range.end - range.start` in the task runner where the limit for hashcat is derived; if the check fails, return an appropriate error or refuse the job instead of letting the subtraction wrap to a huge value. Ensure the check is placed near the existing clippy attribute and references the same `range` variable so the downstream code that builds the hashcat limit uses a validated, non-negative value.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/main.rs`:
- Around line 117-122: The fallback error-classification block that builds msg
(let msg = format!("{err:#}")) should also detect the "invalid server URL"
context and map it to EXIT_CONFIG; update the conditional that checks
msg.contains("agent token is required") || msg.contains("failed to load
configuration") to include msg.contains("invalid server URL") so URL parse
errors from src/agent/mod.rs are classified as configuration failures and return
EXIT_CONFIG.
---
Nitpick comments:
In `@src/service.rs`:
- Around line 24-32: The match in function handle on the non-exhaustive Command
enum lacks a wildcard arm; update handle (the match over Command with arms
calling install(), uninstall(), start(), stop(), status()) to include a final _
=> Err(anyhow::anyhow!("unsupported command variant")) (or equivalent error) so
unknown future variants return a clear Result::Err instead of causing unexpected
behavior; keep existing arms intact and ensure the error message names the
function (handle) and the enum (Command) for clarity.
- Around line 53-67: The ServiceInstallCtx is hardcoding "--json-logs" in args
which should be either documented or made configurable; update the code around
the ServiceInstallCtx construction to either (a) add a short comment above the
ctx explaining why "--json-logs" is chosen (structured logs for
parsing/monitoring) or (b) make it configurable by introducing a boolean flag
(e.g., enable_json_logs) passed into the surrounding function and use it to set
args (args: enable_json_logs.then(|| vec![OsString::from("--json-logs")]).ensure
a sensible default (true) and propagate the flag through callers so users can
opt out, referencing ServiceInstallCtx and the args field when making the
change.
In `@src/task/downloader.rs`:
- Around line 119-121: The conditional using buf.get(..n) is redundant because n
is the byte count returned by reader.read and always <= buf.len(); replace the
if-let block with a direct slice update by calling hasher.update(&buf[..n])
(locate this change near the read loop where buf, n and hasher.update are used
in downloader.rs) so the code directly updates the hasher with the read bytes
without the unnecessary Option check.
- Around line 46-67: The progress bar is always created and may spam stderr in
non-TTY environments; update the progress construction in the total_size match
(the total_size variable and progress binding) to check stderr TTY via
std::io::stderr().is_terminal() (add use std::io::IsTerminal) and use
ProgressBar::hidden() when not a terminal instead of
ProgressBar::new_spinner()/ProgressBar::new(n), preserving the existing styles
for the TTY case (references: ProgressBar::new_spinner, ProgressBar::new,
ProgressBar::hidden, ProgressStyle::default_spinner,
ProgressStyle::default_bar).
In `@src/task/runner.rs`:
- Line 133: Add a defensive validation for the work range before performing the
subtraction used to compute the limit: check that range.end >= range.start
(e.g., with a debug_assert! and/or an early error/return) prior to the
computation `range.end - range.start` in the task runner where the limit for
hashcat is derived; if the check fails, return an appropriate error or refuse
the job instead of letting the subtraction wrap to a huge value. Ensure the
check is placed near the existing clippy attribute and references the same
`range` variable so the downstream code that builds the hashcat limit uses a
validated, non-negative value.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 4e11a17d-f0d8-45a1-b917-77daec3d9a92
📒 Files selected for processing (4)
src/main.rssrc/service.rssrc/task/downloader.rssrc/task/runner.rs
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
…r AI-assisted contributions Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Summary
Implements exponential backoff with jitter for all API requests, adds CLI UX improvements, cross-platform service management, and restructures project documentation.
34 files changed (+1,636 / -351) across 4 main areas:
backoncrate with exponential backoff, jitter, and precise error classificationservice-managercrate for systemd/launchd/sc.exe install/start/stopWhat Changed
API Retry / Backoff
RetryConfigmapsAgentConfigbackoff fields tobackon::ExponentialBuilderis_retryable()classifies errors: only 5xx and transient network errors (timeout/connect) retry; auth, parse, not-found fail immediatelyApiClientmethods usewith_retryinternally — retries are transparent to callersApiClient::newandurl()now returnResultinstead of panicking{:#}formatCLI UX
-v/--verboseflag (count-based:-v= debug,-vv= trace)NO_COLORenv var and TTY detection for ANSI outputindicatifprogress bars for file downloads (bytes/speed/ETA)--json-logsnow supportsHASH_HIVE_JSON_LOGSenv varlong_aboutwith lifecycle description,value_namehints on all argsService Management
service-install,service-uninstall,service-start,service-stop,service-statussubcommandsHASH_HIVE_*env vars, sets restart-on-failure with 5s delaySystem Paths
/var/lib/hash_hive_agent(Unix),%ProgramData%\HashHive\Agent\data(Windows)/var/cache/hash_hive_agent(Unix),%ProgramData%\HashHive\Agent\cache(Windows)Error Handling Improvements
fs::read— OOM on 100GB+ files)extract_error_messagelogs body-read failures instead of returning empty stringparse_status_progresslogs missing JSON fields instead of silently defaulting to zeroDocumentation
Dependency Updates
backon,indicatif,service-managerTest plan
just test)cargo clippy --all-targets)cargo auditclean (no advisories)hash-hive-agent --helpshows new long_about and verbose flaghash-hive-agent service-installon Linux (requires root)NO_COLOR=1suppresses ANSI codes