Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 45 additions & 42 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# PR + main-branch quality gate.
#
# Runs lint + typecheck + test on both workspaces, plus a schema smoke
# that applies all 9 migrations against a real pgvector container. Audit
# enforces a high-severity ceiling so a CVE-bumping dep can't slip in
# unnoticed.
# that applies every migration in the repo against a real pgvector
# container. Audit enforces a high-severity ceiling so a CVE-bumping
# dep can't slip in unnoticed.
#
# Naming-independent — no secrets, no GHCR/npm push. Release-flow lives
# in release.yml (currently placeholder; activates once OB-30 Block 2
Expand All @@ -12,8 +12,12 @@
name: CI

on:
# Pull-request trigger accepts any base branch so that cluster-fix
# PRs stacked on the test-suite resurrection branch (#35 / #37)
# still run CI. Once #35 merges and the cluster work is done, this
# can return to `branches: [main]`.
pull_request:
branches: [main]
branches: ['**']
push:
branches: [main]

Expand Down Expand Up @@ -41,7 +45,7 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '22'
cache: 'npm'
cache-dependency-path: middleware/package-lock.json

Expand Down Expand Up @@ -75,7 +79,7 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '22'
cache: 'npm'
cache-dependency-path: web-ui/package-lock.json

Expand All @@ -92,8 +96,11 @@ jobs:
run: npm run test

# ------------------------------------------------------------------
# Schema smoke: apply all 9 migrations against pgvector. Catches
# SQL-only regressions before they hit prod-or-OSS-demo deploys.
# Schema smoke: apply every migration in the repo against pgvector.
# Catches SQL-only regressions before they hit prod-or-OSS-demo
# deploys. Domains are listed explicitly in dependency order; files
# inside a domain are applied in lexical (numbered) order, so newly
# added migrations are picked up automatically.
# ------------------------------------------------------------------
schema:
name: schema (migrations on pgvector)
Expand All @@ -112,6 +119,17 @@ jobs:
--health-interval 5s
--health-timeout 3s
--health-retries 20
env:
# Schema domains in apply order. Within each domain, files apply
# in lexical (file-name) order — which matches the numbered
# migration convention. Newline-separated so the shell loop can
# iterate cleanly.
MIGRATION_DOMAINS: |
middleware/packages/harness-knowledge-graph-neon/src/migrations
middleware/src/auth/migrations
middleware/src/plugins/routines/migrations
middleware/src/profileSnapshots/migrations
middleware/src/profileStorage/migrations
steps:
- uses: actions/checkout@v4

Expand All @@ -120,45 +138,30 @@ jobs:
PGPASSWORD=omadia-ci psql -h localhost -U omadia -d omadia \
-c "CREATE EXTENSION IF NOT EXISTS vector;"

- name: Apply 9 migrations in order
- name: Apply all migrations
run: |
set -euo pipefail
declare -a MIGRATIONS=(
"middleware/packages/harness-knowledge-graph-neon/src/migrations/0001_graph_init.sql"
"middleware/src/services/graph/migrations/0002_user_scoping.sql"
"middleware/packages/harness-knowledge-graph-neon/src/migrations/0003_agentic_graph.sql"
"middleware/src/services/graph/migrations/0004_turn_fts.sql"
"middleware/packages/harness-knowledge-graph-neon/src/migrations/0005_turn_embeddings_768.sql"
"middleware/packages/harness-knowledge-graph-neon/src/migrations/0006_embedding_backfill_state.sql"
"middleware/src/services/graph/migrations/0007_verifier_tables.sql"
"middleware/src/services/graph/migrations/0008_teams_attachments.sql"
"middleware/src/plugins/routines/migrations/0001_routines.sql"
)
for m in "${MIGRATIONS[@]}"; do
echo "--- applying $(basename "$m")"
PGPASSWORD=omadia-ci psql -h localhost -U omadia -d omadia \
-v ON_ERROR_STOP=1 -f "$m"
done
while IFS= read -r dir; do
[ -z "$dir" ] && continue
echo "==> domain: $dir"
for f in "$dir"/*.sql; do
echo " applying $(basename "$f")"
PGPASSWORD=omadia-ci psql -h localhost -U omadia -d omadia \
-v ON_ERROR_STOP=1 -f "$f"
done
done <<< "$MIGRATION_DOMAINS"

- name: Re-apply migrations (idempotency check)
run: |
set -euo pipefail
declare -a MIGRATIONS=(
"middleware/packages/harness-knowledge-graph-neon/src/migrations/0001_graph_init.sql"
"middleware/src/services/graph/migrations/0002_user_scoping.sql"
"middleware/packages/harness-knowledge-graph-neon/src/migrations/0003_agentic_graph.sql"
"middleware/src/services/graph/migrations/0004_turn_fts.sql"
"middleware/packages/harness-knowledge-graph-neon/src/migrations/0005_turn_embeddings_768.sql"
"middleware/packages/harness-knowledge-graph-neon/src/migrations/0006_embedding_backfill_state.sql"
"middleware/src/services/graph/migrations/0007_verifier_tables.sql"
"middleware/src/services/graph/migrations/0008_teams_attachments.sql"
"middleware/src/plugins/routines/migrations/0001_routines.sql"
)
for m in "${MIGRATIONS[@]}"; do
PGPASSWORD=omadia-ci psql -h localhost -U omadia -d omadia \
-v ON_ERROR_STOP=1 -f "$m" > /dev/null
echo "✓ idempotent: $(basename "$m")"
done
while IFS= read -r dir; do
[ -z "$dir" ] && continue
for f in "$dir"/*.sql; do
PGPASSWORD=omadia-ci psql -h localhost -U omadia -d omadia \
-v ON_ERROR_STOP=1 -f "$f" > /dev/null
echo "✓ idempotent: $(basename "$f")"
done
done <<< "$MIGRATION_DOMAINS"

# ------------------------------------------------------------------
# Dependency audit. Enforces a "no high or critical" floor — moderate
Expand All @@ -182,7 +185,7 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '22'
cache: 'npm'
cache-dependency-path: ${{ matrix.workspace }}/package-lock.json

Expand Down
39 changes: 39 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,45 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- 2026-05-17 — byte5ai engineering-standards bootstrap (PR #31). Repo is now
on `status: applied` against `byte5ai/engineering-standards`:
- `.github/engineering-standards.yml` as the explicit marker.
- `.hooks/pre-push` blocks direct pushes to `main`/`master` locally.
- `script/setup` enables the hook and runs the npm bootstrap in one step.
- AGENTS.md gained a "Git Workflow & Engineering Standards" section.
- CONTRIBUTING.md documents the pre-push guard and forbids
`Co-Authored-By:` trailers for AI agents.
- Branch protection on `main` is enforced server-side: PR required,
force-push and deletion blocked, all four CI workflows (five contexts
including the `audit` matrix) wired up as required status checks.

GitHub Actions were disabled on the repo since 2026-05-11 and were
reactivated as part of this rollout. The first post-reactivation CI run
surfaced three pre-existing pipeline bugs that had been masked while
Actions were off — they're fixed in the same wave, see *Fixed* below.

### Fixed

- 2026-05-17 — Three pre-existing bugs in the CI pipeline, surfaced once
Actions were reactivated:
- `.github/workflows/ci.yml` pinned `setup-node@v4` to `node-version: '20'`
in three places, but `middleware/package.json` declares
`engines.node ">=22 <23"`. `npm ci` failed with `EBADENGINE` in the
`middleware` and `audit (middleware)` jobs. Bumped to `'22'`.
- The `schema (migrations on pgvector)` job applied a hardcoded list of
nine migrations, four of which had moved or been renumbered as the
knowledge-graph schema grew (`harness-knowledge-graph-neon` now ships
13 migrations, two more domains were added — `auth/`,
`profileSnapshots/`, `profileStorage/`). Replaced the array with a
glob over five migration domains, applied in lexical order. Coverage
grew from 9 to 20 migrations.
- `middleware/src/index.ts:398` triggered `prefer-const` because
eslint's reassignment analysis doesn't trace the forward-reference
assignment ~1300 lines later in `main()`. Documented the intent and
suppressed the rule on that one line.

### Changed

- `docs/CHANGELOG.md` reformatted to follow the Keep-a-Changelog convention.
Expand Down
10 changes: 5 additions & 5 deletions middleware/profiles/minimal-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ id: minimal-dev
name: Minimal Dev
description: In-memory knowledge graph, no verifier. Embeddings are included because orchestrator-extras requires embeddingClient@^1. Add channel plugins via the admin UI after the profile applies.
plugins:
- @omadia/memory
- @omadia/knowledge-graph-inmemory
- @omadia/embeddings
- @omadia/orchestrator-extras
- @omadia/orchestrator
- "@omadia/memory"
- "@omadia/knowledge-graph-inmemory"
- "@omadia/embeddings"
- "@omadia/orchestrator-extras"
- "@omadia/orchestrator"
14 changes: 8 additions & 6 deletions middleware/profiles/production.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ id: production
name: Recommended Production
description: Postgres-backed knowledge graph + verifier + full orchestrator stack. Operator sets DATABASE_URL + ANTHROPIC_API_KEY before profile apply, then installs channel plugins via the admin UI.
plugins:
- @omadia/memory
- @omadia/knowledge-graph-neon
- @omadia/embeddings
- @omadia/orchestrator-extras
- @omadia/verifier
- @omadia/orchestrator
- "@omadia/memory"
- "@omadia/knowledge-graph-neon"
- "@omadia/embeddings"
- "@omadia/orchestrator-extras"
- "@omadia/verifier"
- "@omadia/orchestrator"
- "de.byte5.channel.teams"
- "de.byte5.channel.telegram"
5 changes: 4 additions & 1 deletion middleware/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,10 @@ async function main(): Promise<void> {
// Forward reference for the channel registry — constructed later in boot
// (after the channel-SDK adapters are wired up). The install hooks below
// close over this variable so post-install activations dispatched to a
// channel-kind plugin reach the right runtime once it exists.
// channel-kind plugin reach the right runtime once it exists. The
// assignment happens further down in main() once the channel runtime
// is wired; eslint's prefer-const doesn't trace through that depth.
// eslint-disable-next-line prefer-const
let channelRegistryRef: ChannelRegistry | undefined;

const installService = new InstallService({
Expand Down
8 changes: 4 additions & 4 deletions middleware/test/profileLoader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ describe('profileLoader / object-form entries with config', () => {
'name: With Config',
'description: Mixed string and object plugin entries',
'plugins:',
' - @omadia/memory',
' - id: @omadia/knowledge-graph-neon',
' - "@omadia/memory"',
' - id: "@omadia/knowledge-graph-neon"',
' config:',
' graph_tenant_id: my-tenant',
'',
Expand Down Expand Up @@ -193,8 +193,8 @@ describe('profileLoader / invalid inputs', () => {
'name: x',
'description: x',
'plugins:',
' - @omadia/memory',
' - @omadia/memory',
' - "@omadia/memory"',
' - "@omadia/memory"',
].join('\n'),
);
await assert.rejects(loadProfile(file), /duplicate plugin id/);
Expand Down
8 changes: 4 additions & 4 deletions middleware/test/profilesRouter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ describe('/api/v1/profiles router', () => {
'name: Production',
'description: Full stack',
'plugins:',
' - @omadia/memory',
' - @omadia/embeddings',
' - "@omadia/memory"',
' - "@omadia/embeddings"',
'',
].join('\n'),
);
Expand All @@ -116,7 +116,7 @@ describe('/api/v1/profiles router', () => {
'name: Minimal',
'description: Minimal stack',
'plugins:',
' - @omadia/memory',
' - "@omadia/memory"',
'',
].join('\n'),
);
Expand All @@ -129,7 +129,7 @@ describe('/api/v1/profiles router', () => {
'name: With Config',
'description: Object-form entries',
'plugins:',
' - id: @omadia/memory',
' - id: "@omadia/memory"',
' config:',
' retention_days: 30',
'',
Expand Down
Loading