Skip to content
Merged
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
19 changes: 19 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: CI

on:
pull_request:
branches: [development]
push:
branches: [development, main]

jobs:
continuous-integration:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Lint markdown
run: |
for f in $(find . -name "*.md"); do
echo "Checking $f..."
test -s "$f" || echo " WARNING: empty file"
done
21 changes: 21 additions & 0 deletions .github/workflows/coordinated-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Coordinated Release

on:
workflow_dispatch:
inputs:
version:
description: 'SemVer tag (e.g. v1.0.0-alpha)'
required: true
message:
description: 'Tag message'
required: true
default: 'CognitiveOS coordinated release'

jobs:
tag:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: scripts/release-tag.sh "${{ inputs.version }}" "${{ inputs.message }}"
env:
COGNITIVEOS_RELEASE_DIR: /tmp/cognitiveos-releases
54 changes: 54 additions & 0 deletions .github/workflows/healthcheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Health Check

on:
schedule:
- cron: '0 6 * * 1' # Every Monday 06:00 UTC
workflow_dispatch:

jobs:
healthcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Run health check
id: check
run: |
scripts/healthcheck.sh \
--work-dir /tmp/cognitiveos-healthcheck \
--branch main \
--json \
--quiet > /tmp/healthcheck-result.json 2>/dev/null

- name: Upload report
uses: actions/upload-artifact@v4
with:
name: healthcheck-report
path: /tmp/healthcheck-result.json

- name: Check results
id: results
run: |
fail=$(jq -r '.summary.fail' /tmp/healthcheck-result.json 2>/dev/null || echo 1)
if [ "$fail" -gt 0 ]; then
echo "failures=$fail" >> "$GITHUB_OUTPUT"
echo "Issues found: $fail check(s) failed" >> /tmp/healthcheck-summary.txt
jq -r '.checks[] | select(.status == "fail") | " FAIL: \(.name) — \(.detail)"' \
/tmp/healthcheck-result.json >> /tmp/healthcheck-summary.txt
fi

- name: Create issue on failure
if: steps.results.outputs.failures && fromJson(steps.results.outputs.failures) > 0
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const body = fs.readFileSync('/tmp/healthcheck-summary.txt', 'utf8');
const date = new Date().toISOString().split('T')[0];
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `Health check failure — ${date}`,
body: `## Health Check Failed\n\n${body}\n\nSee workflow run: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
labels: ['healthcheck']
});
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ Software Development Life Cycle documentation for the CognitiveOS project.

## Contributing

1. Branch from `development`, not `main`
2. Use topic branches: `feature/<name>`, `fix/<name>`, `bugfix/<name>`
3. Open a PR to `development` with a clear title and description
4. Merge via squash after review
5. Changes flow to `main` via a release PR
Read the guides in `workflow/` before submitting changes:

See the [SDLC repo](https://github.com/CognitiveOS-Project/sdlc) for the full contribution guide, code review standards, and testing strategy.
- [`workflow/contribution-guide.md`](workflow/contribution-guide.md) — full contribution process
- [`workflow/code-review.md`](workflow/code-review.md) — review checklist and expectations
- [`workflow/testing.md`](workflow/testing.md) — testing strategy across all layers
- [`workflow/ci-cd.md`](workflow/ci-cd.md) — CI/CD pipeline definitions

All repos in the CognitiveOS project follow topic-branch flow: branch from `development`, PR to `development`, squash merge, then release PR to `main`.

## Author

Expand Down
81 changes: 52 additions & 29 deletions plan/implementation-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ This plan covers the implementation of all 10 repos in the CognitiveOS-Project o
| `cli` | UI | Go | Bubble Tea TUI frontend |
| `cognitiveos-distro` | Distribution | Shell/Docker | Alpine image builder |
| `cgp-template` | Ecosystem | Template | .cgp skill boilerplate |
| `registry-server` | Infrastructure | Go | .cgp package registry |
| `registry-server` | Infrastructure | Go | .cgp notary proxy (metadata + checksum, no file hosting) |

## Dependency Graph

Expand All @@ -41,7 +41,7 @@ product-specs ──────────────────────
│ │
├── cli ────────── depends on cognitiveosd (socket client)
├── registry-server ─── depends on registry-api spec
├── registry-server ─── depends on registry-api spec, dependency-validation spec
└── cgp-template ─ depends on .cgp format spec

Expand Down Expand Up @@ -135,25 +135,36 @@ cognitiveos-distro ───── depends on all built binaries

**Repos:** `inference`

**Goal:** Working inference engine that can load and run GGUF models, exposed via an Ollama-compatible API.
**Goal:** Working inference engine that can load and run GGUF models, exposed via an Ollama-compatible API. Architecture uses a **vendored llama.cpp C source + thin CGo bridge** — no `llama-cli` subprocess.

| Task | Dependencies | Est. effort |
|------|-------------|-------------|
| llama.cpp cross-compilation for Alpine | None | Medium |
| `POST /api/generate` | None | Medium |
| `POST /api/chat` | None | Medium |
| Vendor `llama.cpp` git submodule (pinned commit) | None | Small |
| `bridge.go` — single `import "C"` file wrapping llama.h API | None | Medium |
| `cgobackend.go` — `CgoBackend` struct implementing `Backend` interface | bridge.go | Medium |
| `loadopts.go` — `LoadOptions{NumCtx, GPULayers, Threads}` | None | Small |
| cmake + gcc toolchain in `Dockerfile.build` | None | Medium |
| Register `--backend cgo` in `cmd/coginfer/main.go` | cgobackend.go | Small |
| `POST /api/generate` — CGo-backed inference | server.go, bridge.go | Medium |
| `POST /api/chat` | generate handler | Small |
| `GET /api/tags` — model listing | None | Small |
| `GET /cognitiveos/status` — resource reporting | inference-api spec | Small |
| `GET /cognitiveos/status` — resource reporting (CGo stats) | inference-api spec | Small |
| `GET /cognitiveos/capabilities` — hardware detection | inference-api spec | Small |
| Wire `LoadOptions` from HTTP request params to `backend.Load()` | server.go | Small |
| Resource negotiation with cognitiveosd | cognitiveosd-api | Medium |
| Idle timeout and auto-unload | None | Small |
| Model swap (unload old, load new) | None | Medium |
| Idle timeout and auto-unload (calls `CgoBackend.Unload()`) | None | Small |
| Model swap (unload old, load new via CGo) | None | Medium |
| Fix `cmd/cograw/main.go` bugs — undefined `llamaBin`, `verifyModel()`, `ramMB` | None | Small |
| Replace `exec.Command("llama-cli")` in cograw with CGo bridge | bridge.go | Medium |
| JSON-RPC 2.0 handler for Raw Model (wrapping bridge calls) | None | Medium |

**Definition of done:**
- Raw Model loads from `/cognitiveos/models/raw/raw-model.gguf`
- `POST /api/generate` produces coherent completions
- Raw Model loads from `/cognitiveos/models/raw/raw-model.gguf` via CGo bridge (no subprocess)
- `POST /api/generate` produces coherent completions via CGo
- Resource usage reported correctly in `/cognitiveos/status`
- Inference engine communicates with cognitiveosd for load/unload
- `CLIBackend` and `--backend cli` flag removed (Phase 5)
- `--backend` defaults to `"cgo"` in production (CGO_ENABLED=1) and `"mock"` when CGO_ENABLED=0

### Phase 4: System Daemon

Expand Down Expand Up @@ -240,26 +251,38 @@ cognitiveos-distro ───── depends on all built binaries

**Repos:** `registry-server`, `cgp-template`

**Goal:** Usable package registry and developer template.

| Task | Dependencies | Est. effort |
|------|-------------|-------------|
| `GET /v1/search` | registry-api | Medium |
| `GET /v1/patches/{name}/{version}` | registry-api | Small |
| `GET .../download` — .cgp binary streaming | registry-api | Medium |
| `POST /v1/patches` — publish with auth | registry-api | Medium |
| `POST .../unlock` — unlock code verification | registry-api | Medium |
| SQLite metadata index | None | Medium |
| Token-based auth | None | Medium |
| cgp-template with sample patch | cgp-format spec | Small |
| cgp-template README and documentation | None | Small |
**Goal:** Usable package notary proxy and developer template.

The registry is a **notary proxy** — it does not host `.cgp` files. Publishers provide a canonical `download_url` and a `sha256` checksum; the registry stores metadata and redirects clients to the download URL. This avoids file storage scaling concerns and allows publishers to host archives on their own infrastructure (GitHub Releases, S3, etc.).

| Task | Dependencies | Est. effort | Status |
|------|-------------|-------------|--------|
| `GET /v1/search` — text search across name, description, tags | registry-api | Small | ✅ Done |
| `GET /v1/patches/{name}` — latest version metadata | registry-api | Small | ✅ Done |
| `GET /v1/patches/{name}/{version}` — version-specific metadata with full manifest | registry-api | Small | ✅ Done |
| `GET /v1/patches/{name}/{version}/download` — HTTP 302 redirect to `download_url` | registry-api | Small | ✅ Done |
| `POST /v1/patches` — JSON-only publish with `manifest`, `sha256`, `download_url` | registry-api | Medium | ✅ Done |
| `PUT /v1/patches/{name}/{version}` — publish new version, URL validated against body | registry-api | Small | ✅ Done |
| A1-A10 publish-time validation (manifest parse, schema, SHA-256 format, dep cycles, file refs, hardware bounds, URL reachability) | dependency-validation spec | Large | ✅ Done |
| Scoped token auth (`publish` scope for POST/PUT, `admin` scope for status/validate) | None | Medium | ✅ Done |
| `PATCH /v1/patches/{name}/{version}/status` — set active/deprecated/buggy | registry-api | Small | ✅ Done |
| `POST /v1/patches/{name}/{version}/validate` — re-run A1-A10 on stored manifest | registry-api | Small | ✅ Done |
| `GET /v1/patches/{name}/dependencies` — dependency tree for a package | registry-api | Small | ✅ Done |
| File-backed store (JSON file, survives restarts, SQLite adapter interface ready) | None | Medium | ✅ Done |
| `POST .../unlock` — unlock code verification | registry-api | Medium | Partial |
| SQLite metadata index (upgrade from file-backed JSON) | None | Medium | Pending |
| cgp-template with sample patch | cgp-format spec | Small | ✅ Done |
| cgp-template README and documentation | None | Small | ✅ Done |
| Registry API spec documenting notary proxy (no file hosting) | — | Small | ✅ Done |
| `publish-cgp.sh` updated for notary pattern (JSON + sha256 + download-url) | — | Small | ✅ Done |

**Definition of done:**
- `cpm search email` returns results from the registry
- `cpm publish ./skill.cgp` uploads to the registry
- `cpm install <name>` downloads and installs from registry
- Unlock code flow works end-to-end
- `cpm init my-skill` creates a valid .cgp skeleton
- `cpm search email` returns results from the registry ✅
- `cpm publish ./skill.cgp --download-url <url>` registers checksum in registry ✅
- `cpm install <name>` downloads from `download_url` after registry redirect ✅
- Unlock code flow works end-to-end ⬜ (stub implementation)
- A1-A10 validation rejects malformed publishes at registry level ✅
- `cpm init my-skill` creates a valid .cgp skeleton ✅

## Build Order with Milestones

Expand Down
21 changes: 15 additions & 6 deletions plan/milestones.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,21 @@
- [ ] Raw Model loads at boot
- [ ] **Demo:** Boot CognitiveOS in QEMU, type a command, get a response

## M6 — Registry Ecosystem
- [ ] `GET /v1/search` returns results
- [ ] `cpm publish ./skill.cgp` uploads to registry
- [ ] `cpm install <name>` downloads from registry
- [ ] Unlock code flow works end-to-end
- [ ] `cpm init my-skill` creates valid .cgp skeleton
## M6 — Registry Ecosystem (Notary Proxy)
- [x] `GET /v1/search` returns results
- [x] `GET /v1/patches/{name}/{version}` returns metadata with sha256 + download_url
- [x] `GET /v1/patches/{name}/{version}/download` redirects to canonical download URL
- [x] `POST /v1/patches` JSON-only publish with manifest + sha256 + download_url
- [x] `PUT /v1/patches/{name}/{version}` publish new version
- [x] A1-A10 publish-time validation (manifest, schema, cycles, file refs, hardware bounds, URLs)
- [x] Scoped token auth (publish/admin)
- [x] File-backed persistence (survives restarts)
- [x] `PATCH .../status`, `POST .../validate`, `GET .../dependencies` endpoints
- [x] `cpm publish ./skill.cgp --download-url <url>` registers in registry
- [x] `cpm install <name>` downloads via registry redirect
- [x] `cpm init my-skill` creates valid .cgp skeleton
- [ ] SQLite backend (upgrade from file-backed JSON)
- [ ] Full unlock code flow end-to-end
- [ ] **Demo:** `cpm search photo` → `cpm install photo-viewer` → AI can show photos

## M7 — v0.1.0 Release
Expand Down
Loading
Loading