Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
caa473a
feat(cli): --quiet flag, pager, per-stream TTY, error deduplication
Patel230 Jul 22, 2026
6fd5384
fix(tui): Esc is no-op during active agent turn
Patel230 Jul 22, 2026
9b3661c
feat(cli): comprehensive quality hardening and production readiness
Patel230 Jul 23, 2026
a85e61b
fix(cli): line-by-line review fixes — panics, security, resource leaks
Patel230 Jul 23, 2026
777a835
fix(cli): critical bugs from deep review — notification, UTF-8, Wayland
Patel230 Jul 23, 2026
4936b6c
fix(theme): test correctness and minor cleanups
Patel230 Jul 23, 2026
e937779
fix(cli): deep review follow-ups — hardening, correctness, cache inva…
Patel230 Jul 23, 2026
e3df9ca
feat(cli): UX overhaul — history search, session picker, code block c…
Patel230 Jul 23, 2026
e5f9daf
perf(cli): deep audit fixes — performance, memory, UX, accessibility
Patel230 Jul 23, 2026
13eb7cc
fix(cli): audit round 2 — concurrency, resource cleanup, error handli…
Patel230 Jul 23, 2026
a436d35
fix(cli): audit round 3 — fix goroutine leaks in permission/askUser t…
Patel230 Jul 23, 2026
9baf4e3
fix(cli): line-by-line review — correct 4 bugs in prior audit rounds
Patel230 Jul 23, 2026
53d9019
fix(cli): audit round 4 — WAL data-loss, batch duplication, markdown …
Patel230 Jul 23, 2026
18a7236
fix(cli): audit round 5 — secret-redaction leak, fork panic, UTF-8 pr…
Patel230 Jul 23, 2026
c309492
fix(cli): audit round 6 — compressFile close-error data loss
Patel230 Jul 23, 2026
4c4c669
fix(cli): audit round 7 — search preview UTF-8 truncation
Patel230 Jul 23, 2026
49b953a
fix(cli): audit round 8 — welcome-screen short-ID panic guard, UTF-8-…
Patel230 Jul 23, 2026
36cc7de
fix(cli): audit round 9 — UTF-8-safe truncations across eval/council/…
Patel230 Jul 23, 2026
b3da4ac
fix(cli): audit round 10 — UTF-8-safe tail truncation for CWD/path di…
Patel230 Jul 23, 2026
d2e120a
fix(cli): audit round 11 — display-width-aware (runewidth) column ali…
Patel230 Jul 23, 2026
729e813
fix(cli): audit round 12 — rune-safe, display-width-aware truncateVis…
Patel230 Jul 23, 2026
6d0da20
fix(cli): audit round 13 — display-width-aware autocomplete suggestio…
Patel230 Jul 23, 2026
ebaf032
fix(cli): audit round 14 — display-width-aware scrollback focus bar s…
Patel230 Jul 23, 2026
8080202
chore(cli): audit round 15 — remove dead duplicate package-level full…
Patel230 Jul 23, 2026
288cebf
fix(cli): audit round 16 — rune-safe case-insensitive match highlighting
Patel230 Jul 23, 2026
5fa3a0a
fix(cli): audit round 17 — promote rune-safe IndexFold, fix search/fe…
Patel230 Jul 23, 2026
0cd98c7
fix(cli): audit round 18 — rune-safe reasoning parse in sight submodule
Patel230 Jul 23, 2026
860a583
fix(cli): audit round 19 — rune-safe focus extraction in tok submodule
Patel230 Jul 23, 2026
6693270
style(cli): audit round 20 — gofmt-clean the cmd tree
Patel230 Jul 23, 2026
ecee94b
fix(cli): audit round 21 — eliminate data race in /voice subcommand
Patel230 Jul 23, 2026
955de23
fix(cli): audit round 24 — bump trace submodule (rune-safe truncateStr)
Patel230 Jul 23, 2026
5cc681f
fix(cli): audit round 25 — bump tok/eyrie/yaad submodules (rune-safe …
Patel230 Jul 23, 2026
d9328f7
fix(cli): audit round 26 — bump sight/inspect submodules (rune/char-s…
Patel230 Jul 23, 2026
8d8ce78
fix(cli): audit round 27 — rune-safe display truncation in cmd helpers
Patel230 Jul 23, 2026
d27b9bd
fix(cli): audit round 28 — rune-safe truncation in internal helpers
Patel230 Jul 23, 2026
3a393c2
fix(cli): audit round 29 — rune-safe truncation across internal/ inli…
Patel230 Jul 23, 2026
280a1ae
fix(cli): audit round 30 — snap extractContext window edges to UTF-8 …
Patel230 Jul 23, 2026
ed36f7f
fix(cli): audit round 31 — release per-iteration resources in retry/s…
Patel230 Jul 23, 2026
b6e0ea1
fix(cli): audit round 35 — bump inspect submodule (timeout-bounded ax…
Patel230 Jul 23, 2026
e490bc8
fix(cli): audit round 37 — private state files created world-readable…
Patel230 Jul 23, 2026
892884d
fix(cli): audit round 40 — unstopped ticker in WatchOSTheme
Patel230 Jul 23, 2026
53bf8e2
feat(cli): wire up manpage, completion install, update commands; fix …
Patel230 Jul 23, 2026
86cb6ab
feat(cli): add bug-report command, expand --help long description
Patel230 Jul 23, 2026
e50c6b2
feat(cli): generate man page OPTIONS from live Cobra flag set
Patel230 Jul 23, 2026
813f904
docs: add shell completions user guide (25-shell-completions.md)
Patel230 Jul 23, 2026
eba2492
feat(doctor): add --json flag for machine-readable diagnostics output
Patel230 Jul 23, 2026
a8aa709
feat(sessions ls): add --json flag for machine-readable background se…
Patel230 Jul 23, 2026
22a1cdc
feat(eval): add --json flags to 'list' and 'results' subcommands
Patel230 Jul 23, 2026
5c9eb89
feat(trust list): add --json flag for machine-readable trust store ou…
Patel230 Jul 23, 2026
ca8a373
feat(rules detect): add --json flag for machine-readable rule file de…
Patel230 Jul 23, 2026
3d10ea9
feat(path): add --json flag and JSON tags to developer path report
Patel230 Jul 23, 2026
0423b2f
feat(daemon status): add --json flag for machine-readable daemon status
Patel230 Jul 23, 2026
54c1e56
feat(snapshot): add --json flag to list and diff subcommands
Patel230 Jul 23, 2026
03782bc
feat(plugin list): add --json flag for machine-readable plugin listing
Patel230 Jul 23, 2026
8a12629
feat(tools): add --json flag for machine-readable tool listing
Patel230 Jul 23, 2026
7f118a0
feat(feedback): add --json flag for machine-readable feedback report
Patel230 Jul 23, 2026
67985c3
feat(ecosystem): add --json flag and structured EcosystemReport type
Patel230 Jul 23, 2026
60551db
feat(plan): add --json flag to list and show subcommands
Patel230 Jul 23, 2026
7fcbec3
feat(config): add JSON tags to CatalogHealth struct
Patel230 Jul 23, 2026
5604e60
feat: add --json flag to checkpoint list
Patel230 Jul 23, 2026
cdff253
test(hawk): remove dead catalog test skip guards and stale FIXMEs
Patel230 Jul 24, 2026
6b9075f
feat(cli): add --json flag to agent list, cost analyze/summary, and v…
Patel230 Jul 24, 2026
836f487
test(cli): cover new --json flags for agent, cost, and version
Patel230 Jul 24, 2026
6c84689
feat(cli): add --json flag to preflight for machine-readable readiness
Patel230 Jul 24, 2026
05e4c1c
docs(arch): add Client SDKs to Ecosystem Integration section
Patel230 Jul 24, 2026
ccc6b77
feat: add execution graph, graph journal, and cloud graph features
Patel230 Jul 25, 2026
9da602d
chore: update submodules to latest commits
Patel230 Jul 25, 2026
5040a90
chore: update inspect and sight submodules after conflict resolution
Patel230 Jul 25, 2026
3c837e1
feat: implement LangGraph-style StateGraph
Patel230 Jul 25, 2026
7c74ae7
test: add test suites for new graph and loop architecture
Patel230 Jul 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,27 @@ jobs:
# Optional secrets used by some repos' goreleaser configs:
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
TAP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }}

# Sign release artifacts with cosign keyless signing. The
# id-token: write permission above enables OIDC federation with
# Fulcio's root CA — no long-lived signing keys to manage.
- name: Install cosign
uses: sigstore/cosign-installer@d8a3f51ef971a853e51de6231a89f4483c5a7a0e # v3.4.0

- name: Sign release checksums with cosign
run: |
set -euo pipefail
# Download the checksums artifact produced by goreleaser.
gh release download "${GITHUB_REF_NAME}" --pattern "checksums.txt" -D dist/
# Sign with keyless OIDC — output is dist/checksums.txt.sig (bundle).
cosign sign-blob \
--yes \
--output-signature dist/checksums.txt.sig \
--output-certificate dist/checksums.txt.cert \
dist/checksums.txt
# Upload the signature and certificate back to the release.
gh release upload "${GITHUB_REF_NAME}" \
dist/checksums.txt.sig \
dist/checksums.txt.cert
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6 changes: 6 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ sboms:
documents:
- "${artifact}.spdx.sbom.json"

# ---------------------------------------------------------------------------
# Signing — cosign keyless signing of checksums is performed in the
# release workflow (post-goreleaser) so the OIDC token from GitHub Actions
# is available. The checksums.txt artifact is signed there.
# ---------------------------------------------------------------------------

release:
draft: false
prerelease: auto
Expand Down
35 changes: 34 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,35 @@ Built with [Bubble Tea](https://github.com/charmbracelet/bubbletea) for a smooth
| **Code** | `LSP` diagnostics, `CodeSearch`, `NotebookEdit`, `SQL` (read-only DB exploration) |
| **MCP** | `ListMcpResources`, `ReadMcpResource` |

### Portable Execution Graph

Export the latest or a selected Hawk session as validated graph nodes, edges,
and lifecycle events:

```bash
hawk graph export
hawk graph export <session-id>
hawk graph export <session-id> --trace-checkpoint abc123def456
hawk graph export --mission-dir /path/to/mission

# Explicitly privacy-normalize and sync the graph for a connected cloud project
hawk cloud graph sync <session-id>
hawk cloud graph sync --mission-dir /path/to/mission
```

The export contains metadata and hashes, not prompts, tool arguments/results,
policy reasons, verification evidence, or runtime output. Trace remains
available separately as `hawk trace graph export`. Persisted chat sessions
automatically append privacy-safe permission, enabled approval-gate, and
`VerifyPlanExecution` summaries for subsequent graph exports. Yaad memory
subgraphs and Hawk code-index chunks actually selected for inference are also
journaled as metadata-only knowledge nodes and linked to the session. Inspect's
observed bridge path similarly journals bounded, metadata-only report/finding
quality subgraphs. Sight exposes the same observed bridge boundary for
metadata-only code-review quality subgraphs. Mission runs also persist a
portable `mission-graph.json`; the mission form is validated and synchronized
explicitly with the `--mission-dir` variants above.

### Multi-Agent Mission Mode (optional)

For larger tasks, decompose work into parallel feature branches (power-user / future team workflows):
Expand Down Expand Up @@ -271,6 +300,7 @@ Endpoints: `GET /v1/health`, `GET /v1/ready` (dependency-aware readiness), `POST
hawk mission "Add auth, rate limiting, and logging"
hawk mission --workers 6 "Refactor into microservices"
hawk mission --dry-run "What would this decompose into?"
hawk mission --from-tasks # Execute validated dependency waves
```

## Providers
Expand Down Expand Up @@ -375,12 +405,15 @@ You may keep a **personal** parent **`go.work`** that lists alternate clones on
| **eyrie** | [GrayCodeAI/eyrie](https://github.com/GrayCodeAI/eyrie) | LLM provider runtime |
| **sight** | [GrayCodeAI/sight](https://github.com/GrayCodeAI/sight) | Diff-based code review (`hawk sight`) |
| **inspect** | [GrayCodeAI/inspect](https://github.com/GrayCodeAI/inspect) | Site audit library |
| **tok** | [GrayCodeAI/tok](https://github.com/GrayCodeAI/tok) | Tokenizer & compression |
| **tok** | [GrayCodeAI/tok](https://github.com/GrayCodeAI/tok) | Compression, redaction, token/cost budgets, and privacy-safe runtime graph facts |
| **yaad** | [GrayCodeAI/yaad](https://github.com/GrayCodeAI/yaad) | Graph-based memory |
| **trace** | [GrayCodeAI/trace](https://github.com/GrayCodeAI/trace) | Session capture and replay engine mounted as `hawk trace ...` |
| **hawk-core-contracts** | [GrayCodeAI/hawk-core-contracts](https://github.com/GrayCodeAI/hawk-core-contracts) | Shared contracts and neutral cross-repo vocabulary |

For the consolidated repo map and the current-vs-proposed architecture diagrams, see [docs/architecture/hawk-current-vs-proposed.md](docs/architecture/hawk-current-vs-proposed.md).
For execution-graph ownership, automatic capture seams, export/sync commands,
and the Trace correlation contract, see
[docs/architecture/execution-graph.md](docs/architecture/execution-graph.md).

## Development

Expand Down
216 changes: 216 additions & 0 deletions api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,154 @@ components:
tool_calls:
type: integer

GraphScope:
type: object
properties:
tenant_id:
type: string
project_id:
type: string
repository_id:
type: string

GraphRef:
type: object
required: [kind, id]
properties:
kind:
type: string
enum: [system, knowledge, execution, policy, quality, operations]
id:
type: string

GraphArtifactRef:
type: object
required: [uri]
properties:
uri:
type: string
digest:
type: string
media_type:
type: string

GraphProvenance:
type: object
required: [producer]
properties:
producer:
type: string
version:
type: string
source_id:
type: string
evidence:
type: array
items:
$ref: "#/components/schemas/GraphArtifactRef"

GraphNode:
type: object
required: [id, kind, created_at, provenance]
properties:
id:
type: string
kind:
type: string
enum: [system, knowledge, execution, policy, quality, operations]
scope:
$ref: "#/components/schemas/GraphScope"
created_at:
type: string
format: date-time
effective_at:
type: string
format: date-time
provenance:
$ref: "#/components/schemas/GraphProvenance"
attributes:
type: object
additionalProperties:
type: string

GraphEdge:
type: object
required: [id, kind, from, to, created_at, provenance]
properties:
id:
type: string
kind:
type: string
enum: [contains, depends_on, references, produced, governed_by, validated_by]
from:
$ref: "#/components/schemas/GraphRef"
to:
$ref: "#/components/schemas/GraphRef"
scope:
$ref: "#/components/schemas/GraphScope"
created_at:
type: string
format: date-time
effective_at:
type: string
format: date-time
provenance:
$ref: "#/components/schemas/GraphProvenance"
attributes:
type: object
additionalProperties:
type: string

GraphEvent:
type: object
required: [id, type, subject, occurred_at, provenance]
properties:
id:
type: string
type:
type: string
enum: [created, updated, transitioned, observed, deleted]
subject:
$ref: "#/components/schemas/GraphRef"
scope:
$ref: "#/components/schemas/GraphScope"
occurred_at:
type: string
format: date-time
correlation_id:
type: string
causation_id:
type: string
idempotency_key:
type: string
provenance:
$ref: "#/components/schemas/GraphProvenance"

ExecutionGraph:
type: object
required: [schema_version, generated_at, scope, nodes, edges, events]
properties:
schema_version:
type: string
enum: [hawk.graph/v1]
generated_at:
type: string
format: date-time
scope:
$ref: "#/components/schemas/GraphScope"
nodes:
type: array
items:
$ref: "#/components/schemas/GraphNode"
edges:
type: array
items:
$ref: "#/components/schemas/GraphEdge"
events:
type: array
items:
$ref: "#/components/schemas/GraphEvent"

Message:
type: object
properties:
Expand Down Expand Up @@ -259,6 +407,8 @@ tags:
description: Session management
- name: messages
description: Message history
- name: graphs
description: Portable read-only execution graph projections
- name: stats
description: Usage statistics
- name: review
Expand Down Expand Up @@ -458,6 +608,72 @@ paths:
schema:
$ref: "#/components/schemas/Error"

/v1/sessions/{id}/graph:
get:
tags: [graphs]
summary: Project a persisted session as a portable execution graph
description: |
Returns Hawk's privacy-safe, read-only `hawk.graph/v1` projection.
Prompt text, tool arguments, tool output, and verification details are
excluded. Explicit Trace checkpoint IDs are additive to authoritative
Trace session correlation performed by Hawk.
parameters:
- name: id
in: path
required: true
schema:
type: string
maxLength: 128
pattern: '^[A-Za-z0-9._-]+$'
- name: repository
in: query
description: Optional repository scope override.
schema:
type: string
maxLength: 256
- name: trace_checkpoint
in: query
description: Optional 12-character lowercase hexadecimal Trace checkpoint ID. May be repeated up to 64 times.
schema:
type: array
maxItems: 64
items:
type: string
pattern: '^[0-9a-f]{12}$'
style: form
explode: true
responses:
"200":
description: Portable execution graph
content:
application/json:
schema:
$ref: "#/components/schemas/ExecutionGraph"
"400":
description: Invalid session, repository, or checkpoint input
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
"404":
description: Session not found
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
"503":
description: Graph projection is not configured
content:
application/json:
schema:
$ref: "#/components/schemas/Error"

/v1/stats:
get:
tags: [stats]
Expand Down
22 changes: 20 additions & 2 deletions cmd/agent.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"encoding/json"
"fmt"
"os"
"path/filepath"
Expand All @@ -18,6 +19,8 @@ var agentCmd = &cobra.Command{
Long: "Create, list, and manage custom agent personas stored in Hawk user state.",
}

var agentListJSON bool

var agentListCmd = &cobra.Command{
Use: "list",
Short: "List all available agents",
Expand Down Expand Up @@ -54,17 +57,29 @@ func init() {
agentCreateCmd.Flags().StringVarP(&agentCreateDesc, "description", "d", "", "Agent description")
agentCreateCmd.Flags().StringVarP(&agentCreateModel, "model", "m", "", "Model to use (empty = inherit)")

agentListCmd.Flags().BoolVar(&agentListJSON, "json", false, "output agents as JSON")
agentCmd.AddCommand(agentListCmd)
agentCmd.AddCommand(agentCreateCmd)
agentCmd.AddCommand(agentShowCmd)
agentCmd.AddCommand(agentRemoveCmd)
}

func runAgentList(_ *cobra.Command, _ []string) error {
func runAgentList(cmd *cobra.Command, _ []string) error {
all, err := agents.ListAll()
if err != nil {
return err
}
if agentListJSON {
if all == nil {
all = []*agents.Agent{}
}
out, err := json.MarshalIndent(all, "", " ")
if err != nil {
return fmt.Errorf("marshaling agents: %w", err)
}
cmd.Println(string(out))
return nil
}
if len(all) == 0 {
fmt.Printf("No agents found. Create one with: hawk agent create <name>\n")
fmt.Printf("Agent directory: %s\n", agents.DefaultDir())
Expand All @@ -80,7 +95,10 @@ func runAgentList(_ *cobra.Command, _ []string) error {
}
desc := a.Description
if len(desc) > 50 {
desc = desc[:50] + "..."
// Rune-safe truncation: never split a multibyte UTF-8 sequence.
if runes := []rune(desc); len(runes) > 50 {
desc = string(runes[:50]) + "..."
}
}
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\n", a.Name, model, desc)
}
Expand Down
Loading
Loading