Commit graph

793 commits

Author SHA1 Message Date
Snider
bdbfc5e59e chore: migrate forge.lthn.ai → forge.lthn.io
Update Forgejo domain references in CI pipeline, vanity import
tool, and core-app codex prompt.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-13 19:13:40 +00:00
Charon (snider-linux)
b779c5ece0 Merge pull request 'fix(bugseti): workspace TTL sweeper and configurable limits (#54)' (#157) from fix/54-workspace-ttl-cleanup into new 2026-02-12 20:35:24 +00:00
Charon (snider-linux)
1e0bff0a2e Merge pull request 'fix(security): path traversal in journal logging (#46)' (#156) from fix/issue-46-path-traversal into new 2026-02-12 20:35:22 +00:00
Charon (snider-linux)
e9df62b04e Merge pull request 'fix(bugseti): race condition in QueueService.load() - missing mutex during init' (#155) from fix/51-queue-load-race-condition into new 2026-02-12 20:35:15 +00:00
Charon (snider-linux)
03d7a7dc4e Merge pull request 'fix(security): move Gemini API key from URL to header (#47)' (#154) from fix/gemini-api-key-in-url-47 into new 2026-02-12 20:35:02 +00:00
Claude
6abe90c8cb
fix(bugseti): add background TTL sweeper and configurable workspace limits
The workspace map previously only cleaned up during Capture() calls,
meaning stale entries would accumulate indefinitely if no new captures
occurred. This adds:

- Background sweeper goroutine (Start/Stop lifecycle) that runs every 5
  minutes to evict expired workspaces
- Configurable MaxWorkspaces and WorkspaceTTLMinutes in Config (defaults:
  100 entries, 24h TTL) replacing hardcoded constants
- cleanup() now returns eviction count for observability logging
- Nil-config fallback to safe defaults

Fixes #54

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 20:31:25 +00:00
Claude
b0ef3fb215
fix(security): sanitize path components in journal logging (#46)
Prevent path traversal in Journal.Append() by validating RepoOwner and
RepoName before using them in file paths. Malicious values like
"../../etc/cron.d" could previously write outside the journal baseDir.

Defence layers:
- Reject inputs containing path separators (/ or \)
- Reject ".." and "." traversal components
- Validate against safe character regex ^[a-zA-Z0-9][a-zA-Z0-9._-]*$
- Verify resolved absolute path stays within baseDir

Closes #46
CVSS 6.3 — OWASP A01:2021-Broken Access Control

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 20:30:47 +00:00
Claude
bcb559630e
fix(bugseti): hold mutex during entire QueueService initialization
Move shared state initialization (issues, seen) and the load() call
inside the mutex scope in NewQueueService() to eliminate the race
window where concurrent callers could observe partially initialized
state. Remove the redundant heap.Init before the lock since load()
already calls heap.Init when restoring from disk.

Add documentation to save() and load() noting they must be called
with q.mu held.

Fixes #51

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 20:30:22 +00:00
Claude
bde00e40f4
fix(security): move Gemini API key from URL query params to header (#47)
Pass the API key via x-goog-api-key HTTP header instead of the URL
query parameter to prevent credential leakage in proxy logs, web
server access logs, and monitoring systems.

Resolves: #47 (CVSS 5.3, OWASP A09:2021)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 20:29:09 +00:00
Charon (snider-linux)
45d8b5b7d4 Merge pull request 'feat(agentic): agent allowance system — respect model quotas and budgets' (#151) from feat/agentic-allowance-system into new 2026-02-12 20:07:11 +00:00
Charon (snider-linux)
6702d56edb Merge pull request 'feat(agentic): Forgejo integration bridge — PHP service linking platform to forges' (#150) from feat/agentic-forgejo-bridge into new 2026-02-12 20:06:58 +00:00
Charon (snider-linux)
4bc43939a6 Merge pull request 'feat(agentic): agent trust model — security wall between non-aligned agents' (#149) from feat/agentic-trust-model into new 2026-02-12 20:06:50 +00:00
Charon (snider-linux)
d2dd23697f Merge pull request 'feat(agentic): real-time dashboard — live agent activity view' (#148) from feat/agentic-dashboard into new 2026-02-12 20:03:51 +00:00
Athena
65c138e126 feat(agentic): add agent allowance system for model quotas and budgets
Implements quota enforcement for agents including daily token limits,
daily job limits, concurrent job caps, model allowlists, and global
per-model budgets. Quota recovery returns 50% for failed jobs and
100% for cancelled jobs.

Go: AllowanceService with MemoryStore, AllowanceStore interface, and
25 tests covering all enforcement paths.

Laravel: migration for 5 tables (agent_allowances, quota_usage,
model_quotas, usage_reports, repo_limits), Eloquent models,
AllowanceService, QuotaMiddleware, and REST API routes.

Closes #99

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 20:32:41 +00:00
Athena
740cf115b2 feat(agentic): add Forgejo integration bridge for PHP platform
Add ForgejoClient and ForgejoService to the Laravel app, providing a
clean service layer for all Forgejo REST API operations the orchestrator
needs. Supports multiple instances (forge, dev, qa) with config-driven
auto-routing, token auth, retry with circuit breaker, and pagination.

Covers issues, PRs, repos, branches, user/token management, and orgs.

Closes #98

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 20:16:15 +00:00
Athena
3bfaf37ab1 feat(agentic): add agent trust model with tiered access control
Implements the security wall between non-aligned agents (issue #97).

Adds pkg/trust with:
- Three trust tiers: Full (Tier 3), Verified (Tier 2), Untrusted (Tier 1)
- Agent registry with mutex-protected concurrent access
- Policy engine with capability-based access control
- Repo-scoped permissions for Tier 2 agents
- Default policies matching the spec (rate limits, approval gates, denials)
- 49 tests covering all tiers, capabilities, edge cases, and helpers

Closes #97

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 20:04:35 +00:00
Athena
72529a8281 feat(agentic): add real-time dashboard with Livewire components (#96)
Add a live agent activity dashboard to the Core App Laravel frontend.
Provides real-time visibility into agent fleet status, job queue,
activity feed, metrics, and human-in-the-loop actions — replacing
SSH + tail -f as the operator interface.

Dashboard panels:
- Agent Fleet: grid of agent cards with heartbeat, status, model info
- Job Queue: filterable table with cancel/retry actions
- Live Activity Feed: real-time stream with agent/type filters
- Metrics: stat cards, budget gauge, cost breakdown, throughput chart
- Human Actions: inline question answering, review gate approval

Tech: Laravel Blade + Livewire 4 + Tailwind CSS + Alpine.js + ApexCharts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 19:56:17 +00:00
7ce8ca717c Merge pull request 'fix(bugseti): add test coverage for SubmitService PR workflow' (#76) from Athena/core:fix/bugseti-submit-tests into new 2026-02-10 15:43:41 +00:00
37b04695d1 Merge pull request 'fix(bugseti): sanitize shell metacharacters in seeder env vars' (#71) from Athena/core:fix/bugseti-sanitize-shell-metacharacters into new 2026-02-10 15:43:37 +00:00
9fe4d5f063 Merge pull request 'fix(bugseti): update config file permissions to 0600' (#57) from fix/bugseti-config-perms into new 2026-02-10 15:43:19 +00:00
16a5ba70ef Merge pull request 'fix(bugseti): add mutex protection to seeder concurrent access' (#75) from Athena/core:fix/issue-63-seeder-mutex into new 2026-02-10 15:42:58 +00:00
88e5560086 Merge pull request 'fix(bugseti): handle silent git fetch failure in submit.go' (#74) from Athena/core:fix/bugseti-git-fetch-error-62 into new 2026-02-10 15:42:54 +00:00
b57e30ea06 Merge pull request 'fix(bugseti): add gh CLI availability check with helpful error' (#73) from Athena/core:fix/bugseti-gh-cli-check into new 2026-02-10 15:42:51 +00:00
8d3f9a73ee Merge pull request 'fix(bugseti): add comprehensive tests for FetcherService' (#72) from Athena/core:fix/bugseti-fetcher-tests into new 2026-02-10 15:42:48 +00:00
Athena
c4d59f9850 fix(bugseti): add test coverage for SubmitService PR workflow (#64)
Extract buildForkURL helper for testable fork URL construction and add
19 tests covering Submit validation, HTTPS/SSH fork URLs, PR body
generation, and ensureFork error handling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 15:42:45 +00:00
9f9e8cc044 Merge pull request 'fix(bugseti): add TTL cleanup and max size cap to workspace map' (#58) from fix/bugseti-workspace-ttl-55 into new 2026-02-10 15:42:44 +00:00
74e2614e41 Merge pull request 'fix(bugseti): acquire mutex in NewQueueService before load()' (#56) from fix/bugseti-queue-race-52 into new 2026-02-10 15:42:40 +00:00
Athena
149dc3de14 fix(bugseti): add mutex protection to seeder concurrent access
Add sync.Mutex to SeederService to protect shared state during
concurrent SeedIssue, GetWorkspaceDir, and CleanupWorkspace calls.
Extract getWorkspaceDir as lock-free helper to avoid double-locking.

Closes #63

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 15:37:11 +00:00
Athena
9319015219 fix(bugseti): handle silent git fetch failure in submit.go
Capture and log the error from `git fetch origin` in createBranch()
instead of silently ignoring it. Warns the user they may be proceeding
with stale data if the fetch fails.

Fixes #62

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 15:30:50 +00:00
Athena
25985af53c fix(bugseti): add gh CLI availability check with helpful error
Adds a startup check that verifies gh is in PATH and authenticated
before initializing services. Provides clear install/auth instructions
on failure instead of cryptic exec errors at runtime.

Closes #61

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 15:27:53 +00:00
Athena
796ec563ed fix(bugseti): add comprehensive tests for FetcherService (#60)
Add fetcher_test.go covering: service creation, start/pause lifecycle,
calculatePriority scoring for all label types, label query construction
with custom and default labels, gh CLI JSON parsing for both list and
single-issue endpoints, channel backpressure when issuesCh is full,
fetchAll with no repos configured, and missing binary error handling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 15:23:35 +00:00
Athena
e83e416854 fix(bugseti): sanitize shell metacharacters in seeder env vars
SanitizeEnv() only removed control characters but not shell
metacharacters. A malicious repo name could execute arbitrary commands
via environment variable injection (e.g. backticks, $(), semicolons).

Add stripShellMeta() to strip backticks, dollar signs, semicolons,
pipes, ampersands, and other shell-significant characters from values
passed to the bash seed script environment.

Fixes #59

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 15:18:36 +00:00
Claude (M3 Studio)
3fc04f809b fix(bugseti): add TTL cleanup and max size cap to workspace map (#55)
The workspaces map in WorkspaceService grew unboundedly. Add cleanup()
that evicts entries older than 24h and enforces a 100-entry cap by
removing oldest entries first. Called on each Capture().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 11:25:00 +00:00
Claude (M3 Studio)
169428a945 fix(bugseti): update config file permissions to 0600
This commit updates the file permissions for the BugSETI configuration file from 0644 to 0600, ensuring owner-only access. This addresses the security concern where the GitHub token stored in the config file was world-readable.

Fixes #53
2026-02-10 11:15:52 +00:00
Claude (M3 Studio)
440086b83a fix(bugseti): acquire mutex in NewQueueService before load()
q.load() accesses shared state (issues, seen, current) without holding
the mutex, creating a race condition. Wrap the call with q.mu.Lock().

Fixes #52

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 11:12:46 +00:00
5e953944f5 Merge pull request 'feat(agentci): Clotho orchestrator, rate limiting, and security hardening' (#49) from feat/agentci-packaging into new 2026-02-10 03:08:36 +00:00
Claude
b00e0df89c
fix(agentci): resolve agents by Forgejo username, not config key
Adds FindByForgejoUser() to Spinner so dispatch matches issues
assigned to Forgejo users (Virgil, Claude, Charon) even when the
agent config key differs (e.g. Hypnos → forgejo_user: Claude).

Searches config key first (direct match), then ForgejoUser field.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 03:08:17 +00:00
Claude
3ccb67bddd
feat(agentci): rate limiting and native Go dispatch runner
Adds pkg/ratelimit for Gemini API rate limiting with sliding window
(RPM/TPM/RPD), persistent state, and token counting. Replaces the
bash agent-runner.sh with a native Go implementation under
`core ai dispatch {run,watch,status}` for local queue processing.

Rate limiting:
- Per-model quotas (RPM, TPM, RPD) with 1-minute sliding window
- WaitForCapacity blocks until capacity available or context cancelled
- Persistent state in ~/.core/ratelimits.yaml
- Default quotas for Gemini 3 Pro/Flash, 2.5 Pro, 2.0 Flash/Lite
- CountTokens helper calls Google tokenizer API
- CLI: core ai ratelimits {show,reset,count,config,check}

Dispatch runner:
- core ai dispatch run — process single ticket from queue
- core ai dispatch watch — daemon mode with configurable interval
- core ai dispatch status — show queue/active/done counts
- Supports claude/codex/gemini runners with rate-limited Gemini
- File-based locking with stale PID detection
- Completion handler updates issue labels on success/failure

Closes #42

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 03:08:16 +00:00
Claude
d92762ecdc
feat(agentci): Clotho orchestrator and security hardening
Adds the Clotho dual-run verification system and hardens the entire
agent dispatch pipeline against command injection, token exposure,
and SSH MitM attacks. Breaks the agentci→handlers circular dependency.

Security:
- SanitizePath (regex whitelist + filepath.Base) for all dispatch inputs
- EscapeShellArg for shell argument safety
- SecureSSHCommand (StrictHostKeyChecking=yes, BatchMode=yes)
- ForgeToken removed from ticket JSON, transferred via .env with 0600
- ssh-keyscan on agent add populates known_hosts before first connection

Clotho:
- Spinner orchestrator determines Standard vs Dual execution mode
- Config-driven via ClothoConfig (strategy, validation_threshold)
- Agent runner supports claude/codex/gemini backends with dual-run
- Divergence detection compares thread outputs via git diff

API:
- LoadActiveAgents() returns map[string]AgentConfig (no handlers import)
- LoadClothoConfig() reads clotho section from config
- Forge helpers: AssignIssue, EnsureLabel, AddIssueLabels

32 tests pass (19 agentci + 13 dispatch).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 03:08:16 +00:00
Claude
4c8be587bf
feat(agentci): add tests and Gemini 3 tiered batch pipeline
- Add 15 tests for pkg/agentci/config.go (load, save, remove, list, round-trip)
- Extend dispatch_test.go from 4 to 12 tests (match edge cases, ticket JSON
  serialization, model/runner variants, execute error paths)
- Add gemini-batch-runner.sh: rate-limit-aware tiered pipeline using
  Flash Lite → Gemini 3 Flash → Gemini 3 Pro with 80% TPM safety margin
- Generate docs/pkg-batch{1-6}-analysis.md covering all 33 packages
  using ~893K tokens total (vs 5.54M single-shot), zero rate limit hits

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 03:07:52 +00:00
Virgil
00dfd27072 Merge pull request 'feat(agentci): package dispatch for multi-agent deployment' (#39) from feat/agentci-packaging into new 2026-02-09 11:25:48 +00:00
Snider
0a3c0204d1 fix(agentci): use log.E() error pattern, add Charm SSH TODOs
Replace fmt.Errorf() with structured log.E() errors in agentci, forge,
jobrunner packages. Update PipelineSignal comment to reflect dispatch
fields. Add TODO markers for charmbracelet/ssh migration across all
exec ssh call sites.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-09 11:15:11 +00:00
Claude
95ef7ced6b
feat(agentci): add gemini runner backend
Support gemini -p -y (non-interactive yolo mode) alongside claude
and codex runners. Three AI backends for different cost profiles.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 11:14:17 +00:00
Claude
947fa38bcd
fix(agentci): correct codex exec flags for v0.98
Use `codex exec --full-auto` instead of `--approval-mode full-auto`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 11:02:41 +00:00
Claude
67dc130424
feat(agentci): add model/runner fields for multi-backend support
Tickets now carry model (sonnet/haiku/opus) and runner (claude/codex)
fields. agent-runner.sh dispatches to the right backend. Defaults to
claude with sonnet model for cost efficiency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 10:58:46 +00:00
Virgil
71cde24842 Merge pull request 'fix(tray): replace placeholder icons with actual bug and diamond icons' (#40) from fix/tray-icons into new 2026-02-09 10:40:09 +00:00
Snider
3b155ae7bf fix(tray): replace placeholder icons with actual bug and diamond icons
BugSETI: bug with antennae and legs (black template, white dark, green app)
Core IDE: diamond shape (black template, white dark, blue app)

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-09 10:39:50 +00:00
Claude
6ae525d54f
feat(agentci): package dispatch system for multi-agent deployment
Config-driven agent targets replace hardcoded map so new agents
can be added via CLI instead of recompiling. Includes setup script
for bootstrapping agent machines and CLI commands for management.

- Add pkg/agentci with config types and CRUD (LoadAgents, SaveAgent, etc.)
- Add CLI: core ai agent {add,list,status,logs,setup,remove}
- Add scripts/agent-setup.sh (SSH bootstrap: dirs, cron, prereq check)
- Headless loads agents from ~/.core/config.yaml
- Dispatch ticket includes forgejo_user for dynamic clone URLs
- agent-runner.sh reads username from ticket JSON, not hardcoded

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 10:36:23 +00:00
Virgil
ab7e7d7b3c Merge pull request 'feat(bugseti): wire BugSETI into root build system and ship v0.1.0' (#38) from feat/bugseti-launch into new 2026-02-09 10:28:37 +00:00
Snider
ff934fa0d3 Merge branch 'new' of https://forge.lthn.ai/host-uk/core into new 2026-02-09 10:24:27 +00:00