Skip to content

Commit 39757f5

Browse files
authored
Merge pull request #72 from m0n0x41d/dev
Dev
2 parents 4969ecb + bb64ec8 commit 39757f5

416 files changed

Lines changed: 95764 additions & 1600 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/release.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252
- { runner: ubuntu-latest, goos: linux, goarch: amd64 }
5353
- { runner: ubuntu-24.04-arm, goos: linux, goarch: arm64 }
5454
- { runner: macos-latest, goos: darwin, goarch: arm64 }
55-
- { runner: macos-latest, goos: darwin, goarch: amd64 }
55+
- { runner: macos-13, goos: darwin, goarch: amd64 }
5656
steps:
5757
- uses: actions/checkout@v6
5858
with:
@@ -64,6 +64,10 @@ jobs:
6464
- uses: actions/setup-node@v6
6565
with:
6666
node-version: '24'
67+
- uses: erlef/setup-beam@v1
68+
with:
69+
otp-version: '27'
70+
elixir-version: '1.18.3'
6771

6872
- name: Prepare desktop embed
6973
run: |
@@ -94,12 +98,20 @@ jobs:
9498
-X github.com/m0n0x41d/haft/internal/cli.BuildDate=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
9599
-o haft ./cmd/haft/
96100
101+
- name: Build Open-Sleigh runtime
102+
run: |
103+
cd open-sleigh
104+
MIX_ENV=prod mix deps.get --only prod
105+
MIX_ENV=prod mix release --overwrite
106+
97107
- name: Package
98108
run: |
99109
mkdir -p _dist
100110
cp tui/dist/tui.mjs .
111+
mkdir -p runtimes/open-sleigh
112+
cp -R open-sleigh/_build/prod/rel/open_sleigh/. runtimes/open-sleigh/
101113
tar czf _dist/haft-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz \
102-
haft tui.mjs README.md LICENSE CHANGELOG.md
114+
haft tui.mjs runtimes README.md LICENSE CHANGELOG.md
103115
104116
- uses: actions/upload-artifact@v4
105117
with:

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ coverage.out
2727
.crush/
2828
.cursor/
2929
.zenflow/
30+
.agents/
31+
.opencode/
32+
opencode.json
3033
desktop/desktop
3134
.zenflow/
3235
.zenflow/**

.golangci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ linters:
2020
settings:
2121
misspell:
2222
locale: US
23+
ignore-rules:
24+
# "cancelled" is the canonical wire-format spelling for the
25+
# WorkCommission state and is persisted in artifacts; switching
26+
# to US "canceled" would be a backwards-incompat data break.
27+
- cancelled
2328
gocritic:
2429
disabled-checks:
2530
- ifElseChain

CHANGELOG.md

Lines changed: 74 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 214 additions & 28 deletions
Large diffs are not rendered by default.

Taskfile.yaml

Lines changed: 151 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ vars:
66
TUI_DIR: tui
77
TUI_BUNDLE: tui/dist/tui.mjs
88
TUI_INSTALL_DIR: ~/.haft/tui
9+
OPEN_SLEIGH_RELEASE_DIR: open-sleigh/_build/prod/rel/open_sleigh
10+
OPEN_SLEIGH_INSTALL_DIR: ~/.haft/runtimes/open-sleigh/current
911
FPF_SPEC: data/FPF/FPF-Spec.md
1012
FPF_DB: internal/cli/fpf.db
1113
DESKTOP_APP_NAME: Haft
14+
DESKTOP_DEV_CLI: desktop-tauri/target/debug/haft
15+
DESKTOP_RELEASE_CLI: desktop-tauri/target/release/haft
1216

1317
tasks:
1418
default:
@@ -70,8 +74,8 @@ tasks:
7074
- '{{.BIN_NAME}}'
7175

7276
install:
73-
desc: Build and install haft (CLI + TUI) locally
74-
deps: [tui, fpf-refresh]
77+
desc: Build and install haft (CLI + TUI + Open-Sleigh runtime) locally
78+
deps: [tui, fpf-refresh, open-sleigh:install-runtime]
7579
cmds:
7680
# Remove any stale `haft` in GOBIN so PATH picks up BIN_DIR/haft,
7781
# not a leftover `go install`'d binary from an older build.
@@ -81,6 +85,7 @@ tasks:
8185
- cp {{.TUI_BUNDLE}} {{.TUI_INSTALL_DIR}}/bundle.mjs
8286
- echo "Installed {{.BIN_DIR}}/{{.BIN_NAME}}"
8387
- echo "Installed {{.TUI_INSTALL_DIR}}/bundle.mjs"
88+
- echo "Installed {{.OPEN_SLEIGH_INSTALL_DIR}}"
8489
- echo "Desktop — run task desktop:install separately (requires Rust toolchain)"
8590

8691
dev:
@@ -96,16 +101,46 @@ tasks:
96101

97102
desktop:
98103
desc: Run Haft desktop app (Tauri dev with hot reload)
104+
deps: [desktop:cli]
99105
dir: desktop-tauri
100106
cmds:
101107
- cargo tauri dev
102108

109+
desktop:cli:
110+
desc: Build the local Haft CLI used by Tauri desktop RPC in dev
111+
cmds:
112+
- mkdir -p desktop-tauri/target/debug
113+
- go build -o {{.DESKTOP_DEV_CLI}} -trimpath ./cmd/haft/
114+
sources:
115+
- cmd/**/*.go
116+
- db/**/*.go
117+
- internal/**/*.go
118+
- go.mod
119+
- go.sum
120+
generates:
121+
- '{{.DESKTOP_DEV_CLI}}'
122+
103123
desktop:build:
104124
desc: Build Haft desktop app (Tauri production bundle)
125+
deps: [desktop:cli:release]
105126
dir: desktop-tauri
106127
cmds:
107128
- cargo tauri build
108129

130+
desktop:cli:release:
131+
desc: Build the Haft CLI next to the release desktop binary
132+
cmds:
133+
- mkdir -p desktop-tauri/target/release
134+
- go build -o {{.DESKTOP_RELEASE_CLI}} -trimpath ./cmd/haft/
135+
sources:
136+
- cmd/**/*.go
137+
- db/**/*.go
138+
- internal/**/*.go
139+
- go.mod
140+
- go.sum
141+
generates:
142+
- '{{.DESKTOP_RELEASE_CLI}}'
143+
109144
desktop:install:
110145
desc: Build and install Haft desktop app locally
111146
deps: [desktop:build]
@@ -164,19 +199,133 @@ tasks:
164199
Linux) "$HOME/.haft/bin/haft-desktop" & ;;
165200
esac
166201
202+
repomix:
203+
desc: Pack all code and specs into a timestamped XML review bundle
204+
vars:
205+
TIMESTAMP:
206+
sh: date -u +%Y%m%dT%H%M%SZ
207+
cmds:
208+
- mkdir -p .context
209+
- >-
210+
repomix
211+
--include "cmd/**,internal/**,logger/**,tui/**,desktop/**,desktop-tauri/**,open-sleigh/**,spec/**,skills/**,scripts/**,assurance/**,db/**,*.md,*.go,go.mod,go.sum,Taskfile.yaml,*.sql,*.yaml,*.yml,*.json,*.toml"
212+
--ignore ".git,.context,.haft,.task,.cache,.claude,.codex,.crush,.cursor,.playwright-mcp,.zenflow,.zenflow-attachments,data/FPF,desktop-tauri/target,desktop/frontend/node_modules,tui/node_modules,open-sleigh/_build,open-sleigh/deps,node_modules,dist,build,tmp,coverage.out,internal/cli/fpf.db,*.db,*.sqlite,*.log,haft"
213+
--output ".context/{{.TIMESTAMP}}_repomix.xml"
214+
--parsable-style
215+
--include-diffs
216+
217+
open-sleigh:doctor:
218+
desc: Check the local Open-Sleigh commission harness prerequisites
219+
dir: open-sleigh
220+
cmds:
221+
- REPO_URL="${REPO_URL:-/Users/ivanzakutnii/Repos/projects/haft}" mix open_sleigh.doctor --path sleigh.commission.md.example --mock-haft
222+
223+
open-sleigh:doctor-haft:
224+
desc: Check the Haft commission-source harness prerequisites
225+
dir: open-sleigh
226+
cmds:
227+
- REPO_URL="${REPO_URL:-/Users/ivanzakutnii/Repos/projects/haft}" mix open_sleigh.doctor --path sleigh.haft.md.example --mock-haft
228+
229+
open-sleigh:smoke:
230+
desc: Run one deterministic local Open-Sleigh commission smoke
231+
dir: open-sleigh
232+
cmds:
233+
- REPO_URL="${REPO_URL:-/Users/ivanzakutnii/Repos/projects/haft}" mix open_sleigh.start --path sleigh.commission.md.example --mock --once --once-timeout-ms=5000
234+
235+
open-sleigh:smoke-haft:
236+
desc: Run one deterministic Haft commission-source smoke
237+
dir: open-sleigh
238+
cmds:
239+
- REPO_URL="${REPO_URL:-/Users/ivanzakutnii/Repos/projects/haft}" mix open_sleigh.start --path sleigh.haft.md.example --mock --once --once-timeout-ms=5000
240+
241+
open-sleigh:smoke-real-haft:
242+
desc: Run Open-Sleigh against a real temporary Haft MCP server and WorkCommission
243+
cmds:
244+
- bash scripts/open_sleigh_real_haft_smoke.sh
245+
246+
open-sleigh:smoke-real-haft-dynamic:
247+
desc: Prove long-running Open-Sleigh picks up new Haft WorkCommissions without restart
248+
cmds:
249+
- bash scripts/open_sleigh_real_haft_dynamic_smoke.sh
250+
251+
open-sleigh:smoke-real-haft-from-decision:
252+
desc: Prove Haft can create a WorkCommission from a DecisionRecord and Open-Sleigh consumes it
253+
cmds:
254+
- bash scripts/open_sleigh_real_haft_from_decision_smoke.sh
255+
256+
open-sleigh:smoke-real-haft-batch:
257+
desc: Prove Haft can create a batch of WorkCommissions and Open-Sleigh consumes the queue
258+
cmds:
259+
- bash scripts/open_sleigh_real_haft_batch_smoke.sh
260+
261+
open-sleigh:smoke-real-haft-plan:
262+
desc: Prove Haft can create WorkCommissions from an ImplementationPlan-lite file
263+
cmds:
264+
- bash scripts/open_sleigh_real_haft_plan_smoke.sh
265+
266+
open-sleigh:smoke-harness-command:
267+
desc: Prove one haft harness command can create commissions and run Open-Sleigh
268+
cmds:
269+
- bash scripts/open_sleigh_harness_command_smoke.sh
270+
271+
open-sleigh:release:
272+
desc: Build packaged Open-Sleigh runtime release
273+
dir: open-sleigh
274+
cmds:
275+
- MIX_ENV=prod mix deps.get --only prod
276+
- MIX_ENV=prod mix release --overwrite
277+
278+
open-sleigh:install-runtime:
279+
desc: Install packaged Open-Sleigh runtime under ~/.haft
280+
deps: [open-sleigh:release]
281+
cmds:
282+
- rm -rf {{.OPEN_SLEIGH_INSTALL_DIR}}
283+
- mkdir -p "$(dirname {{.OPEN_SLEIGH_INSTALL_DIR}})"
284+
- cp -R {{.OPEN_SLEIGH_RELEASE_DIR}} {{.OPEN_SLEIGH_INSTALL_DIR}}
285+
286+
open-sleigh:harness:
287+
desc: Run local Open-Sleigh commission harness with real agent and mock Haft/Judge
288+
dir: open-sleigh
289+
cmds:
290+
- REPO_URL="${REPO_URL:-/Users/ivanzakutnii/Repos/projects/haft}" mix open_sleigh.start --path sleigh.commission.md.example --mock-haft --mock-judge
291+
292+
open-sleigh:harness-haft:
293+
desc: Run Haft commission-source harness with real agent and mock Haft/Judge
294+
dir: open-sleigh
295+
cmds:
296+
- REPO_URL="${REPO_URL:-/Users/ivanzakutnii/Repos/projects/haft}" mix open_sleigh.start --path sleigh.haft.md.example --mock-haft --mock-judge
297+
298+
open-sleigh:harness-from-decision:
299+
desc: Create a WorkCommission from DECISION and run the real Haft-backed Open-Sleigh harness
300+
cmds:
301+
- bash scripts/open_sleigh_harness_from_decision.sh "{{.DECISION}}"
302+
303+
open-sleigh:harness-from-decisions:
304+
desc: Create WorkCommissions from DECISIONS and run the real Haft-backed Open-Sleigh harness
305+
cmds:
306+
- DECISIONS="{{.DECISIONS}}" bash scripts/open_sleigh_harness_from_decision.sh
307+
308+
open-sleigh:harness-plan:
309+
desc: Create WorkCommissions from PLAN and run the real Haft-backed Open-Sleigh harness
310+
cmds:
311+
- PLAN="{{.PLAN}}" bash scripts/open_sleigh_harness_from_decision.sh
312+
167313
clean:
168314
desc: Remove local build artifacts
169315
cmds:
170316
- rm -f {{.BIN_NAME}}
171317
- rm -rf tui/dist
318+
- rm -rf open-sleigh/_build
172319

173320
cleanup:
174321
desc: Remove all built binaries and installed files
175322
cmds:
176323
- rm -f {{.BIN_NAME}}
177324
- rm -rf tui/dist
325+
- rm -rf open-sleigh/_build
178326
- rm -f {{.BIN_DIR}}/{{.BIN_NAME}}
179327
- rm -rf {{.TUI_INSTALL_DIR}}
328+
- rm -rf ~/.haft/runtimes/open-sleigh
180329
- rm -rf ~/Applications/{{.DESKTOP_APP_NAME}}.app
181330
- rm -f ~/.haft/bin/haft-desktop
182331
- rm -f ~/.local/share/applications/haft.desktop

data/FPF

db/migrations.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,4 +406,19 @@ var kernelMigrations = []Migration{
406406
"UPDATE desktop_tasks SET raw_output = output_tail WHERE TRIM(COALESCE(raw_output, '')) = '' AND TRIM(COALESCE(output_tail, '')) != ''",
407407
},
408408
},
409+
{
410+
Version: 28,
411+
Description: "Add spec_section_baselines for SpecSection drift detection",
412+
Statements: []string{
413+
`CREATE TABLE IF NOT EXISTS spec_section_baselines (
414+
project_id TEXT NOT NULL,
415+
section_id TEXT NOT NULL,
416+
hash TEXT NOT NULL,
417+
captured_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
418+
approved_by TEXT NOT NULL DEFAULT '',
419+
PRIMARY KEY (project_id, section_id)
420+
)`,
421+
`CREATE INDEX IF NOT EXISTS idx_spec_section_baselines_project ON spec_section_baselines(project_id)`,
422+
},
423+
},
409424
}

0 commit comments

Comments
 (0)