Conversation
Move drift instruction from post-list advice to pre-list guard line. Agents read tool output more attentively than skill preambles — guard at point of action prevents "summarize as expected" shortcut. Tool output now shows: ⚠ REQUIRED: read git diff for each modified file before taking action Classify: cosmetic | material | incidental SKILL.md adds explicit post-scan protocol: read diffs, classify, present to user. Skipping diff review = FPF violation.
"likely implemented" / "not yet implemented" replaced with "git activity detected / not detected after decision date". Tool outputs observable facts; agent performs all interpretation.
SelectProblems and FindActiveProblem applied status filter in Go after SQL LIMIT, so deprecated rows could push active ones out of the result window. Added Store.ListActiveByKind with SQL-level status='active' filter.
Reproducing test for reported issue where root modules show as "blind" despite having decisions with affected_files. Test passes — root cause still under investigation, awaiting reporter DB state.
Push trigger now only fires on main (post-merge). PR branches use pull_request trigger exclusively, preventing double CI runs.
…TS5 improvements Kernel layering (dec-20260327-001): - Extract ArtifactStore interface (26 methods) in iface.go - All 35 domain functions accept interface instead of concrete *Store - Compile-time check: var _ ArtifactStore = (*Store)(nil) - Extract pure Build* functions for Problem, Note, Decision, Explore - Move raw SQL from decision.go to Store.SupersedeEvidenceByType() - DecideContext, ExploreContext structs for pre-fetched data - extractSection() helper replaces repeated markdown parsing FTS5 search quality (dec-20260326-002 through dec-20260326-006): - AND-default with OR fallback for multi-term queries (store.go, index.go) - bm25 column weighting: title=10, kind=5, keywords=3, content=1 - Stop-word filter replacing len>2 heuristic (preserves Go, CI, DB) - FPF spec search as MCP action: quint_query(action="fpf") All 12 test suites pass. Zero MCP contract changes.
…dules - BuildComparisonBody: pure comparison table + Pareto front + warnings - BuildPortfolioArtifact: pure portfolio construction with ExploreContext - ValidateExploreInput, CheckVariantDiversity: extracted as pure functions - BuildWaiverSection, BuildSupersedeSection, BuildDeprecateSection: pure body sections - BuildRefreshReportArtifact: pure report construction - extractSection: reusable pure markdown section extractor All 7 domain modules now have pure Build* functions. Orchestrator functions are thin: fetch → pure build → persist.
…nternal/present New package internal/present with pure formatting functions: - NavStrip, NoteResponse, NoteRejection - ProblemResponse, SolutionResponse, DecisionResponse - BaselineResponse, DriftResponse, ScanResponse - RefreshActionResponse, ReconcileResponse, MissingProblemResponse serve.go updated to use present.* instead of artifact.Format*. FormatProblemsListResponse stays in artifact (reads store — not pure). Original functions preserved in artifact for test compatibility. Step 3 of kernel layering (dec-20260327-001) complete.
… into domain - ParseKind, ParseStatus, ParseMode with IsValid() and ValidX maps - BuildProblemArtifact and Decide reject invalid mode strings - Empty mode still defaults to standard (backward compatible)
…onical source - Delete 11 Format* functions from artifact (note, decision, solution, refresh, problem, nav) - FormatProblemsListResponse stays in artifact (reads store — not pure) - BuildNavStrip removed — serve.go calls present.NavStrip(ComputeNavState()) directly - Format* tests moved to internal/present/format_test.go - Contract tests in nav_test.go rewritten to assert NavState directly artifact package now has zero presentation logic in serve.go callers. present → artifact is one-way. No circular dependency.
ReopenDecision pure extraction:
- BuildLineageNotes: pure lineage construction from pre-fetched sources
- LineageSource, LinkedProblem types for pre-fetch context
FormatProblemsListResponse split:
- ProblemListItem + EnrichProblemsForList: effect boundary
- present.ProblemsListResponse: pure formatting
- Zero Format* remain in artifact
serve.go handler split:
- dispatchTool, logToolEntry, applyCrossProjectRecall,
applyCrossProjectIndex, applyRefreshReminder extracted
- makeV5Handler is now ~15 lines
Modernization: interface{} → any (Go 1.18+)
Structured fields (migration 16): - New structured_data TEXT column on artifacts table - ProblemFields, DecisionFields types for typed JSON storage - BuildProblemArtifact and BuildDecisionArtifact populate structured_data - Canonical structured JSON alongside markdown body Boundary validation: - ParseKind/ParseStatus/ParseMode enforced at all user-facing boundaries - query.go, parser.go, solution.go: validated at entry points Architecture documentation: - ARCHITECTURE.md: full layer hierarchy with compilation chain - Every layer specifies: concepts, functions, inexpressible states, deps
DB read validation (was Critical): - store.go Get() and scanArtifacts() now use ParseKind/ParseStatus/ParseMode instead of raw Kind(string) casts, with graceful fallback for older data StructuredData read-side (was Critical — write-only dead code): - UnmarshalProblemFields and UnmarshalDecisionFields on Artifact type - BuildDecisionArtifact reads ProblemFields from structured_data when available - Falls back to markdown extractSection() for older artifacts without it - DecideContext gains ProblemStructured field, wired in Decide orchestrator Type safety hardening: - ValidKinds/ValidStatuses/ValidModes unexported (prevent external mutation) Remaining known violations (not fixed in this commit): - query.go presentation logic in artifact package (needs larger refactor) - store.DB() skip-level access in serve.go (needs interface extension) - writer.go renderArtifact in artifact package (needs present/ move)
…ArtifactFile Query layer separation: - FetchSearchResults, FetchStatusData, FetchListData, FetchRelatedArtifacts return raw data (artifact package, no formatting) - SearchResponse, StatusResponse, ListResponse, RelatedResponse pure formatters (present package, no store access) - StatusData, ListData types for pre-fetched dashboard data - serve.go callers updated: fetch → format File serialization: - renderArtifact → RenderArtifactFile (exported, documented as pure) - Stays in artifact due to Go import cycle (present → artifact) - Comment documents the constraint and future fix path store.DB() audit: - Confirmed: zero DB() calls in domain layer (internal/artifact/) - All DB() calls contained in handler layer (cmd/serve.go) - Used for cross-concern queries (codebase scanner, audit log, project index)
Complete standalone agent implementation (quint-code agent command). Same kernel as MCP server — one kernel, two transports. Lemniscate: - 5-phase FPF cycle: framer, explorer, decider, worker, measure - Depth × Interaction orthogonal controls - Auto-enter framer (PhaseReady as resting state) - FPF-accurate phase prompts (ADI cycle references) - Per-phase tool gating with budgets - bash denied to framer/explorer per FPF spec Subagents: - Blocking spawn_agent tool - Explore/title/compact subagent definitions - Collapsed TUI with peek (ctrl+o to expand) Tree-sitter: - Symbol extraction for 7 languages (Go, Python, JS/TS, Rust, C/C++) - Repo map injected into system prompt - Symbol-level baseline hashing for drift detection - affected_symbols DB table Infrastructure: - Shared db.Migrate() runner (replaces if-else chain) - Agent session/message tables - 3-stage context compaction pipeline - Parallel tool execution (goroutines + WaitGroup) - OpenAI Responses API with Codex auth TUI: - BubbleTea v2 with hexagon tool icons - Colored diffs, status verbs, friendly tool names - Glider animation, session picker, permission dialogs
Replace bubbles/v2 viewport with custom ChatList component that supports mouse text selection, eliminating the tmux mouse-capture vs text-selection conflict. Architecture (4 layers): - L1 selection.go: pure geometry — coords, ranges, word/line boundaries, ANSI-aware highlight via ultraviolet ScreenBuffer - L2 chatitem.go: domain items with highlight state — each message, tool call, and transient block is an independently selectable unit - L3 chatlist.go: scrollable item list with mouse state machine — hit-testing, drag selection, double/triple click, auto-scroll - Shell clipboard.go: OSC 52 + native clipboard (atatto/clipboard) Selection flow: mouseDown → drag (highlight via reverse-video) → mouseUp → auto-copy to clipboard. New deps: ultraviolet (cell-level ANSI rendering), atotto/clipboard.
Command palette: - Overlay appears when typing "/" in input, filters as you type - j/k or arrow keys for navigation, Tab to autocomplete, Enter to execute - Renders as bordered box over bottom of chat area (no layout shift) - Registry of 16 slash commands with descriptions Performance: - View() renders only visible items (skip off-screen Render() calls) - Cached ScreenBuffer per item — ANSI parsed once, drag only flips attrs - Drag debounce at 16ms (60fps cap) - Textarea keystroke no longer triggers full item rebuild - resizeComponents() skips refreshChat() when size unchanged Other: - Ctrl+S prefix mode: Ctrl+S then i copies session ID to clipboard - Inline notification in status bar (no layout-shifting banner) - resolvedRange() handles -1 sentinel for cross-item highlight
- ToolExecutor.Execute() returns (ToolResult, error) with optional ArtifactMeta (kind, ref, operation) for artifact-producing tools - Cycle entity (reasoning_cycles table) tracks prob→sol→dec refs - Coordinator binds artifact refs from typed Meta, no string parsing - Adopt action on quint_problem for cross-session problem continuity - Phase transitions derived from cycle state, not signal detection - Removed V3 signal→NavState transition gate - closeCycle/reframeCycle for cycle lifecycle completion - History sanitization for interrupted sessions - Forward-only transitions prevent backward phase loops
- Cycle pure functions: DerivePhaseFromCycle, BindArtifact, PhaseAfter, CompleteCycle, AbandonCycle, AdoptCycle, PhaseSpec mapping table - CycleStore interface + SQLite implementation (migrations 6-7) - Session.ActiveCycleID for cycle-session binding - Unified agent prompts: explorer requires characterize step, decider requires compare step, framer supports adopt - All phases mandatory (no tactical skip per FPF B.5.1) - ForceCompact for /compact command with persistent history cleanup - ModelContextWindow updated for gpt-5.4 (1.05M)
- 4 animation patterns: glider, orbit, converge, pulse (state-driven) - Custom markdown renderer replaces glamour (fixes Unicode text garbling) - Cycle pipeline in status bar: Working on: prob-008 → sol-004 - Phase transition overlay (y/n) for symbiotic mode approval gates - Ctrl+C double-tap quit confirmation - Session resume restores cycle state from DB - Verb randomization seeded by session ID - Removed /next slash command, Ctrl+T depth toggle - Fixed /compact infinite recursion crash - Fixed slash command pass-through recursion (/status etc.)
- q-char.md: characterize is inline reasoning, not persisted artifact - q-decide.md: remove fields not in haft tool schema (why_not_others, pre_conditions, evidence_requirements, rollback, refresh_triggers) - q-reason SKILL.md: sync depth calibration table with runtime behavior
Architecture: - Replace 5-phase pipeline with single react loop (coordinator rewrite) - One unified agent prompt replaces 5 phase-specific prompts - FPF enforced by tool guardrails (CanExplore/CanDecide/CanMeasure) - Remove PhaseDef, PhaseByID, FilterToolsForPhase, phase transitions - Decision-aware context injection on governed file edits - Drift detection at session start Tools: - Ripgrep backend for grep/glob (10-100x faster, .gitignore aware) - Rich grep schema: output_mode, context lines, multiline, type filter - Glob sorted by mtime (newest first) - Read-before-edit tracking in registry - Flexible edit matching (fuzzy fallback on exact miss) - FPF guardrails on quint tools (cycle state precondition checks) TUI: - Paste-as-attachment for large text (>1000 chars or >10 newlines) - Message queueing during streaming (type while agent works) - Glamour rendering with clean StyleConfig (fixes mixed-lang garbling) - Rune-safe truncation (fixes byte-slicing on Cyrillic text) - Empty sessions hidden from resume picker - Ctrl+C double-tap quit confirmation - Input stays focused during streaming Tests: - 8 grep/glob parity tests (ripgrep vs fallback)
FPF Lemniscate: - R_eff auto-tracking from agent actions (tests, lint, file review) - Evidence chain computed as min(scores) with CL penalties - Cycle closure on measure verdict (complete/abandon/reframe) - Predictions field on quint_decision(decide) - Outer cycle trigger (suggest reframe after completion) - Characterize as real action (wired to kernel CharacterizeProblem) - Solution similarity lookup (search past portfolios) - R_eff display in TUI status bar (green/dim/red by threshold) Agent Prompt: - Collaborative workflow: stop after frame and explore, let user review - User selects variant BEFORE decide (Transformer Mandate A.12) - ADI cycle can loop: explore → feedback → re-explore → compare → iterate - Slash commands reframed as course correction, not driving New Tools: - multiedit: batch edits, validate all before apply, reverse order - fetch: HTTP GET with html-to-markdown conversion - @ file mentions with picker overlay Infrastructure: - Subagent read-only enforcement at execution time - Repo map lazy refresh with mtime sort and symbol kinds - Evidence auto-tracking types (EvidenceChain, EvidenceItem, ComputeREff)
Complete rewrite of the CLI agent with FPF reasoning discipline. Agent & Architecture: - Single react loop with tool guardrails (no phase machine) - Unified system prompt: SWE discipline + FPF distillate + collaborative workflow - Transformer Mandate enforced via message history check - Evidence split: observations (auto-detected) vs explicit evidence (R_eff) - R_eff threshold check at cycle closure - Autonomous mode indicator injected into LLM context - Reframe loop on failed measurement (NewCycleFromLineage) Providers: - Anthropic Messages API provider (streaming, tool calls, extended thinking) - Provider factory: auto-routes by model name (openai/anthropic) - Model registry (catwalk pattern): remote sync + embedded fallback - Multi-provider config in ~/.haft/config.yaml CLI: - Full rename: quint-code → haft (module, binary, tools, dirs, env vars) - Go module at repo root (SoTA layout: cmd/haft/main.go + internal/) - haft (bare) = launch agent, haft setup = interactive config - Slash commands renamed /q-* → /h-* with rich FPF steering prompts - OAuth device flow for ChatGPT Plus/Pro in setup TUI - Migration: ~/.quint-code/ → ~/.haft/, .quint/ → .haft/, quint.db → haft.db TUI: - Permission dialog: 3 choices (allow/allow all/deny) + tool description - Expandable tool output (press e) and thinking box (press t) - Persistent error boxes (Esc to dismiss) - Ctrl+M model switch overlay with inline auth - Compact user messages (CC-style background highlight) - Slash commands inject hidden steering prompts (display ≠ LLM text) - Dead code cleanup: removed phase machine remnants LSP: - JSON-RPC 2.0 client with lazy server startup - 36 language servers (gopls, pyright, rust-analyzer, clangd, ...) - Tools: lsp_diagnostics, lsp_references, lsp_restart Overseer: - Tree-sitter symbol-level drift detection - Alert clearing when issues resolved - "stale" label (was misleadingly "expiring") - Dedup fix in ScanStale FPF Compliance: - DepthTactical removed (all phases mandatory per B.5.2) - Nav strip no longer suggests skipping explore - Characterization docs fixed (tracked, not inline) - Prompt enforces all-phases, 3+ variants, Pareto front CI/CD: - Workflows updated for repo-root Go module - Goreleaser builds from cmd/haft/ - Taskfile simplified (no src/mcp/ indirection)
Agent state (decisions, problems, notes) is managed through MCP tools at runtime, not version-controlled. Remove from index and add to .gitignore.
Streaming refactor: coordinator writes assistant messages to store during streaming and sends snapshots via AssistantMessageUpdateMsg. TUI upserts chat items by message ID instead of rebuilding from scratch — eliminates flicker and preserves scroll position. Permission dialog: new modal overlay (PermDialog) with diff view for edit/write tools, replacing the old inline permission box. Diff renderer (diffview.go) uses go-udiff for unified diffs. Loop detection: three-level escalation (green/yellow/red). Guardrail errors excluded from counting — the agent learning from rejections is not a loop. Yellow injects a warning, red hard-stops. Provider: handle reasoning model output items, concise reasoning summary for Codex backend, registry dedup by context window. Other: logger thread safety, empty response detection, autonomous mode prompt rewrite, h-refresh reporting guidelines.
Replace Go BubbleTea TUI with TypeScript/Ink TUI process (two-process architecture: Go backend + Node/Bun TUI via JSON-RPC over pipes). TUI: - Ink-based terminal UI with React components - Permission dialog, question dialog, picker, attachments - Mouse tracking (SGR), scroll, input routing - Async clipboard image paste via Ctrl+V - Terminal echo suppression on Go side (unix termios) New subsystems: - JSON-RPC server/client for backend↔TUI protocol - Task manager (background jobs) - Hook executor (pre/post tool hooks) - LSP integration (diagnostics, references) - Web search, tool search, plan mode, worktree isolation - AskUser tool (blocks until TUI responds) - Doctor command (health checks) Removed: - internal/tui/ (BubbleTea) — 9000+ lines - internal/ui/ (tview dashboard) — 1200+ lines Build: - Taskfile.yaml: esbuild TUI bundle, install to ~/.haft/ - scripts/build.sh for CI
Rewrite input pipeline — Ink is now rendering-only, all input flows through our EventEmitter (keyboard, mouse, paste as separate channels). Eliminates class of bugs where Ink's stdin management interferes. Input: - Edit buffer with cursor movement (home/end, word nav, arrow keys) - Input history (up/down arrow navigation) - Async clipboard image paste via Ctrl+V (osascript, no event loop block) - Bracketed paste support with timeout safety valves - Double Ctrl-C force exit - Stdin resume detection (tmux reattach, laptop wake) Rendering: - Syntax highlighting via highlight.js (lazy-loaded) - AnsiText component for pre-highlighted code blocks - Improved markdown: tables, blockquotes, strikethrough, links - Line-based scroll with entry height measurement Selection: - Mouse drag text selection with clipboard copy - Selection state machine (mouseDown → drag → release → copy) Infrastructure: - InputContext (React context for input EventEmitter) - Debug trace system (HAFT_DEBUG=1 writes to /tmp/haft-debug.log) - JSON-RPC client hardened (reconnect, error handling)
P2-1: Task runner shutdown copies state under lock before use — prevents
concurrent read/write between shutdown and finalizeTask goroutines.
P2-1: CancelTask copies state under lock before persist/emit calls.
P2-2: Registry and config JSON use atomic write (temp file + rename)
to prevent corruption from concurrent calls.
P2-3: ensureFlowController uses mutex instead of non-atomic nil check.
P2-4: Terminal waitLoop reads session status under manager mutex.
P3-1: Agent tasks now use context.WithTimeout from config (TaskTimeoutMinutes).
Prevents zombie processes that hang indefinitely.
P3-2: wireHaftMCPClaude uses atomic write for ~/.claude.json.
Governance scanner now returns empty data (not errors) when: - Controller context is cancelled (shutting down) - Database connection is closed during scan - Context expires between scan steps These are expected during project switching and should not produce error toasts. The new project's scanner starts fresh after switch.
DX-2 complete: Decision detail page shows per-evidence cards with formality level (F0-F3), congruence level (CL0-CL3), verdict badges, freshness indicators, and coverage gaps (claims without evidence). Code review fixes: - S2: Remove dead var _ *sql.DB import guard - S15: Cache tableHasColumn PRAGMA results (was 2 queries per evidence op)
When agent output exceeds 500 lines, show only the last 200 with a "Show full output" button. Prevents WebView freezing on long agent runs (100K+ characters in a single pre element).
Previously, artifact insertion and link insertions were separate operations. If a link insert failed after the artifact committed, the database had an artifact with missing links. Now both are in a single transaction — either all succeed or all roll back.
README: rewritten with product identity (Think → Run → Govern), two primary surfaces (desktop + MCP), pre-alpha warning for TUI and desktop app, cleaner structure. CHANGELOG: added desktop app, knowledge graph, invariant injection, invariant verification, governance alerts, probe-or-commit gate, evidence F/G/R decomposition, auto-run toggle to unreleased section. Removed competitor name from mock data.
New command syncs .haft/ markdown files into local SQLite database. Team workflow: 1. Engineer A creates decision → .haft/decisions/dec-001.md 2. git commit && git push 3. Engineer B: git pull → haft sync → local DB updated 4. Both see same decisions in haft status / haft board Handles: YAML frontmatter with colons in titles (auto-quoting), all artifact types (problems, decisions, portfolios, notes), upsert semantics (create or update based on updated_at timestamp), graceful skip for unchanged artifacts.
- Replace ASCII art banner from quint-code to HAFT with brand green - Add haft sync command to changelog unreleased section - Add 13 bug fixes to changelog (races, null safety, atomic writes, task timeout, output truncation, search race, PRAGMA caching, etc.) - Regenerated Wails bindings for new desktop bindings
Replace naive string-index section removal with prefix-aware removeTomlSections that strips all [mcp_servers.haft*] headers and their bodies before writing the new block. Prevents duplicate-key TOML parse errors on repeated init. Restructure CHANGELOG: promote Unreleased to [6.0.0] with explicit Breaking Changes section (rename, data model, reasoning model, /h-verify replacement).
- haft_problem(action="close") marks a ProblemCard as addressed - StatusAddressed added to valid artifact statuses - Deciding with affected_files now auto-baselines file hashes - MCP and plugin tool schemas updated with close action
- Split Darwin-only syscall code (TIOCGETA/TIOCSETA) into platform files with build tags for both tui.go and agent.go - Exclude desktop/ from CI test and lint (requires frontend build) - Move fpf-routes.json from .context/ to internal/fpf/ (was removed from git by filter-repo, broke FPF golden tests)
install.sh looked for 'quint-code' in release tarballs but goreleaser now builds 'haft'. Updated binary name, ASCII logo, build-from-source path, and all user-facing text.
Owner
Author
|
@codex please :) |
|
To use Codex here, create an environment for this repo. |
Owner
Author
|
@codex okie review plz |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.