This commit is contained in:
40
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
40
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Report something that isn't working as expected
|
||||
title: "[bug] "
|
||||
labels: bug
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
## Describe the bug
|
||||
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
## To reproduce
|
||||
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. See error
|
||||
|
||||
## Expected behavior
|
||||
|
||||
What you expected to happen instead.
|
||||
|
||||
## Screenshots / logs
|
||||
|
||||
If applicable, add screenshots or paste relevant log output. **Redact any API
|
||||
keys, tokens, or personal data before pasting.**
|
||||
|
||||
## Environment
|
||||
|
||||
- Waggle build: [desktop (Windows/macOS) or web / `npm run dev`]
|
||||
- App version or commit SHA:
|
||||
- OS and version:
|
||||
- Node version (`node -v`):
|
||||
|
||||
## Additional context
|
||||
|
||||
Anything else that might help — e.g. which workspace/persona, whether it is
|
||||
reproducible, when it started.
|
||||
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Security vulnerability
|
||||
url: https://github.com/marolinik/waggle-os/security/advisories/new
|
||||
about: Please report security issues privately, not as a public issue. See SECURITY.md.
|
||||
- name: Question or discussion
|
||||
url: https://github.com/marolinik/waggle-os/discussions
|
||||
about: Ask questions, propose ideas, or discuss architecture here.
|
||||
26
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
26
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea or improvement for Waggle OS
|
||||
title: "[feature] "
|
||||
labels: enhancement
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
## Problem
|
||||
|
||||
What problem are you trying to solve? What's the use case? A feature request
|
||||
grounded in a real workflow is much easier to evaluate than a solution in search
|
||||
of a problem.
|
||||
|
||||
## Proposed solution
|
||||
|
||||
Describe what you'd like to happen.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
Any alternative approaches or workarounds you've thought about or tried.
|
||||
|
||||
## Additional context
|
||||
|
||||
Mockups, links, or references to prior art. Note if this touches an existing
|
||||
area (memory, connectors, personas, marketplace, etc.).
|
||||
37
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
37
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<!--
|
||||
Thanks for contributing to Waggle OS! Please read docs/CONTRIBUTING.md and the
|
||||
root CLAUDE.md before opening a PR. Keep each PR to one focused change.
|
||||
-->
|
||||
|
||||
## What & why
|
||||
|
||||
<!-- What does this change do, and why is it needed? Link any related issue. -->
|
||||
|
||||
Closes #
|
||||
|
||||
## Type of change
|
||||
|
||||
- [ ] `feat` — new feature
|
||||
- [ ] `fix` — bug fix
|
||||
- [ ] `refactor` — code restructuring (no behavior change)
|
||||
- [ ] `test` — tests only
|
||||
- [ ] `docs` — documentation only
|
||||
- [ ] `chore` / `perf` / `ci`
|
||||
|
||||
## How it was tested
|
||||
|
||||
<!-- Commands you ran and what you observed. Bug fixes should add a regression test. -->
|
||||
|
||||
- [ ] `npm run test` (Vitest) passes
|
||||
- [ ] `npx tsc --noEmit` passes for the package(s) I touched
|
||||
- [ ] `npm run lint` passes
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] The change is scoped to one concern (no unrelated edits or reformatting).
|
||||
- [ ] New behavior has accompanying tests; bug fixes have a regression test.
|
||||
- [ ] No secrets, API keys, or credentials are committed.
|
||||
- [ ] Docs updated if behavior, commands, or configuration changed.
|
||||
- [ ] If this touches the memory substrate (`packages/hive-mind-core`), I read
|
||||
CLAUDE.md §7.5 (the monorepo is the source of truth; do not author
|
||||
substrate features directly on the OSS mirror).
|
||||
39
.github/dependabot.yml
vendored
Normal file
39
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
# Dependabot — dependency & supply-chain update gate for Waggle OS.
|
||||
# Docs: https://docs.github.com/code-security/dependabot/dependabot-version-updates
|
||||
version: 2
|
||||
updates:
|
||||
# npm — one entry at the repo root. This is an npm workspaces monorepo with a
|
||||
# SINGLE root package-lock.json shared by every workspace (apps/*, packages/*),
|
||||
# so Dependabot's workspace-aware npm updater covers the root manifest AND all
|
||||
# workspace package.json files from `directory: "/"`. (The plural `directories`
|
||||
# form is for repos with independent per-directory lockfiles — not this layout.)
|
||||
# Minor+patch bumps are grouped into one PR per run to keep review volume low;
|
||||
# majors stay ungrouped so breaking changes land as isolated, reviewable PRs.
|
||||
#
|
||||
# Intentionally NOT covered: `app/` (the Tauri desktop shell) is a standalone
|
||||
# npm project outside the workspace with its own app/package-lock.json, and its
|
||||
# Tauri toolchain is owned by the release/tauri workflows — add a separate npm
|
||||
# entry with `directory: "/app"` only if that wave asks for it. `external/**`
|
||||
# is vendored third-party code and is left alone.
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
open-pull-requests-limit: 10
|
||||
groups:
|
||||
npm-minor-and-patch:
|
||||
update-types:
|
||||
- "minor"
|
||||
- "patch"
|
||||
|
||||
# GitHub Actions pinned across .github/workflows/*.
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
open-pull-requests-limit: 5
|
||||
groups:
|
||||
actions-minor-and-patch:
|
||||
update-types:
|
||||
- "minor"
|
||||
- "patch"
|
||||
242
.github/sync.md
vendored
Normal file
242
.github/sync.md
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
> **⚠️ DEPRECATED (2026-04-30 monorepo migration) — HISTORICAL/AUDIT REFERENCE ONLY.**
|
||||
> This manual describes the dual-repo bidirectional-sync mechanism that ran while the
|
||||
> substrate lived in BOTH waggle-os (`packages/core/src/{mind,harvest}/`) and an external
|
||||
> `marolinik/hive-mind`. After the migration the substrate lives ONLY at
|
||||
> **`packages/hive-mind-core/src/{mind,harvest}/`**, and the OSS mirror is **generated** via
|
||||
> `git subtree split` — see [`packages/hive-mind-core/CONTRIBUTING.md`](../packages/hive-mind-core/CONTRIBUTING.md)
|
||||
> and [`scripts/oss-subtree-split.sh`](../scripts/oss-subtree-split.sh). The
|
||||
> `mind-parity-check.yml` / `sync-mind.yml` workflows referenced below are **inert deprecation
|
||||
> anchors** (their `packages/core/src/...` trigger paths no longer exist, so they never fire).
|
||||
> Everything below is retained for historical context — do NOT treat it as the active process.
|
||||
> See CLAUDE.md §7.5 for the current mechanism.
|
||||
|
||||
---
|
||||
|
||||
# Memory Substrate Sync — `waggle-os` ↔ `hive-mind`
|
||||
|
||||
This document is the operating manual for the two GitHub Actions workflows
|
||||
that keep `packages/core/src/mind/` and `packages/core/src/harvest/` in
|
||||
sync with the OSS release artifact at
|
||||
[`marolinik/hive-mind`](https://github.com/marolinik/hive-mind).
|
||||
|
||||
> **Audience:** anyone modifying files under `packages/core/src/mind/` or
|
||||
> `packages/core/src/harvest/`. If you only touch `packages/agent/`,
|
||||
> `packages/server/`, `apps/web/`, etc., none of this applies — those
|
||||
> paths are explicitly Waggle-only per
|
||||
> [`hive-mind/EXTRACTION.md`](https://github.com/marolinik/hive-mind/blob/master/EXTRACTION.md).
|
||||
|
||||
---
|
||||
|
||||
## TL;DR
|
||||
|
||||
| What you did | What happens |
|
||||
|--------------|--------------|
|
||||
| Modify `packages/core/src/mind/foo.ts` and open a PR | `mind-parity-check` runs hive-mind's tests against your change. Failure blocks merge unless allowlisted. |
|
||||
| Merge the PR to `main` | `sync-mind-to-hive-mind` opens a PR on `marolinik/hive-mind` with the filtered diff. Manual review there before merge. |
|
||||
| Want to skip a parity test that's intentionally divergent | Add the basename to `.parity-allowlist` with a comment explaining why. |
|
||||
| Modify `packages/core/src/mind/vault.ts` (NOT-extracted) | Sync workflow filters this out automatically — nothing leaks to hive-mind. |
|
||||
|
||||
---
|
||||
|
||||
## Why this exists
|
||||
|
||||
Both repos carry their own copy of `packages/core/src/mind/` and
|
||||
`packages/core/src/harvest/`. The audit at
|
||||
`PM-Waggle-OS/decisions/2026-04-26-memory-sync-audit.md` documented the
|
||||
status quo before this workflow shipped:
|
||||
|
||||
- No automated sync existed; bug fixes flowed in both directions ad-hoc.
|
||||
- Two production bug fixes that landed in hive-mind never made it back
|
||||
to waggle-os until the manual Step 1 backport (commits `89c1004` +
|
||||
`fed4a20`).
|
||||
- The OSS release artifact and the production substrate had silently
|
||||
drifted in 2/19 mind/ files.
|
||||
|
||||
The two workflows below close that gap. Their goal is **detection +
|
||||
human-reviewed propagation**, never automatic merge.
|
||||
|
||||
---
|
||||
|
||||
## Workflow 1 — `mind-parity-check.yml`
|
||||
|
||||
**File:** `.github/workflows/mind-parity-check.yml`
|
||||
**Trigger:** PR or push to `main` that touches `packages/core/src/mind/`,
|
||||
`packages/core/src/harvest/`, or `packages/core/tests/mind/`.
|
||||
**Outcome:** test-pass = ✅ block-clear; test-fail = ❌ merge blocked.
|
||||
|
||||
### What it does, step by step
|
||||
|
||||
1. Checks out **both** repos — waggle-os in `./waggle-os/`, hive-mind
|
||||
master in `./hive-mind/`.
|
||||
2. Runs the **waggle-os baseline** mind/ test suite. This is the
|
||||
committed Step 2 ports plus all pre-existing waggle-os mind/ tests.
|
||||
If this fails, the PR is rejected on a regular regression — same as
|
||||
any other failing test.
|
||||
3. **Injects** the latest hive-mind tests into the waggle-os checkout
|
||||
under `<basename>-hive-mind.test.ts` filenames, with import paths
|
||||
adapted via `sed` from `./*.js` to `../../src/mind/*.js`. Three rules
|
||||
govern what gets injected:
|
||||
- **`.parity-allowlist`**: filenames listed here are skipped entirely.
|
||||
- **Already-committed `-hive-mind` file**: kept as-is. The committed
|
||||
version (typically a Step 2 port with bespoke header comments
|
||||
documenting provenance and adaptation rationale) is what the parity
|
||||
check exercises — overwriting it with the latest hive-mind verbatim
|
||||
content would silently drop those headers and any waggle-os-side
|
||||
adaptations.
|
||||
- **No collision**: copy hive-mind file as `<basename>-hive-mind.test.ts`
|
||||
into `tests/mind/`, sed the imports.
|
||||
4. Runs the **combined suite** (waggle-os baseline + injected
|
||||
hive-mind tests). If hive-mind has added new test cases since the
|
||||
last Step 2 port, they'll surface here. Failure here means waggle-os
|
||||
has accidentally diverged from hive-mind's surface contract.
|
||||
5. Emits an **informational diff** of shared substrate file sizes —
|
||||
not a gate, just visibility.
|
||||
|
||||
### When it fails
|
||||
|
||||
| Failure mode | What it means | What to do |
|
||||
|--------------|---------------|------------|
|
||||
| Baseline waggle-os mind/ tests fail | Regular regression | Fix your change |
|
||||
| `<x>-hive-mind.test.ts` (suffixed) fails | hive-mind tests a behavior waggle-os doesn't honor any more | Decide: (a) accept and fix waggle-os to match hive-mind, OR (b) document intentional divergence and add to `.parity-allowlist` |
|
||||
| Test fails because of import-path adaptation drift | hive-mind reorganized imports | Update the `sed` rules in `mind-parity-check.yml` |
|
||||
| `db-hive-mind.test.ts` fails (always — see allowlist) | The proprietary-tables-must-be-absent assertion mismatches Waggle's schema | This is in `.parity-allowlist` already; if you removed it, restore it |
|
||||
|
||||
### `.parity-allowlist` policy
|
||||
|
||||
The file at the repo root lists test basenames whose verbatim hive-mind
|
||||
copy is intentionally skipped during the parity check.
|
||||
|
||||
```
|
||||
# Comment describing why this entry exists
|
||||
file-name.test.ts
|
||||
```
|
||||
|
||||
**Adding an entry** requires a comment line directly above with the
|
||||
divergence rationale and at least one cross-reference (EXTRACTION.md
|
||||
section, PM-Waggle-OS memo, or related PR).
|
||||
|
||||
**Removing an entry** is allowed only when the divergence is resolved
|
||||
— either hive-mind upstream changed or waggle-os adopted the upstream
|
||||
behavior. Re-running parity check should pass without the entry first.
|
||||
|
||||
The current single entry is `db-hive-mind.test.ts` because hive-mind's
|
||||
`db.test.ts` asserts proprietary tables (ai_interactions,
|
||||
execution_traces, evolution_runs, improvement_signals, install_audit)
|
||||
MUST BE ABSENT — its OSS-scrub guarantee. Waggle-os carries those
|
||||
tables legitimately. The waggle-os adaptation lives in committed
|
||||
`db.test.ts` (no suffix) which splits the original assertion into "OSS
|
||||
shared must exist" (verbatim from hive-mind) + "Waggle-specific must
|
||||
exist" (inverted). See
|
||||
`PM-Waggle-OS/decisions/2026-04-26-memory-sync-step2-test-port-results.md`.
|
||||
|
||||
---
|
||||
|
||||
## Workflow 2 — `sync-mind.yml`
|
||||
|
||||
**File:** `.github/workflows/sync-mind.yml`
|
||||
**Trigger:** push to `main` that touches `packages/core/src/mind/` or
|
||||
`packages/core/src/harvest/`.
|
||||
**Outcome:** opens a PR on `marolinik/hive-mind` with the filtered
|
||||
diff. **Never auto-merges.** The PR sits for manual review on the
|
||||
hive-mind side.
|
||||
|
||||
### Direction note (binding)
|
||||
|
||||
This workflow implements ONLY the **waggle-os → hive-mind** direction.
|
||||
The empirically primary direction (**hive-mind → waggle-os**) requires
|
||||
a workflow living **inside the hive-mind repo**, which is out of scope
|
||||
for the waggle-os Step 3 PR. It will be added via a sibling PR to
|
||||
hive-mind once Step 3 here is ratified by PM. The current Memory Sync
|
||||
Repair audit shows hive-mind is the more active substrate repo (ahead
|
||||
in 2/5 audit dimensions, +14 organic test files), so the
|
||||
hive-mind-side workflow carries the heavier production burden.
|
||||
|
||||
### Filter list — NOT-extracted paths
|
||||
|
||||
The workflow excludes these paths from the patch — leaking them into
|
||||
hive-mind would put Waggle-specific code into the Apache-2.0 release
|
||||
artifact:
|
||||
|
||||
```
|
||||
packages/core/src/mind/vault.ts
|
||||
packages/core/src/mind/evolution-runs.ts
|
||||
packages/core/src/mind/execution-traces.ts
|
||||
packages/core/src/mind/improvement-signals.ts
|
||||
packages/core/src/compliance/**
|
||||
```
|
||||
|
||||
This list mirrors the "NOT Extracted" section of
|
||||
[`hive-mind/EXTRACTION.md`](https://github.com/marolinik/hive-mind/blob/master/EXTRACTION.md).
|
||||
**If you add a new NOT-extracted file, update the workflow's
|
||||
`excluded_paths` array AND EXTRACTION.md in the same PR** — otherwise
|
||||
the file will leak on the next mind/ push.
|
||||
|
||||
### Setup — `HIVE_MIND_SYNC_TOKEN`
|
||||
|
||||
This workflow needs a fine-grained PAT scoped to `marolinik/hive-mind`
|
||||
with `pull_request: write` + `contents: write` permissions. Marko
|
||||
configures it via:
|
||||
|
||||
```bash
|
||||
gh secret set HIVE_MIND_SYNC_TOKEN --repo marolinik/waggle-os
|
||||
gh variable set MIND_SYNC_ENABLED --body 'true' --repo marolinik/waggle-os
|
||||
```
|
||||
|
||||
The `MIND_SYNC_ENABLED` repository variable is the kill switch — set
|
||||
it to `false` to disable the workflow entirely without removing the
|
||||
secret. The workflow's `if:` condition checks this before running.
|
||||
|
||||
If `HIVE_MIND_SYNC_TOKEN` is unset, the workflow fails fast with a
|
||||
clear error rather than silently skipping.
|
||||
|
||||
### When the patch doesn't apply
|
||||
|
||||
`git apply --3way` falls back to a 3-way merge when the index
|
||||
mismatch is small. If even that fails, the workflow exits with an
|
||||
error pointing to the source SHA. Manual reconciliation:
|
||||
|
||||
1. Check out hive-mind master locally.
|
||||
2. `git apply` the patch from the workflow run's
|
||||
`sync-patch-<sha>` artifact.
|
||||
3. Resolve conflicts; commit on a branch named
|
||||
`auto-sync/waggle-os-<short-sha>`.
|
||||
4. Open the PR by hand following the same body template.
|
||||
|
||||
This is rare in practice because hive-mind's mind/ files are mostly
|
||||
verbatim extractions of waggle-os's — any genuine conflict means
|
||||
hive-mind has its own change at the same lines, which is exactly the
|
||||
case the human review is supposed to catch.
|
||||
|
||||
---
|
||||
|
||||
## Bidirectional bug fix protocol
|
||||
|
||||
When you find a bug whose fix should go into BOTH repos:
|
||||
|
||||
1. Fix it in waggle-os first (production-impacted).
|
||||
2. Merge to waggle-os main → `sync-mind.yml` auto-opens a hive-mind PR.
|
||||
3. Review and merge the hive-mind PR.
|
||||
4. Confirm the next `mind-parity-check` on waggle-os main is green —
|
||||
that closes the loop.
|
||||
|
||||
When the bug originates in hive-mind (e.g. an upstream contributor
|
||||
reports it):
|
||||
|
||||
1. Wait for the hive-mind PR (or open it yourself).
|
||||
2. After it merges, the eventual hive-mind→waggle-os auto-PR (when
|
||||
that workflow ships) will pick it up.
|
||||
3. Until then, manual cherry-pick to waggle-os, identical to Step 1
|
||||
of the original sync repair (see Step 1 results memo at
|
||||
`PM-Waggle-OS/decisions/2026-04-26-memory-sync-step1-results.md`
|
||||
for the canonical pattern: commit message references hive-mind SHA
|
||||
verbatim).
|
||||
|
||||
---
|
||||
|
||||
## Cross-references
|
||||
|
||||
- Audit + 3-step plan: `PM-Waggle-OS/decisions/2026-04-26-memory-sync-audit.md`
|
||||
- Step 1 results (forward-port + bidirectional audit): `PM-Waggle-OS/decisions/2026-04-26-memory-sync-step1-results.md`
|
||||
- Step 2 results (test port): `PM-Waggle-OS/decisions/2026-04-26-memory-sync-step2-test-port-results.md`
|
||||
- Step 3 results (this workflow): `PM-Waggle-OS/decisions/2026-04-26-memory-sync-step3-cicd-results.md`
|
||||
- EXTRACTION.md: `D:\Projects\hive-mind\EXTRACTION.md` (or [GitHub link](https://github.com/marolinik/hive-mind/blob/master/EXTRACTION.md))
|
||||
179
.github/workflows/ci.yml
vendored
Normal file
179
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
name: CI
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-npm-
|
||||
|
||||
# NOTE: the switch to `npm ci` (deterministic, lockfile-faithful) is deferred
|
||||
# to the deps/lockfile hardening pass, after the root package-lock.json is
|
||||
# regenerated in sync with every workspace manifest. `npm install` is the
|
||||
# safe, lockfile-tolerant install until then.
|
||||
- run: npm install
|
||||
|
||||
# Real typecheck gate. The old step ran `npx tsc --noEmit` against the root
|
||||
# tsconfig.json, whose `"files": ["apps/web/src/vite-env.d.ts"]` (and no
|
||||
# `include`) typechecks essentially nothing. build:packages is the actual
|
||||
# `tsc --build` chain for every @waggle/* package (shared → hive-mind-core →
|
||||
# core → agent → server) and also emits the dist/ that apps/web unit tests
|
||||
# import; typecheck:web is the real apps/web check (tsc -p tsconfig.app.json).
|
||||
- name: Type check — workspace packages (tsc --build chain)
|
||||
run: npm run build:packages
|
||||
|
||||
- name: Type check — web (apps/web, tsc -p tsconfig.app.json)
|
||||
run: npm run typecheck:web
|
||||
|
||||
- name: Lint (root flat config)
|
||||
run: npm run lint
|
||||
|
||||
- name: Tauri TS typecheck (app/scripts)
|
||||
run: npx tsc -p app/tsconfig.json
|
||||
|
||||
# Runtime tests pack and install workspace packages. Build every ignored
|
||||
# dist/ payload explicitly so CI proves a fresh checkout.
|
||||
- name: Build package-install test runtimes
|
||||
run: |
|
||||
npm run build:hook-runtime
|
||||
npm run build --workspace @waggle/cli
|
||||
npm run build --workspace @waggle-ai/waggle
|
||||
npm run build --workspace waggle-memory-mcp
|
||||
|
||||
- name: Unit tests — packages + cross-cutting (root vitest)
|
||||
run: |
|
||||
npm test -- \
|
||||
--exclude=packages/cli/tests/cli-runtime.test.ts \
|
||||
--exclude=packages/hive-mind-cli/tests/cli-help.test.ts \
|
||||
--exclude=packages/hive-mind-mcp-server/tests/runtime.test.ts \
|
||||
--exclude=packages/launcher/tests/cli.test.ts \
|
||||
--exclude=packages/memory-mcp/tests/runtime.test.ts
|
||||
|
||||
# These tests each create a temporary project and run npm install. Running
|
||||
# several cold installs in parallel makes individual test timeouts measure
|
||||
# runner contention rather than package correctness.
|
||||
- name: Package-install runtime tests (serial)
|
||||
run: |
|
||||
npx vitest run \
|
||||
packages/cli/tests/cli-runtime.test.ts \
|
||||
packages/hive-mind-cli/tests/cli-help.test.ts \
|
||||
packages/hive-mind-mcp-server/tests/runtime.test.ts \
|
||||
packages/launcher/tests/cli.test.ts \
|
||||
packages/memory-mcp/tests/runtime.test.ts \
|
||||
--maxWorkers=1 \
|
||||
--no-file-parallelism
|
||||
|
||||
# The root vitest.config.ts excludes `apps/**`, so apps/web's own 131-file
|
||||
# suite never ran in CI. Run it via its own vitest config (jsdom). Blocking.
|
||||
- name: Unit tests — apps/web
|
||||
run: npm run test -w apps/web
|
||||
|
||||
- name: Security audit (informational)
|
||||
run: npm audit --audit-level=high
|
||||
continue-on-error: true
|
||||
|
||||
# ADVISORY / NON-BLOCKING. `continue-on-error: true` means a red e2e run does
|
||||
# NOT block merges — by design. These specs are broad product/audit journeys
|
||||
# (full-product-audit, power-user-stress, competitive-benchmarks, …) that are
|
||||
# historically flake-prone, so gating merges on them would produce false reds.
|
||||
# The blocking `e2e-smoke` job above covers the stable launch, settings,
|
||||
# memory, workspace, and mobile regression slice. This broad job stays
|
||||
# advisory so exploratory audit coverage can report flakes without blocking
|
||||
# merges.
|
||||
e2e-smoke:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-npm-
|
||||
|
||||
- run: npm install
|
||||
- name: Build packages
|
||||
run: npm run build:packages
|
||||
- name: Build frontend
|
||||
run: npm run build
|
||||
- name: Install Playwright browsers
|
||||
run: npx playwright install --with-deps chromium
|
||||
- name: Run blocking Playwright smoke journeys
|
||||
run: npm run test:e2e:smoke
|
||||
env:
|
||||
WAGGLE_ECHO_MODE: "1"
|
||||
NODE_ENV: test
|
||||
WAGGLE_TRUST_LOCALHOST: "1"
|
||||
|
||||
e2e:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-npm-
|
||||
|
||||
- run: npm install
|
||||
|
||||
# apps/web's tsc build imports @waggle/shared etc. which export dist/;
|
||||
# build the workspace packages first (the deploy does this via build:all).
|
||||
- name: Build packages
|
||||
run: npm run build:packages
|
||||
|
||||
- name: Build frontend
|
||||
run: npm run build
|
||||
|
||||
- name: Install Playwright browsers
|
||||
run: npx playwright install --with-deps chromium
|
||||
|
||||
- name: Run Playwright E2E tests
|
||||
run: npx playwright test tests/e2e/
|
||||
env:
|
||||
WAGGLE_ECHO_MODE: "1"
|
||||
NODE_ENV: test
|
||||
# D1: the e2e suite hits /api/* directly without a bearer token; trust
|
||||
# loopback in CI's test server (prod default stays secure). Mirrors
|
||||
# vitest.setup.ts and playwright.config.ts webServer.env.
|
||||
WAGGLE_TRUST_LOCALHOST: "1"
|
||||
|
||||
- name: Upload Playwright report
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
retention-days: 14
|
||||
99
.github/workflows/deploy-www.yml
vendored
Normal file
99
.github/workflows/deploy-www.yml
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
name: Deploy Landing Page
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'apps/www/**'
|
||||
- 'docs/methodology.md'
|
||||
- 'package.json'
|
||||
- 'package-lock.json'
|
||||
- '.github/workflows/deploy-www.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: www-production
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
deployment_config:
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: production
|
||||
url: https://waggle-os.ai
|
||||
outputs:
|
||||
configured: ${{ steps.vercel.outputs.configured }}
|
||||
env:
|
||||
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
|
||||
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
|
||||
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
|
||||
steps:
|
||||
- name: Check Vercel configuration
|
||||
id: vercel
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ -n "$VERCEL_TOKEN" && -n "$VERCEL_ORG_ID" && -n "$VERCEL_PROJECT_ID" ]]; then
|
||||
echo "configured=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "configured=false" >> "$GITHUB_OUTPUT"
|
||||
echo "::warning::Landing page verified but not deployed: Vercel secrets are not configured."
|
||||
fi
|
||||
|
||||
verify:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Test public site
|
||||
run: npm run test -w apps/www -- --reporter=dot
|
||||
|
||||
- name: Typecheck public site
|
||||
run: npx tsc --noEmit --project apps/www/tsconfig.json
|
||||
|
||||
- name: Build public site
|
||||
run: npm run build:www
|
||||
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [deployment_config, verify]
|
||||
if: needs.deployment_config.outputs.configured == 'true'
|
||||
environment:
|
||||
name: production
|
||||
url: https://waggle-os.ai
|
||||
env:
|
||||
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
|
||||
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
|
||||
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Pull Vercel production environment
|
||||
working-directory: apps/www
|
||||
run: npx --yes vercel pull --yes --environment=production --token="$VERCEL_TOKEN"
|
||||
|
||||
- name: Build Vercel prebuilt output
|
||||
working-directory: apps/www
|
||||
run: npx --yes vercel build --prod --token="$VERCEL_TOKEN"
|
||||
|
||||
- name: Deploy Vercel prebuilt output
|
||||
working-directory: apps/www
|
||||
run: npx --yes vercel deploy --prebuilt --prod --token="$VERCEL_TOKEN"
|
||||
101
.github/workflows/hive-mind-cli-cross-platform.yml
vendored
Normal file
101
.github/workflows/hive-mind-cli-cross-platform.yml
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
name: hive-mind-cli cross-platform install + smoke
|
||||
|
||||
# Wave 1 cleanup brief 2026-04-29 §3.5 — windows-latest CI regression test.
|
||||
# Verifies that `npm install -g @waggle/hive-mind-cli` followed by `hive-mind-cli doctor`
|
||||
# works without ENOENT, quarantine, or manual debug on Windows + macOS + Linux.
|
||||
#
|
||||
# Acceptance per feedback_memory_install_dead_simple binding rule:
|
||||
# - All three OS matrix cells PASS green
|
||||
# - Zero manual intervention required
|
||||
# - First MCP-style tool call (the doctor smoke test) succeeds in <60s
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, 'feature/**']
|
||||
paths:
|
||||
- 'packages/hive-mind-cli/**'
|
||||
- 'packages/hive-mind-shim-core/**'
|
||||
- 'packages/hive-mind-core/**'
|
||||
- 'packages/hive-mind-mcp-server/**'
|
||||
- 'packages/hive-mind-wiki-compiler/**'
|
||||
- 'packages/hive-mind-hooks-claude-code/**'
|
||||
- '.github/workflows/hive-mind-cli-cross-platform.yml'
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'packages/hive-mind-cli/**'
|
||||
- 'packages/hive-mind-shim-core/**'
|
||||
- 'packages/hive-mind-core/**'
|
||||
|
||||
jobs:
|
||||
install-and-smoke:
|
||||
name: ${{ matrix.os }} install + smoke
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
node-version: ['20.x']
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Install workspace deps
|
||||
run: npm install
|
||||
|
||||
# hive-mind-core imports @waggle/shared, whose dist/ is gitignored and so
|
||||
# absent on a clean checkout. hive-mind-core/tsconfig declares no project
|
||||
# reference to it (the OSS subtree-split mirrors that tsconfig, so a
|
||||
# ../shared reference would dangle in the export root), so `tsc --build`
|
||||
# won't bootstrap it. Build shared first — same as ci.yml/tauri-build-pr.yml.
|
||||
- name: Build @waggle/shared (hive-mind-core dep)
|
||||
run: cd packages/shared && npx tsc --build
|
||||
|
||||
- name: Build hive-mind-core (substrate)
|
||||
run: cd packages/hive-mind-core && npx tsc --build
|
||||
|
||||
- name: Build hive-mind-wiki-compiler
|
||||
run: cd packages/hive-mind-wiki-compiler && npx tsc --build
|
||||
|
||||
- name: Build hive-mind-mcp-server
|
||||
run: cd packages/hive-mind-mcp-server && npx tsc --build
|
||||
|
||||
- name: Build hive-mind-cli
|
||||
run: cd packages/hive-mind-cli && npx tsc --build
|
||||
|
||||
- name: Run postinstall (bundles fix on win32, no-op POSIX)
|
||||
run: node packages/hive-mind-cli/postinstall.cjs
|
||||
|
||||
- name: Init hive-mind data dir (scaffold personal.mind for the smoke)
|
||||
run: node packages/hive-mind-cli/dist/index.js init
|
||||
env:
|
||||
HIVE_MIND_DATA_DIR: ${{ runner.temp }}/waggle-ci-home
|
||||
|
||||
- name: Smoke test — hive-mind-cli doctor (independent of upstream hook)
|
||||
run: node packages/hive-mind-cli/dist/index.js doctor
|
||||
env:
|
||||
# doctor + init resolve the mind via HIVE_MIND_DATA_DIR (the CLI never
|
||||
# reads WAGGLE_HOME — that prior env was a no-op). Isolate to a CI temp
|
||||
# dir; init above scaffolds personal.mind there so doctor finds it.
|
||||
HIVE_MIND_DATA_DIR: ${{ runner.temp }}/waggle-ci-home
|
||||
|
||||
- name: Doctor smoke result must be green (no quarantine, no ENOENT)
|
||||
run: |
|
||||
# If we got here, doctor exited 0 — green. Re-emit a confirmation marker
|
||||
# so log scrapers see the success line clearly.
|
||||
echo "::notice title=hive-mind-cli doctor passed::Cross-platform install + smoke verified on ${{ matrix.os }}"
|
||||
shell: bash
|
||||
|
||||
acceptance:
|
||||
name: Wave 1 acceptance gate
|
||||
runs-on: ubuntu-latest
|
||||
needs: install-and-smoke
|
||||
steps:
|
||||
- name: All matrix cells passed
|
||||
run: echo "Wave 1 dead-simple acceptance criteria met across windows-latest + macos-latest + ubuntu-latest."
|
||||
115
.github/workflows/installer-smoke.yml
vendored
Normal file
115
.github/workflows/installer-smoke.yml
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
name: Installer Smoke
|
||||
|
||||
# Authoritative Linux proof for the one-line self-host installer (steal #5).
|
||||
# The installer is developed on Windows, where the esbuild-hoist trap and CRLF
|
||||
# quirks are Windows-only — so a green `bash -n` locally is NOT proof it works
|
||||
# for the VPS/homelab audience. This job runs install.sh end-to-end from a
|
||||
# clean ubuntu runner: it actually installs, builds packages, boots the sidecar,
|
||||
# and asserts /health returns 200, then tears it down and asserts the port frees.
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- install.sh
|
||||
- scripts/waggle-server.sh
|
||||
- .github/workflows/installer-smoke.yml
|
||||
push:
|
||||
paths:
|
||||
- install.sh
|
||||
- scripts/waggle-server.sh
|
||||
- .github/workflows/installer-smoke.yml
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
installer-smoke:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
WAGGLE_PORT: "3947"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# The `runner` context is not available in job-level env, so the scratch
|
||||
# paths (isolated from the checkout to exercise the real "copy + fresh
|
||||
# install" path) are computed here from $RUNNER_TEMP instead.
|
||||
- name: Compute scratch paths
|
||||
run: |
|
||||
echo "WAGGLE_INSTALL_DIR=$RUNNER_TEMP/waggle" >> "$GITHUB_ENV"
|
||||
echo "WAGGLE_DATA_DIR=$RUNNER_TEMP/wdata" >> "$GITHUB_ENV"
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
|
||||
# shellcheck ships pre-installed on ubuntu-latest runners. Findings are
|
||||
# failures — the installer is user-facing shell that runs unsupervised via
|
||||
# `curl | bash`, so lint cleanliness is a correctness gate, not a nicety.
|
||||
- name: shellcheck installer scripts
|
||||
run: shellcheck install.sh scripts/waggle-server.sh
|
||||
|
||||
# The real E2E. --local-source copies THIS checkout (tracked + untracked,
|
||||
# excluding node_modules/dist) into a scratch dir, then does a from-scratch
|
||||
# npm install + build:packages there. --no-web keeps it to API/echo mode
|
||||
# (no vite build); --no-start hands the boot to waggle-server.sh below so we
|
||||
# test the process manager too.
|
||||
- name: Install (install.sh --yes, from-scratch)
|
||||
run: |
|
||||
./install.sh \
|
||||
--yes \
|
||||
--no-web \
|
||||
--no-start \
|
||||
--local-source "$GITHUB_WORKSPACE" \
|
||||
--dir "$WAGGLE_INSTALL_DIR" \
|
||||
--data-dir "$WAGGLE_DATA_DIR" \
|
||||
--port "$WAGGLE_PORT"
|
||||
|
||||
- name: Start the sidecar (waggle-server.sh start)
|
||||
run: |
|
||||
bash "$WAGGLE_INSTALL_DIR/scripts/waggle-server.sh" start \
|
||||
--port "$WAGGLE_PORT" \
|
||||
--data-dir "$WAGGLE_DATA_DIR"
|
||||
|
||||
# Defensive re-poll. waggle-server.sh already blocks until /health is 200
|
||||
# (up to 60s; the sidecar spends ~9s on marketplace sync before listening),
|
||||
# so this normally passes on the first attempt. The wider 90s budget guards
|
||||
# against a slow cold runner without making the assertion flaky.
|
||||
- name: Wait for /health (HTTP 200)
|
||||
run: |
|
||||
url="http://127.0.0.1:${WAGGLE_PORT}/health"
|
||||
for i in $(seq 1 90); do
|
||||
code="$(curl -s -o /dev/null -w '%{http_code}' --max-time 3 "$url" || echo 000)"
|
||||
if [ "$code" = "200" ]; then
|
||||
echo "healthy after ${i}s (HTTP 200)"
|
||||
exit 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
echo "::error::/health did not return 200 within 90s"
|
||||
echo "--- last sidecar log lines ---"
|
||||
tail -n 40 "$WAGGLE_DATA_DIR/server.log" 2>/dev/null || true
|
||||
exit 1
|
||||
|
||||
- name: Status
|
||||
run: |
|
||||
bash "$WAGGLE_INSTALL_DIR/scripts/waggle-server.sh" status \
|
||||
--port "$WAGGLE_PORT" \
|
||||
--data-dir "$WAGGLE_DATA_DIR"
|
||||
|
||||
- name: Stop
|
||||
run: |
|
||||
bash "$WAGGLE_INSTALL_DIR/scripts/waggle-server.sh" stop \
|
||||
--port "$WAGGLE_PORT" \
|
||||
--data-dir "$WAGGLE_DATA_DIR"
|
||||
|
||||
- name: Assert port is free after stop
|
||||
run: |
|
||||
url="http://127.0.0.1:${WAGGLE_PORT}/health"
|
||||
if curl -fsS -o /dev/null --max-time 3 "$url"; then
|
||||
echo "::error::/health still responding on port ${WAGGLE_PORT} after stop"
|
||||
exit 1
|
||||
fi
|
||||
echo "port ${WAGGLE_PORT} is free"
|
||||
|
||||
- name: Dump sidecar log on failure
|
||||
if: failure()
|
||||
run: tail -n 100 "$WAGGLE_DATA_DIR/server.log" 2>/dev/null || echo "(no log file)"
|
||||
178
.github/workflows/mind-parity-check.yml
vendored
Normal file
178
.github/workflows/mind-parity-check.yml
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
name: mind-parity-check
|
||||
|
||||
# DEPRECATED 2026-04-30 — CC Sesija B monorepo migration §2.6 Task B22.
|
||||
#
|
||||
# This workflow ran the (then-external) hive-mind repo's mind/+harvest/ tests
|
||||
# against waggle-os's substrate to verify behavioral parity while the same code
|
||||
# lived in both repos. After CC Sesija B migration, the substrate lives ONLY in
|
||||
# waggle-os/packages/hive-mind-core/, and the OSS mirror at
|
||||
# github.com/marolinik/hive-mind is generated FROM waggle-os via subtree-split
|
||||
# (not maintained as a parallel codebase). Parity checking is therefore
|
||||
# definitionally trivial — the OSS export is byte-identical to its source.
|
||||
#
|
||||
# This workflow is preserved as the deprecation anchor. It will NOT fire on
|
||||
# push because trigger paths (packages/core/src/mind/**) no longer exist as
|
||||
# tracked content. See sync-mind.yml's deprecation note for the full migration
|
||||
# context.
|
||||
|
||||
# Memory Sync Repair Step 3.1. Verifies that hive-mind's mind/ + harvest/
|
||||
# tests pass against waggle-os's substrate. The check runs the waggle-os
|
||||
# committed Step 2 ports (which include adapted versions like db.test.ts)
|
||||
# AS BASELINE, then ALSO injects the latest hive-mind tests into the
|
||||
# waggle-os checkout under `<basename>-hive-mind.test.ts` filenames so
|
||||
# any NEW hive-mind cases since the Step 2 port get exercised.
|
||||
#
|
||||
# Triggers ONLY when shared substrate paths change. Failure blocks merge
|
||||
# unless the failing test is allowlisted in `.parity-allowlist` at the
|
||||
# repo root with a documented reason.
|
||||
#
|
||||
# See `.github/sync.md` for full design rationale and allowlist policy.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'packages/core/src/mind/**'
|
||||
- 'packages/core/src/harvest/**'
|
||||
- 'packages/core/tests/mind/**'
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'packages/core/src/mind/**'
|
||||
- 'packages/core/src/harvest/**'
|
||||
- 'packages/core/tests/mind/**'
|
||||
|
||||
concurrency:
|
||||
group: mind-parity-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
parity-check:
|
||||
name: hive-mind ↔ waggle-os mind substrate parity
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
|
||||
steps:
|
||||
- name: Checkout waggle-os
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: waggle-os
|
||||
|
||||
- name: Checkout hive-mind master
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: marolinik/hive-mind
|
||||
ref: master
|
||||
path: hive-mind
|
||||
|
||||
- name: Setup Node 20
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-npm-${{ hashFiles('waggle-os/**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-npm-
|
||||
|
||||
- name: Install waggle-os dependencies
|
||||
working-directory: waggle-os
|
||||
run: npm install
|
||||
|
||||
- name: Run waggle-os baseline mind/ tests (committed Step 2 ports)
|
||||
working-directory: waggle-os
|
||||
run: npx vitest run --reporter=default packages/core/tests/mind/
|
||||
|
||||
- name: Inject latest hive-mind tests as -hive-mind suffix files
|
||||
working-directory: waggle-os
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
allowlist_file=".parity-allowlist"
|
||||
allowlist_basenames=()
|
||||
if [ -f "$allowlist_file" ]; then
|
||||
while IFS= read -r line; do
|
||||
# Strip comments + leading/trailing whitespace; skip blanks
|
||||
clean="${line%%#*}"
|
||||
clean="$(echo "$clean" | tr -d '[:space:]')"
|
||||
[ -z "$clean" ] && continue
|
||||
allowlist_basenames+=("$clean")
|
||||
done < "$allowlist_file"
|
||||
echo "Allowlist entries: ${allowlist_basenames[@]:-<none>}"
|
||||
else
|
||||
echo "No .parity-allowlist file present — no skips."
|
||||
fi
|
||||
|
||||
# Helper: is a basename in the allowlist?
|
||||
is_allowlisted() {
|
||||
local name="$1"
|
||||
for a in "${allowlist_basenames[@]:-}"; do
|
||||
[ "$a" = "$name" ] && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
target_dir="packages/core/tests/mind"
|
||||
source_dir="../hive-mind/packages/core/src/mind"
|
||||
injected=0
|
||||
skipped=0
|
||||
|
||||
already_committed=0
|
||||
for src in "$source_dir"/*.test.ts; do
|
||||
[ -e "$src" ] || continue
|
||||
base="$(basename "$src" .test.ts)"
|
||||
target_name="${base}-hive-mind.test.ts"
|
||||
target_path="$target_dir/$target_name"
|
||||
|
||||
if is_allowlisted "$target_name"; then
|
||||
echo " SKIP (allowlist): $target_name"
|
||||
skipped=$((skipped + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ -f "$target_path" ]; then
|
||||
# File is committed (Step 2 port). Preserve its bespoke
|
||||
# header comments + any waggle-os adaptations. The
|
||||
# committed version IS what the parity check should
|
||||
# exercise — it's exactly what landed in main.
|
||||
already_committed=$((already_committed + 1))
|
||||
echo " KEEP (committed): $target_name"
|
||||
continue
|
||||
fi
|
||||
|
||||
cp "$src" "$target_path"
|
||||
# Adapt import paths from hive-mind's adjacent style (`./x.js`) to
|
||||
# waggle-os's separate-tests-folder style (`../../src/mind/x.js`).
|
||||
sed -i "s|from \"\\./|from \"../../src/mind/|g" "$target_path"
|
||||
sed -i "s|from '\\./|from '../../src/mind/|g" "$target_path"
|
||||
injected=$((injected + 1))
|
||||
echo " INJECT: $target_name"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Injected: $injected new hive-mind test file(s) under -hive-mind suffix"
|
||||
echo "Kept: $already_committed already-committed Step 2 port file(s)"
|
||||
echo "Skipped: $skipped allowlisted file(s)"
|
||||
|
||||
- name: Run combined waggle-os + injected hive-mind suite
|
||||
working-directory: waggle-os
|
||||
run: npx vitest run --reporter=default packages/core/tests/mind/
|
||||
|
||||
- name: Informational diff — shared substrate file sizes
|
||||
working-directory: waggle-os
|
||||
if: always()
|
||||
run: |
|
||||
echo "## Substrate file size comparison (informational)"
|
||||
for f in db.ts schema.ts frames.ts search.ts knowledge.ts identity.ts awareness.ts sessions.ts scoring.ts reconcile.ts ontology.ts concept-tracker.ts entity-normalizer.ts embedding-provider.ts inprocess-embedder.ts; do
|
||||
wf="packages/core/src/mind/$f"
|
||||
hf="../hive-mind/packages/core/src/mind/$f"
|
||||
if [ -f "$wf" ] && [ -f "$hf" ]; then
|
||||
wsize=$(wc -c < "$wf")
|
||||
hsize=$(wc -c < "$hf")
|
||||
diff_pct=$(awk -v w="$wsize" -v h="$hsize" 'BEGIN { if (h == 0) print "n/a"; else printf "%.1f%%", ((w - h) / h) * 100 }')
|
||||
echo " $f: waggle-os=$wsize hive-mind=$hsize delta=$diff_pct"
|
||||
fi
|
||||
done
|
||||
145
.github/workflows/release.yml
vendored
Normal file
145
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
# Waggle — Release Build Workflow
|
||||
#
|
||||
# Builds desktop apps for Windows (NSIS) and macOS (DMG) on tag push.
|
||||
# Publishes artifacts as GitHub Release assets.
|
||||
#
|
||||
# Trigger: push tag v* (e.g., v1.0.0)
|
||||
# Also supports manual dispatch for testing.
|
||||
|
||||
name: Release Build
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build-windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
|
||||
- name: Setup Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Rust cache
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: app/src-tauri
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Build packages (shared -> core -> agent -> server)
|
||||
run: npm run build:packages
|
||||
|
||||
- name: Build sidecar
|
||||
run: node scripts/build-sidecar.mjs
|
||||
|
||||
- name: Bundle native dependencies
|
||||
run: node scripts/bundle-native-deps.mjs
|
||||
|
||||
- name: Bundle Node.js runtime
|
||||
run: node scripts/bundle-node.mjs
|
||||
|
||||
- name: Stage sidecar dependencies
|
||||
run: node scripts/stage-sidecar-deps.mjs
|
||||
|
||||
- name: Build frontend
|
||||
run: cd apps/web && npx vite build
|
||||
|
||||
- name: Build Tauri (Windows)
|
||||
uses: tauri-apps/tauri-action@v0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
projectPath: app
|
||||
tagName: ${{ github.ref_name }}
|
||||
releaseName: 'Waggle ${{ github.ref_name }}'
|
||||
releaseBody: 'See the release notes for details.'
|
||||
releaseDraft: true
|
||||
prerelease: false
|
||||
|
||||
build-macos:
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
matrix:
|
||||
target: [aarch64-apple-darwin, x86_64-apple-darwin]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
|
||||
- name: Setup Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- name: Rust cache
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: app/src-tauri
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Build packages (shared -> core -> agent -> server)
|
||||
run: npm run build:packages
|
||||
|
||||
- name: Build sidecar
|
||||
run: node scripts/build-sidecar.mjs
|
||||
|
||||
- name: Bundle native dependencies
|
||||
run: node scripts/bundle-native-deps.mjs
|
||||
env:
|
||||
TARGET_ARCH: ${{ matrix.target == 'aarch64-apple-darwin' && 'arm64' || 'x64' }}
|
||||
|
||||
- name: Bundle Node.js runtime
|
||||
run: node scripts/bundle-node.mjs
|
||||
env:
|
||||
TARGET_ARCH: ${{ matrix.target == 'aarch64-apple-darwin' && 'arm64' || 'x64' }}
|
||||
|
||||
- name: Stage sidecar dependencies
|
||||
run: node scripts/stage-sidecar-deps.mjs
|
||||
env:
|
||||
TARGET_ARCH: ${{ matrix.target == 'aarch64-apple-darwin' && 'arm64' || 'x64' }}
|
||||
|
||||
- name: Build frontend
|
||||
run: cd apps/web && npx vite build
|
||||
|
||||
- name: Build Tauri (macOS)
|
||||
uses: tauri-apps/tauri-action@v0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
projectPath: app
|
||||
tagName: ${{ github.ref_name }}
|
||||
releaseName: 'Waggle ${{ github.ref_name }}'
|
||||
releaseBody: 'See the release notes for details.'
|
||||
releaseDraft: true
|
||||
prerelease: false
|
||||
args: --target ${{ matrix.target }}
|
||||
|
||||
# NOTE: the Tauri auto-updater is disabled for v1 (plugins.updater removed from
|
||||
# tauri.conf.json — see BUILD P0-2 / P1-8). The former `update-manifest` job
|
||||
# published a latest.json with EMPTY signatures, which every client rejected at
|
||||
# signature verification. Re-enabling the updater requires:
|
||||
# 1. Provision a TAURI_SIGNING_PRIVATE_KEY (+ password) repo secret.
|
||||
# 2. Restore `plugins.updater` (endpoints + pubkey) in tauri.conf.json and
|
||||
# set bundle.createUpdaterArtifacts so tauri-action emits signed .sig files.
|
||||
# 3. Restore a latest.json generator that reads the real signatures from the
|
||||
# build artifacts (tauri-action can publish the manifest directly).
|
||||
230
.github/workflows/sync-mind.yml
vendored
Normal file
230
.github/workflows/sync-mind.yml
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
name: sync-mind-to-hive-mind
|
||||
|
||||
# DEPRECATED 2026-04-30 — CC Sesija B monorepo migration §2.6 Task B22.
|
||||
#
|
||||
# This workflow was the bidirectional-sync mechanism between waggle-os and the
|
||||
# now-archived `marolinik/hive-mind` repo while substrate code lived in BOTH
|
||||
# places (packages/core/src/mind/ + packages/core/src/harvest/ in waggle-os,
|
||||
# duplicated in hive-mind/packages/core/src/{mind,harvest}/).
|
||||
#
|
||||
# After CC Sesija B migration (commits ff5b4aa..b59d188 on
|
||||
# feature/hive-mind-monorepo-migration), the substrate lives ONLY in
|
||||
# waggle-os/packages/hive-mind-core/. The OSS distribution mechanism is now
|
||||
# `git subtree split` from waggle-os monorepo to public mirror — see
|
||||
# `scripts/oss-subtree-split.sh` and `packages/hive-mind-core/CONTRIBUTING.md`.
|
||||
#
|
||||
# This workflow is preserved for AUDIT TRAIL purposes (the historical
|
||||
# trigger paths and concurrency settings are referenced in EXTRACTION.md and
|
||||
# the .github/sync.md operating manual). It will NOT fire on push because the
|
||||
# trigger paths (packages/core/src/mind/** + packages/core/src/harvest/**) no
|
||||
# longer exist as tracked content — they were git-mv'd to packages/hive-mind-core/
|
||||
# on commit 3b556c0.
|
||||
#
|
||||
# DO NOT delete this file as part of cleanup — leave it as the deprecation
|
||||
# anchor. If the workflow ever needs reactivation, trigger paths must be
|
||||
# updated to the new packages/hive-mind-core/ location AND the
|
||||
# @hive-mind ↔ @waggle name remapping must be added.
|
||||
|
||||
# Memory Sync Repair Step 3.2 — waggle-os → hive-mind direction.
|
||||
#
|
||||
# Triggered when waggle-os main receives a push that touches shared
|
||||
# substrate paths (mind/ or harvest/), this workflow extracts the
|
||||
# filtered diff (excluding NOT-extracted files per EXTRACTION.md), opens
|
||||
# a PR against marolinik/hive-mind master with the patch applied, and
|
||||
# tags the PR with the source SHA.
|
||||
#
|
||||
# This is the SECONDARY direction empirically — Steps 1+2 found
|
||||
# hive-mind is the more active substrate repo (ahead in 2/5 audit
|
||||
# dimensions, +14 organic test files). The PRIMARY direction
|
||||
# (hive-mind push → auto-PR ka waggle-os) is intentionally NOT
|
||||
# implemented in this file because it requires a workflow living in
|
||||
# the hive-mind repo, which is out of CC-2 scope. It will be added
|
||||
# via a sibling PR to hive-mind once Step 3 here is ratified.
|
||||
#
|
||||
# See `.github/sync.md` for full design rationale, EXTRACTION.md
|
||||
# filter list, and how to extend bidirectional sync.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'packages/core/src/mind/**'
|
||||
- 'packages/core/src/harvest/**'
|
||||
|
||||
concurrency:
|
||||
group: sync-mind-${{ github.ref }}
|
||||
# Don't cancel — every main push to mind/ or harvest/ deserves its own
|
||||
# sync attempt (the resulting hive-mind PR is per-commit traceable).
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
open-hive-mind-pr:
|
||||
name: Open auto-sync PR to marolinik/hive-mind
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
# `HIVE_MIND_SYNC_TOKEN` is a fine-grained PAT scoped to
|
||||
# marolinik/hive-mind with `pull_request: write` + `contents: write`.
|
||||
# Configured by Marko via `gh secret set HIVE_MIND_SYNC_TOKEN`.
|
||||
# Without the secret, the job fails fast with a documented error
|
||||
# rather than silently skipping.
|
||||
if: ${{ vars.MIND_SYNC_ENABLED == 'true' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout waggle-os (full history for the diff)
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Verify HIVE_MIND_SYNC_TOKEN is configured
|
||||
run: |
|
||||
if [ -z "${{ secrets.HIVE_MIND_SYNC_TOKEN }}" ]; then
|
||||
echo "::error::HIVE_MIND_SYNC_TOKEN secret is not configured."
|
||||
echo "::error::Run: gh secret set HIVE_MIND_SYNC_TOKEN --repo marolinik/waggle-os"
|
||||
echo "::error::See .github/sync.md for full setup instructions."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Compute filtered diff (exclude NOT-extracted paths)
|
||||
id: diff
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# Files that MUST be excluded from sync per EXTRACTION.md
|
||||
# "NOT Extracted" section. Sync attempts that include these paths
|
||||
# would leak Waggle-specific code (vault, compliance, evolution,
|
||||
# tier system) into the hive-mind Apache-2.0 release artifact.
|
||||
excluded_paths=(
|
||||
'packages/core/src/mind/vault.ts'
|
||||
'packages/core/src/mind/evolution-runs.ts'
|
||||
'packages/core/src/mind/execution-traces.ts'
|
||||
'packages/core/src/mind/improvement-signals.ts'
|
||||
'packages/core/src/compliance'
|
||||
)
|
||||
|
||||
# Build the rev range. `${{ github.event.before }}` is the parent
|
||||
# commit of this push; `${{ github.sha }}` is the new HEAD. For a
|
||||
# branch's first push or a force-push, `before` may be all-zeros;
|
||||
# in that case fall back to the previous merge-base via reflog.
|
||||
before_sha='${{ github.event.before }}'
|
||||
after_sha='${{ github.sha }}'
|
||||
if [ "$before_sha" = "0000000000000000000000000000000000000000" ]; then
|
||||
echo "::warning::push has no `before` SHA — falling back to HEAD~1"
|
||||
before_sha="$(git rev-parse HEAD~1)"
|
||||
fi
|
||||
|
||||
# All shared-substrate files in this push, before exclusion.
|
||||
changed=$(git diff --name-only "$before_sha" "$after_sha" -- \
|
||||
'packages/core/src/mind/**' 'packages/core/src/harvest/**')
|
||||
|
||||
# Apply EXTRACTION.md "NOT extracted" exclusions.
|
||||
filtered_files=()
|
||||
while IFS= read -r f; do
|
||||
[ -z "$f" ] && continue
|
||||
skip=false
|
||||
for excl in "${excluded_paths[@]}"; do
|
||||
case "$f" in
|
||||
"$excl"|"$excl"/*)
|
||||
skip=true
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
$skip || filtered_files+=("$f")
|
||||
done <<< "$changed"
|
||||
|
||||
if [ ${#filtered_files[@]} -eq 0 ]; then
|
||||
echo "No syncable changes after EXTRACTION.md filtering."
|
||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Files to sync:"
|
||||
printf ' %s\n' "${filtered_files[@]}"
|
||||
|
||||
# Generate a patch limited to the filtered files. This patch will
|
||||
# apply to hive-mind because the directory layout matches:
|
||||
# waggle-os `packages/core/src/{mind,harvest}/...` ↔
|
||||
# hive-mind `packages/core/src/{mind,harvest}/...`.
|
||||
mkdir -p .sync-output
|
||||
git diff "$before_sha" "$after_sha" -- "${filtered_files[@]}" > .sync-output/patch.diff
|
||||
|
||||
# Capture the original commit subjects for the PR description.
|
||||
git log --format='- %h %s' "$before_sha".."$after_sha" -- "${filtered_files[@]}" > .sync-output/commits.txt
|
||||
|
||||
echo "skip=false" >> "$GITHUB_OUTPUT"
|
||||
echo "after_sha=$after_sha" >> "$GITHUB_OUTPUT"
|
||||
echo "after_short=$(git rev-parse --short "$after_sha")" >> "$GITHUB_OUTPUT"
|
||||
echo "first_subject=$(git log -1 --format=%s "$after_sha")" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Checkout hive-mind for patch application
|
||||
if: steps.diff.outputs.skip != 'true'
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: marolinik/hive-mind
|
||||
ref: master
|
||||
token: ${{ secrets.HIVE_MIND_SYNC_TOKEN }}
|
||||
path: hive-mind
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Apply patch to hive-mind branch + push
|
||||
if: steps.diff.outputs.skip != 'true'
|
||||
working-directory: hive-mind
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.HIVE_MIND_SYNC_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
branch_name="auto-sync/waggle-os-${{ steps.diff.outputs.after_short }}"
|
||||
git config user.name 'waggle-os-sync-bot'
|
||||
git config user.email 'sync-bot@waggle-os.ai'
|
||||
git checkout -b "$branch_name"
|
||||
|
||||
# Apply the filtered patch. The waggle-os layout is identical
|
||||
# under packages/core/src/{mind,harvest}/ so the patch applies
|
||||
# directly without `--directory` rewriting.
|
||||
if ! git apply --3way ../.sync-output/patch.diff; then
|
||||
echo "::error::Patch did not apply cleanly. Manual reconciliation required."
|
||||
echo "::error::Source SHA: ${{ steps.diff.outputs.after_sha }}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git add -A
|
||||
git commit -m "chore(sync): auto-sync from waggle-os@${{ steps.diff.outputs.after_short }}
|
||||
|
||||
Source: marolinik/waggle-os main @ ${{ steps.diff.outputs.after_sha }}
|
||||
Subject: ${{ steps.diff.outputs.first_subject }}
|
||||
|
||||
See PR description for the full list of waggle-os commits in this batch."
|
||||
|
||||
git push origin "$branch_name"
|
||||
|
||||
- name: Open PR on hive-mind
|
||||
if: steps.diff.outputs.skip != 'true'
|
||||
working-directory: hive-mind
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.HIVE_MIND_SYNC_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
branch_name="auto-sync/waggle-os-${{ steps.diff.outputs.after_short }}"
|
||||
commit_list="$(cat ../.sync-output/commits.txt)"
|
||||
|
||||
gh pr create \
|
||||
--repo marolinik/hive-mind \
|
||||
--base master \
|
||||
--head "$branch_name" \
|
||||
--title "auto-sync from waggle-os@${{ steps.diff.outputs.after_short }}: ${{ steps.diff.outputs.first_subject }}" \
|
||||
--body "$(printf 'Automated cross-repo sync — Memory Sync Repair Step 3.2 (waggle-os → hive-mind direction).\n\n## Source\n- Repo: marolinik/waggle-os\n- Branch: main\n- HEAD: %s\n- Workflow run: %s/%s/actions/runs/%s\n\n## Filtering\nThis patch was filtered to exclude paths listed under "NOT Extracted" in EXTRACTION.md:\n- packages/core/src/mind/vault.ts\n- packages/core/src/mind/evolution-runs.ts\n- packages/core/src/mind/execution-traces.ts\n- packages/core/src/mind/improvement-signals.ts\n- packages/core/src/compliance\n\n## Originating commits in this batch\n\n%s\n\n## Review checklist\n- [ ] Patch applied cleanly to hive-mind master without 3-way conflicts\n- [ ] No NOT-extracted paths sneaked through (sanity-check the diff against EXTRACTION.md)\n- [ ] Test deltas (if any) make sense for the OSS surface; no Waggle-specific test fixtures\n- [ ] mind-parity-check on waggle-os side is GREEN before merging this PR (otherwise the sync would re-introduce a regression)' \
|
||||
"${{ steps.diff.outputs.after_sha }}" \
|
||||
"${{ github.server_url }}" \
|
||||
"${{ github.repository }}" \
|
||||
"${{ github.run_id }}" \
|
||||
"$commit_list")"
|
||||
|
||||
- name: Upload patch as artifact (debug aid)
|
||||
if: always() && steps.diff.outputs.skip != 'true'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sync-patch-${{ steps.diff.outputs.after_short }}
|
||||
path: .sync-output/
|
||||
retention-days: 30
|
||||
178
.github/workflows/tauri-build-pr.yml
vendored
Normal file
178
.github/workflows/tauri-build-pr.yml
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
# Waggle — Tauri Build Verification (per-PR + main pushes)
|
||||
#
|
||||
# CC Sesija A §2.4 Task A13 (PM-reframed scope). Verifies the desktop app
|
||||
# builds cleanly on Win + macOS for every PR + main push, so a regression
|
||||
# can't sneak in unnoticed between releases. Distinct from release.yml
|
||||
# which only triggers on `v*` tags + uploads to GitHub Releases (this
|
||||
# workflow only uploads to the workflow run as artifacts for download
|
||||
# verification, no release publishing).
|
||||
#
|
||||
# Exit signal: green CI here means tag-push to release.yml is safe to
|
||||
# pull the trigger on. Red CI here = same investigation flow as release.yml
|
||||
# (Rust compile / Vite build / sidecar bundle / native dep failure).
|
||||
|
||||
name: Tauri Build Verification
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'app/**'
|
||||
- 'apps/web/**'
|
||||
- 'packages/**'
|
||||
- 'scripts/**'
|
||||
- 'package.json'
|
||||
- 'package-lock.json'
|
||||
- '.github/workflows/tauri-build-pr.yml'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'app/**'
|
||||
- 'apps/web/**'
|
||||
- 'packages/**'
|
||||
- 'scripts/**'
|
||||
- 'package.json'
|
||||
- 'package-lock.json'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
verify-windows:
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
|
||||
- name: Setup Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Rust cache
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: app/src-tauri
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Build packages (shared → core → agent → server)
|
||||
run: npm run build:packages
|
||||
|
||||
- name: Build sidecar
|
||||
run: node scripts/build-sidecar.mjs
|
||||
|
||||
- name: Bundle native dependencies
|
||||
run: node scripts/bundle-native-deps.mjs
|
||||
|
||||
- name: Bundle Node.js runtime
|
||||
run: node scripts/bundle-node.mjs
|
||||
|
||||
- name: Stage sidecar dependencies
|
||||
run: node scripts/stage-sidecar-deps.mjs
|
||||
|
||||
- name: Build frontend
|
||||
run: cd apps/web && npx vite build
|
||||
|
||||
- name: Build Tauri (Windows)
|
||||
# @tauri-apps/cli is declared in app/package.json devDeps but is absent
|
||||
# from package-lock.json, so `npm install` never installs it and a bare
|
||||
# `npx tauri` errors "could not determine executable to run". Fetch the
|
||||
# CLI explicitly by package name (npx resolves the win32 binary).
|
||||
run: cd app && npx --yes @tauri-apps/cli@2 build
|
||||
env:
|
||||
# Skip code signing for PR verification — release.yml handles signing
|
||||
# only on tag push.
|
||||
TAURI_PRIVATE_KEY: ''
|
||||
TAURI_KEY_PASSWORD: ''
|
||||
|
||||
- name: Upload Windows artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: waggle-windows-${{ github.sha }}
|
||||
path: |
|
||||
app/src-tauri/target/release/bundle/nsis/*.exe
|
||||
app/src-tauri/target/release/bundle/msi/*.msi
|
||||
if-no-files-found: warn
|
||||
retention-days: 7
|
||||
|
||||
verify-macos:
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
# Per-arch, matching release.yml. Universal builds are rejected by the
|
||||
# bundle scripts (sqlite-vec / onnxruntime / node ship per-arch binaries),
|
||||
# so each arch is staged and built separately.
|
||||
matrix:
|
||||
target: [aarch64-apple-darwin, x86_64-apple-darwin]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
|
||||
- name: Setup Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- name: Rust cache
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: app/src-tauri
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Build packages (shared → core → agent → server)
|
||||
run: npm run build:packages
|
||||
|
||||
- name: Build sidecar
|
||||
run: node scripts/build-sidecar.mjs
|
||||
|
||||
- name: Bundle native dependencies
|
||||
run: node scripts/bundle-native-deps.mjs
|
||||
env:
|
||||
TARGET_ARCH: ${{ matrix.target == 'aarch64-apple-darwin' && 'arm64' || 'x64' }}
|
||||
|
||||
- name: Bundle Node.js runtime
|
||||
run: node scripts/bundle-node.mjs
|
||||
env:
|
||||
TARGET_ARCH: ${{ matrix.target == 'aarch64-apple-darwin' && 'arm64' || 'x64' }}
|
||||
|
||||
- name: Stage sidecar dependencies
|
||||
run: node scripts/stage-sidecar-deps.mjs
|
||||
env:
|
||||
TARGET_ARCH: ${{ matrix.target == 'aarch64-apple-darwin' && 'arm64' || 'x64' }}
|
||||
|
||||
- name: Build frontend
|
||||
run: cd apps/web && npx vite build
|
||||
|
||||
- name: Build Tauri (macOS ${{ matrix.target }})
|
||||
# See verify-windows note: fetch @tauri-apps/cli by package name (absent
|
||||
# from the lockfile). Built per-arch — universal is rejected by the
|
||||
# bundle scripts (per-arch native modules), matching release.yml.
|
||||
run: cd app && npx --yes @tauri-apps/cli@2 build --target ${{ matrix.target }}
|
||||
env:
|
||||
TAURI_PRIVATE_KEY: ''
|
||||
TAURI_KEY_PASSWORD: ''
|
||||
|
||||
- name: Upload macOS artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: waggle-macos-${{ matrix.target }}-${{ github.sha }}
|
||||
path: |
|
||||
app/src-tauri/target/${{ matrix.target }}/release/bundle/dmg/*.dmg
|
||||
app/src-tauri/target/${{ matrix.target }}/release/bundle/macos/*.app
|
||||
if-no-files-found: warn
|
||||
retention-days: 7
|
||||
Reference in New Issue
Block a user