This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.go]
|
||||
indent_style = tab
|
||||
|
||||
[*.{md,yml,yaml,json,sql}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
@@ -0,0 +1,19 @@
|
||||
# Local development only. Copy to .env.local; never commit real secrets.
|
||||
ASSISTANT_ENV=development
|
||||
ASSISTANT_LOG_LEVEL=info
|
||||
|
||||
POSTGRES_HOST=localhost
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_DB=assistant
|
||||
POSTGRES_SUPERUSER=assistant_bootstrap
|
||||
POSTGRES_SUPERUSER_PASSWORD=CHANGE_ME_LOCAL_ONLY
|
||||
|
||||
NATS_URL=nats://localhost:4222
|
||||
|
||||
# Git / deployment targets (no passwords here)
|
||||
GIT_REMOTE=https://git.cin.su/m/Assistant.git
|
||||
PORTAINER_URL=https://docker.cin.su
|
||||
# Prefer API key stored in OS/env secret store, never Git.
|
||||
PORTAINER_API_KEY=
|
||||
PORTAINER_ENDPOINT_ID=
|
||||
PORTAINER_STACK_NAME=assistant
|
||||
@@ -0,0 +1,21 @@
|
||||
name: CI
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.26.6'
|
||||
- name: Format check
|
||||
run: test -z "$(gofmt -l .)"
|
||||
- name: Architecture Sentinel
|
||||
run: go run ./cmd/devctl check-architecture
|
||||
- name: Test
|
||||
run: go test ./...
|
||||
- name: Vet
|
||||
run: go vet ./...
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
# secrets/local overrides
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
!*.env.example
|
||||
secrets/
|
||||
*.pem
|
||||
*.key
|
||||
*.p12
|
||||
*.pfx
|
||||
|
||||
# Go
|
||||
/bin/
|
||||
/dist/
|
||||
*.test
|
||||
*.out
|
||||
coverage.*
|
||||
|
||||
# IDE/OS
|
||||
.idea/
|
||||
.vscode/
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# runtime data
|
||||
.data/
|
||||
data/
|
||||
logs/
|
||||
tmp/
|
||||
|
||||
# dev task generated artifacts
|
||||
.devctl/
|
||||
@@ -0,0 +1,73 @@
|
||||
# AGENTS.md — Codex operating contract
|
||||
|
||||
You are implementing this repository under a frozen architecture generation. **Capability to edit files is not authority to change architecture.**
|
||||
|
||||
## Mandatory startup sequence
|
||||
|
||||
Before any non-trivial change:
|
||||
|
||||
1. Read `architecture/ARCHITECTURE_CONSTITUTION.md`.
|
||||
2. Read `architecture/CORE_SEMANTIC_MODEL_V1.md`.
|
||||
3. Read `architecture/architecture-registry.yaml` and `architecture/architecture-registry.json`.
|
||||
4. Read `development/CODEX_DEVELOPMENT_CONTRACT.md`.
|
||||
5. Read the active file under `dev/tasks/`.
|
||||
6. Run `go run ./cmd/devctl preflight -task <task-file>` for Tier B+ tasks when available.
|
||||
|
||||
If documents conflict, authority order is:
|
||||
|
||||
`Architecture Constitution > accepted ADR > Architecture Registry > Core Semantic Model > module architecture file > task packet > examples/comments`.
|
||||
|
||||
Do not silently resolve a conflict. Return `BLOCKED_BY_SPEC_GAP` or `BLOCKED_BY_ARCHITECTURE_GAP`.
|
||||
|
||||
## Hard prohibitions
|
||||
|
||||
- NO cross-module direct DB access.
|
||||
- NO cross-owner SQL JOIN/FK/view/trigger by default.
|
||||
- NO direct external mutation outside Commit/Executor boundary.
|
||||
- NO model/provider call outside cognitive adapter/gateway boundaries.
|
||||
- NO semantic durable timer implemented as `time.After`, unmanaged goroutine or in-memory queue.
|
||||
- NO cross-module correctness depending on shared mutex, pointer, filesystem or process-local transaction.
|
||||
- NO giant `common`, `shared`, generic `Entity`, generic `Status`, generic `Manager`, `ServiceLocator`, or `map[string]any` as a substitute for Core semantics.
|
||||
- NO provider/runtime types in domain packages.
|
||||
- NO weakening tests, architecture lints, DB ACLs, or guardrails to make a task pass.
|
||||
- NO new third-party dependency in an ordinary feature task.
|
||||
- NO protected-path modification unless the task explicitly grants Tier E authority.
|
||||
- NO reading/copying literal passwords from other repositories into this repository.
|
||||
- NO production secret in source, task packet, commit message, logs or tests.
|
||||
|
||||
## Codex freedom
|
||||
|
||||
Inside the declared owner/module and allowed paths, choose ordinary local implementation details freely. Prefer explicit, typed, boring Go over reflection, metaprogramming or framework tricks.
|
||||
|
||||
Semantic duplication is preferable to false abstraction. Shared technical mechanisms may live under `platform/`; shared domain meaning may not.
|
||||
|
||||
## When blocked
|
||||
|
||||
Valid terminal states include:
|
||||
|
||||
- `BLOCKED_BY_SPEC_GAP`
|
||||
- `BLOCKED_BY_ARCHITECTURE_GAP`
|
||||
- `BLOCKED_BY_MISSING_CAPABILITY`
|
||||
- `BLOCKED_BY_CONFLICT`
|
||||
- `REQUIRES_MIGRATION_DECISION`
|
||||
|
||||
Never “make it work somehow” by violating a boundary.
|
||||
|
||||
## Git and deployment
|
||||
|
||||
- Canonical remote: `https://git.cin.su/m/Assistant.git`.
|
||||
- Target deployment control plane: `https://docker.cin.su` (Portainer).
|
||||
- Use configured credential helpers first; never echo secrets.
|
||||
- If push/deploy credentials are unavailable, ask the user for the minimum needed access.
|
||||
- Ordinary Codex work happens on a branch/worktree, never directly on protected `main`.
|
||||
|
||||
## Required completion report
|
||||
|
||||
State:
|
||||
- task ID/revision;
|
||||
- changed paths/modules;
|
||||
- contracts/schemas/events/dependencies/privileges touched;
|
||||
- tests actually executed;
|
||||
- assumptions;
|
||||
- findings not changed;
|
||||
- gaps or limitations.
|
||||
@@ -0,0 +1,15 @@
|
||||
.PHONY: check test vet dev-up dev-down
|
||||
check:
|
||||
go run ./cmd/devctl check-architecture
|
||||
|
||||
test:
|
||||
go test ./...
|
||||
|
||||
vet:
|
||||
go vet ./...
|
||||
|
||||
dev-up:
|
||||
docker compose -f deploy/docker-compose.dev.yml up -d --build
|
||||
|
||||
dev-down:
|
||||
docker compose -f deploy/docker-compose.dev.yml down
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"project": "Assistant",
|
||||
"local_expected_path": "Z:\\mst\\codex\\assistent",
|
||||
"git_remote": "https://git.cin.su/m/Assistant.git",
|
||||
"deployment_control_plane": "https://docker.cin.su",
|
||||
"deployment_kind": "Portainer",
|
||||
"semantic_generation": 1,
|
||||
"architecture_generation": 1,
|
||||
"go_baseline": "1.26.x",
|
||||
"postgres_baseline": "18.6",
|
||||
"first_task": "dev/tasks/DEV-000001-bootstrap-guardrails.json"
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
.env.example
|
||||
adapters/models/deterministic.go
|
||||
adapters/models/doc.go
|
||||
adapters/nats/doc.go
|
||||
adapters/portainer/doc.go
|
||||
adapters/postgres/authority_repository.go
|
||||
adapters/postgres/capability_repository.go
|
||||
adapters/postgres/commit_repository.go
|
||||
adapters/postgres/continuity_repository.go
|
||||
adapters/postgres/doc.go
|
||||
adapters/postgres/identity_repository.go
|
||||
adapters/postgres/situation_repository.go
|
||||
adapters/postgres/work_repository.go
|
||||
adapters/temporal/doc.go
|
||||
adapters/testexecutor/executor.go
|
||||
AGENTS.md
|
||||
architecture/adrs/ADR-0001-extractable-modular-architecture.md
|
||||
architecture/adrs/ADR-0002-codex-is-implementation-capability.md
|
||||
architecture/adrs/README.md
|
||||
architecture/ARCHITECTURE_CONSTITUTION.md
|
||||
architecture/architecture-registry.json
|
||||
architecture/architecture-registry.md
|
||||
architecture/architecture-registry.yaml
|
||||
architecture/CORE_SEMANTIC_MODEL_V1.md
|
||||
architecture/DECISION_CONSOLIDATION_V1.md
|
||||
architecture/README.md
|
||||
architecture/reference/FOUNDATION_FREEZE_PACK_V1.docx
|
||||
architecture/reference/FOUNDATION_FREEZE_PACK_V1.md
|
||||
architecture/UNRESOLVED_QUESTIONS.md
|
||||
architecture/WALKING_SKELETON_SPEC.md
|
||||
ci/architecture/protected-paths.txt
|
||||
ci/architecture/README.md
|
||||
cmd/cognitive-worker/main.go
|
||||
cmd/commit-runtime/main.go
|
||||
cmd/continuity-runtime/main.go
|
||||
cmd/core-runtime/main.go
|
||||
cmd/devctl/architecture_test.go
|
||||
cmd/devctl/main.go
|
||||
contracts/artifact/doc.go
|
||||
contracts/artifact/types.go
|
||||
contracts/authority/doc.go
|
||||
contracts/authority/types.go
|
||||
contracts/capability/doc.go
|
||||
contracts/capability/types.go
|
||||
contracts/commit/doc.go
|
||||
contracts/commit/types.go
|
||||
contracts/continuity/doc.go
|
||||
contracts/continuity/types.go
|
||||
contracts/epistemics/doc.go
|
||||
contracts/epistemics/types.go
|
||||
contracts/identity/doc.go
|
||||
contracts/identity/session.go
|
||||
contracts/identity/types.go
|
||||
contracts/situation/doc.go
|
||||
contracts/situation/types.go
|
||||
contracts/work/doc.go
|
||||
contracts/work/types.go
|
||||
database/bootstrap/001_roles_and_schemas.sql
|
||||
database/migrations/001_bootstrap_creator_authority.sql
|
||||
database/migrations/002_continuity_prospective_items.sql
|
||||
database/migrations/003_situation_focus_bindings.sql
|
||||
database/migrations/004_work_tasks.sql
|
||||
database/migrations/005_commit_actions.sql
|
||||
database/migrations/006_capability_health.sql
|
||||
database/migrations/007_capability_health_v2.sql
|
||||
database/migrations/artifact/README.md
|
||||
database/migrations/authority/README.md
|
||||
database/migrations/capability/README.md
|
||||
database/migrations/commit/README.md
|
||||
database/migrations/continuity/README.md
|
||||
database/migrations/epistemics/README.md
|
||||
database/migrations/identity/README.md
|
||||
database/migrations/situation/README.md
|
||||
database/migrations/work/README.md
|
||||
database/README.md
|
||||
deploy/docker-compose.dev.yml
|
||||
deploy/docker-compose.prod.yml
|
||||
deploy/images/002_owner_passwords.sh
|
||||
deploy/images/postgres.Dockerfile
|
||||
deploy/images/runtime.Dockerfile
|
||||
deploy/PORTAINER.md
|
||||
dev/README.md
|
||||
dev/task-packet.schema.json
|
||||
dev/tasks/DEV-000001-bootstrap-guardrails.json
|
||||
dev/tasks/DEV-000002-walking-skeleton-focus-isolation.json
|
||||
dev/tasks/DEV-000003-production-docker-stack.json
|
||||
dev/tasks/DEV-000004-bootstrap-creator-authority.json
|
||||
dev/tasks/DEV-000005-safe-action-commit.json
|
||||
dev/tasks/DEV-000006-durable-prospective-memory.json
|
||||
dev/tasks/DEV-000007-deterministic-cognitive-fake.json
|
||||
dev/tasks/DEV-000008-continuity-postgres-api.json
|
||||
dev/tasks/DEV-000009-situation-focus-postgres-api.json
|
||||
dev/tasks/DEV-000010-work-task-postgres-api.json
|
||||
dev/tasks/DEV-000011-focus-guarded-task-commit.json
|
||||
dev/tasks/DEV-000012-commit-postgres-api.json
|
||||
dev/tasks/DEV-000013-topology-equivalence.json
|
||||
dev/tasks/DEV-000014-no-llm-degraded-capability.json
|
||||
dev/tasks/DEV-000015-capability-semantic-evolution.json
|
||||
dev/tasks/DEV-000016-owner-acl-negative-test.json
|
||||
dev/tasks/DEV-000017-runtime-authorized-action-validation.json
|
||||
dev/tasks/DEV-000018-foundation-exit-audit.json
|
||||
dev/tasks/DEV-000019-creator-authentication.json
|
||||
dev/tasks/DEV-000020-test-executor-reconciliation.json
|
||||
dev/tasks/DEV-000021-architecture-sentinel-negative-tests.json
|
||||
dev/tasks/DEV-000022-remove-commit-identity-drift.json
|
||||
dev/tasks/DEV-000023-remote-topology-harness.json
|
||||
development/CODEX_DEVELOPMENT_CONTRACT.md
|
||||
development/CREDENTIAL_POLICY.md
|
||||
development/README.md
|
||||
docs/CREDENTIALS_AND_SECRETS.md
|
||||
docs/DEPLOYMENT.md
|
||||
docs/FOUNDATION_EXIT_AUDIT.md
|
||||
docs/LOCAL_PATH_AND_RESOURCES.md
|
||||
docs/MIGRATIONS.md
|
||||
go.mod
|
||||
go.sum
|
||||
Makefile
|
||||
modules/artifact/application/doc.go
|
||||
modules/artifact/domain/doc.go
|
||||
modules/artifact/module.go
|
||||
modules/artifact/ports/doc.go
|
||||
modules/artifact/README.arch.md
|
||||
modules/authority/application/doc.go
|
||||
modules/authority/domain/creator.go
|
||||
modules/authority/domain/doc.go
|
||||
modules/authority/domain/grant.go
|
||||
modules/authority/module.go
|
||||
modules/authority/ports/doc.go
|
||||
modules/authority/README.arch.md
|
||||
modules/capability/application/doc.go
|
||||
modules/capability/domain/doc.go
|
||||
modules/capability/domain/health.go
|
||||
modules/capability/module.go
|
||||
modules/capability/ports/doc.go
|
||||
modules/capability/ports/repository.go
|
||||
modules/capability/README.arch.md
|
||||
modules/commit/application/doc.go
|
||||
modules/commit/domain/commit.go
|
||||
modules/commit/domain/doc.go
|
||||
modules/commit/module.go
|
||||
modules/commit/ports/doc.go
|
||||
modules/commit/ports/executor.go
|
||||
modules/commit/README.arch.md
|
||||
modules/continuity/application/doc.go
|
||||
modules/continuity/domain/doc.go
|
||||
modules/continuity/domain/prospective.go
|
||||
modules/continuity/module.go
|
||||
modules/continuity/ports/doc.go
|
||||
modules/continuity/ports/repository.go
|
||||
modules/continuity/README.arch.md
|
||||
modules/epistemics/application/doc.go
|
||||
modules/epistemics/domain/doc.go
|
||||
modules/epistemics/module.go
|
||||
modules/epistemics/ports/doc.go
|
||||
modules/epistemics/README.arch.md
|
||||
modules/identity/application/doc.go
|
||||
modules/identity/domain/creator.go
|
||||
modules/identity/domain/doc.go
|
||||
modules/identity/domain/session.go
|
||||
modules/identity/module.go
|
||||
modules/identity/ports/doc.go
|
||||
modules/identity/README.arch.md
|
||||
modules/situation/application/doc.go
|
||||
modules/situation/domain/doc.go
|
||||
modules/situation/domain/focus.go
|
||||
modules/situation/module.go
|
||||
modules/situation/ports/doc.go
|
||||
modules/situation/README.arch.md
|
||||
modules/work/application/doc.go
|
||||
modules/work/domain/doc.go
|
||||
modules/work/domain/task.go
|
||||
modules/work/module.go
|
||||
modules/work/ports/doc.go
|
||||
modules/work/README.arch.md
|
||||
ops/RUNBOOK.md
|
||||
platform/clock/clock.go
|
||||
platform/errors/errors.go
|
||||
platform/ids/ids.go
|
||||
platform/README.md
|
||||
PROJECT_MANIFEST.json
|
||||
PROJECT_TREE.txt
|
||||
README.md
|
||||
runtime/health/server.go
|
||||
scripts/bootstrap.ps1
|
||||
scripts/bootstrap.sh
|
||||
security/README.md
|
||||
START_HERE_CODEX.md
|
||||
tests/action_commit/safe_commit_test.go
|
||||
tests/action_commit/test_executor_reconciliation_test.go
|
||||
tests/architecture/registry_test.go
|
||||
tests/cognitive_fake/deterministic_test.go
|
||||
tests/creator_auth/session_test.go
|
||||
tests/creator_authority/creator_authority_test.go
|
||||
tests/degraded_continuity/capability_health_test.go
|
||||
tests/owner_acl/verify.ps1
|
||||
tests/prospective_memory/recovery_test.go
|
||||
tests/semantic_evolution/capability_health_v2_test.go
|
||||
tests/topology_equivalence/commit_test.go
|
||||
tests/topology_equivalence/focus_test.go
|
||||
tests/topology_equivalence/verify-remote.ps1
|
||||
tests/walking_skeleton/focus_isolation_test.go
|
||||
tests/walking_skeleton/README.md
|
||||
@@ -0,0 +1,52 @@
|
||||
# Assistant
|
||||
|
||||
Long-lived, evolvable personal/work assistant. This repository is intentionally designed for implementation primarily through Codex while preserving strict semantic, authority, storage and deployment boundaries.
|
||||
|
||||
## Fixed project coordinates
|
||||
|
||||
- **Expected local project folder:** `Z:\mst\codex\assistent`
|
||||
- **Git remote:** `https://git.cin.su/m/Assistant.git`
|
||||
- **Deployment control plane / Portainer:** `https://docker.cin.su`
|
||||
- **Go baseline:** 1.26.x
|
||||
- **PostgreSQL baseline:** 18.6
|
||||
- **Semantic generation:** 1
|
||||
- **Architecture generation:** 1
|
||||
|
||||
The repository at `git.cin.su/m/Assistant` was externally reachable and empty when this bootstrap pack was created. `docker.cin.su` was externally reachable as Portainer.
|
||||
|
||||
## First rule
|
||||
|
||||
Read `AGENTS.md`, then `architecture/ARCHITECTURE_CONSTITUTION.md`, then the current task packet under `dev/tasks/` **before editing code**.
|
||||
|
||||
## Bootstrap on Windows
|
||||
|
||||
```powershell
|
||||
Set-Location Z:\mst\codex\assistent
|
||||
powershell -ExecutionPolicy Bypass -File .\scripts\bootstrap.ps1
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
```powershell
|
||||
go run .\cmd\devctl doctor
|
||||
go run .\cmd\devctl check-architecture
|
||||
go test ./...
|
||||
docker compose -f deploy/docker-compose.dev.yml up -d --build
|
||||
```
|
||||
|
||||
## Credentials
|
||||
|
||||
Do **not** commit passwords, API keys, tokens or copied credentials from sibling projects.
|
||||
|
||||
Codex should try, in this order:
|
||||
|
||||
1. existing OS/Git/Docker credential helpers without printing the secret;
|
||||
2. existing environment variables / secret stores already configured for this machine;
|
||||
3. inspect sibling projects only for non-secret deployment conventions, endpoint names and environment-variable names;
|
||||
4. if actual credentials are still unavailable, ask the user.
|
||||
|
||||
See `docs/CREDENTIALS_AND_SECRETS.md`.
|
||||
|
||||
## V1 non-goals
|
||||
|
||||
V1 must not implement autonomous self-modification, global collective learning, a universal ontology engine, Kubernetes as a requirement, custom consensus, autonomous plugin installation, full robotics/control-loop infrastructure, or a multi-user federation platform. Preserve extension paths; do not materialize speculative systems.
|
||||
@@ -0,0 +1,29 @@
|
||||
# START HERE — CODEX
|
||||
|
||||
This folder is intended to be copied/extracted to:
|
||||
|
||||
`Z:\mst\codex\assistent`
|
||||
|
||||
Do not begin feature implementation immediately.
|
||||
|
||||
## Step 1
|
||||
Read `AGENTS.md` and the architecture authority files it references.
|
||||
|
||||
## Step 2
|
||||
Run Windows bootstrap if applicable:
|
||||
|
||||
```powershell
|
||||
powershell -ExecutionPolicy Bypass -File .\scripts\bootstrap.ps1
|
||||
```
|
||||
|
||||
## Step 3
|
||||
Execute task packet `dev/tasks/DEV-000001-bootstrap-guardrails.json` only.
|
||||
|
||||
The first task validates the guardrail factory itself. Do not start the Assistant semantic features before this passes.
|
||||
|
||||
## Access
|
||||
|
||||
Git remote is already known: `https://git.cin.su/m/Assistant.git`.
|
||||
Deployment target is Portainer: `https://docker.cin.su`.
|
||||
|
||||
Use existing Git/Docker/OS credential helpers if already configured. Never reveal them. If write/deploy access is absent, request the minimum credentials from the user rather than mining plaintext secrets from other project trees.
|
||||
@@ -0,0 +1,33 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
|
||||
"git.cin.su/m/Assistant/contracts/capability"
|
||||
commitcontract "git.cin.su/m/Assistant/contracts/commit"
|
||||
"git.cin.su/m/Assistant/contracts/identity"
|
||||
"git.cin.su/m/Assistant/contracts/work"
|
||||
"git.cin.su/m/Assistant/platform/ids"
|
||||
)
|
||||
|
||||
// DeterministicRequest is already target-bound. The adapter performs no text
|
||||
// routing and emits a candidate only; Commit remains the execution boundary.
|
||||
type DeterministicRequest struct {
|
||||
ActorID identity.ActorID
|
||||
CapabilityID capability.CapabilityID
|
||||
Target work.TaskTarget
|
||||
Operation commitcontract.ExternalOperation
|
||||
}
|
||||
|
||||
type Candidate struct {
|
||||
Proposal commitcontract.ActionProposal
|
||||
Seed string
|
||||
}
|
||||
|
||||
func Propose(request DeterministicRequest) Candidate {
|
||||
seed := string(request.ActorID) + "|" + string(request.CapabilityID) + "|" + string(request.Target.TaskID) + "|" + string(request.Target.GoalID) + "|" + string(request.Target.ScopeID) + "|" + string(request.Operation)
|
||||
digest := sha256.Sum256([]byte(seed))
|
||||
intent := commitcontract.ActionIntentID(ids.ID(hex.EncodeToString(digest[:16])))
|
||||
return Candidate{Seed: hex.EncodeToString(digest[:]), Proposal: commitcontract.ActionProposal{IntentID: intent, ActorID: request.ActorID, CapabilityID: request.CapabilityID, Target: request.Target, Operation: request.Operation, State: commitcontract.ActionProposed}}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package models
|
||||
|
||||
// Package models: Cognitive provider adapters. Provider output is candidate/proposal, never direct canonical truth/action.
|
||||
@@ -0,0 +1,3 @@
|
||||
package nats
|
||||
|
||||
// Package nats: NATS integration transport adapter. NATS is not canonical event history.
|
||||
@@ -0,0 +1,3 @@
|
||||
package portainer
|
||||
|
||||
// Package portainer: Deployment adapter/tooling only; never imported by semantic domain modules.
|
||||
@@ -0,0 +1,29 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.cin.su/m/Assistant/contracts/authority"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type AuthorityRepository struct{ pool *pgxpool.Pool }
|
||||
|
||||
func OpenAuthority(ctx context.Context, c ContinuityConfig) (*AuthorityRepository, error) {
|
||||
p, e := pgxpool.New(ctx, fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", c.Host, c.Port, c.Database, c.User, c.Password))
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return &AuthorityRepository{p}, nil
|
||||
}
|
||||
func (r *AuthorityRepository) Close() { r.pool.Close() }
|
||||
func (r *AuthorityRepository) LoadGrant(ctx context.Context, id authority.GrantID) (authority.AuthorityGrant, authority.Scope, error) {
|
||||
var grant authority.AuthorityGrant
|
||||
var scope authority.Scope
|
||||
err := r.pool.QueryRow(ctx, `SELECT g.grant_id, g.actor_id, g.principal_id, g.scope_id, g.grant_class, g.revision, g.active, s.scope_id, s.global_scope, s.label FROM authority.authority_grants g JOIN authority.scopes s ON s.scope_id=g.scope_id WHERE g.grant_id=$1`, id).Scan(&grant.ID, &grant.ActorID, &grant.PrincipalID, &grant.ScopeID, &grant.Class, &grant.Revision, &grant.Active, &scope.ID, &scope.Global, &scope.Label)
|
||||
if err != nil {
|
||||
return authority.AuthorityGrant{}, authority.Scope{}, fmt.Errorf("load authority grant: %w", err)
|
||||
}
|
||||
return grant, scope, nil
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.cin.su/m/Assistant/contracts/capability"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
var ErrCapabilityHealthNotFound = errors.New("capability health not found")
|
||||
|
||||
type CapabilityRepository struct{ pool *pgxpool.Pool }
|
||||
|
||||
func OpenCapability(ctx context.Context, config ContinuityConfig) (*CapabilityRepository, error) {
|
||||
dsn := fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", config.Host, config.Port, config.Database, config.User, config.Password)
|
||||
pool, err := pgxpool.New(ctx, dsn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &CapabilityRepository{pool: pool}, nil
|
||||
}
|
||||
|
||||
func (r *CapabilityRepository) Close() { r.pool.Close() }
|
||||
|
||||
func (r *CapabilityRepository) SaveHealth(ctx context.Context, health capability.Health) error {
|
||||
_, err := r.pool.Exec(ctx, `INSERT INTO capability.health (capability_id, state, reason, revision, semantic_version, observed_at_unix_millis) VALUES ($1,$2,$3,$4,$5,$6) ON CONFLICT (capability_id) DO UPDATE SET state=EXCLUDED.state, reason=EXCLUDED.reason, revision=EXCLUDED.revision, semantic_version=EXCLUDED.semantic_version, observed_at_unix_millis=EXCLUDED.observed_at_unix_millis WHERE capability.health.revision < EXCLUDED.revision`, health.CapabilityID, health.State, health.Reason, health.Revision, health.SemanticVersion, health.ObservedAtUnixMillis)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CapabilityRepository) LoadHealth(ctx context.Context, id capability.CapabilityID) (capability.Health, error) {
|
||||
var health capability.Health
|
||||
err := r.pool.QueryRow(ctx, `SELECT capability_id, state, reason, revision, semantic_version, observed_at_unix_millis FROM capability.health WHERE capability_id=$1`, id).Scan(&health.CapabilityID, &health.State, &health.Reason, &health.Revision, &health.SemanticVersion, &health.ObservedAtUnixMillis)
|
||||
if err != nil {
|
||||
return capability.Health{}, fmt.Errorf("load capability health: %w", err)
|
||||
}
|
||||
return health, nil
|
||||
}
|
||||
|
||||
func (r *CapabilityRepository) RebuildHealthProjection(ctx context.Context) (int64, error) {
|
||||
tx, err := r.pool.Begin(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer tx.Rollback(ctx)
|
||||
if _, err = tx.Exec(ctx, `DELETE FROM capability.health_projection`); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
result, err := tx.Exec(ctx, `INSERT INTO capability.health_projection (capability_id, state, reason, revision, semantic_version, observed_at_unix_millis) SELECT capability_id, state, reason, revision, semantic_version, observed_at_unix_millis FROM capability.health`)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err = tx.Commit(ctx); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
commitcontract "git.cin.su/m/Assistant/contracts/commit"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type CommitRepository struct{ pool *pgxpool.Pool }
|
||||
|
||||
func OpenCommit(ctx context.Context, c ContinuityConfig) (*CommitRepository, error) {
|
||||
p, e := pgxpool.New(ctx, fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", c.Host, c.Port, c.Database, c.User, c.Password))
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return &CommitRepository{p}, nil
|
||||
}
|
||||
func (r *CommitRepository) Close() { r.pool.Close() }
|
||||
func (r *CommitRepository) SaveAuthorized(ctx context.Context, a commitcontract.AuthorizedAction) error {
|
||||
_, e := r.pool.Exec(ctx, `INSERT INTO commit.authorized_actions (authorized_action_id,action_intent_id,state,revision) VALUES ($1,$2,$3,1) ON CONFLICT (authorized_action_id) DO NOTHING`, a.ID, a.Proposal.IntentID, a.State)
|
||||
return e
|
||||
}
|
||||
func (r *CommitRepository) SaveAttempt(ctx context.Context, a commitcontract.ActionAttempt) error {
|
||||
_, e := r.pool.Exec(ctx, `INSERT INTO commit.action_attempts (action_attempt_id,authorized_action_id,action_intent_id,state) VALUES ($1,$2,$3,$4) ON CONFLICT (action_attempt_id) DO NOTHING`, a.ID, a.AuthorizedID, a.IntentID, a.State)
|
||||
return e
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.cin.su/m/Assistant/contracts/continuity"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
var ErrProspectiveNotFound = errors.New("prospective item not found")
|
||||
|
||||
type ContinuityConfig struct{ Host, Port, Database, User, Password string }
|
||||
type ContinuityRepository struct{ pool *pgxpool.Pool }
|
||||
|
||||
func OpenContinuity(ctx context.Context, config ContinuityConfig) (*ContinuityRepository, error) {
|
||||
dsn := fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", config.Host, config.Port, config.Database, config.User, config.Password)
|
||||
pool, err := pgxpool.New(ctx, dsn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ContinuityRepository{pool: pool}, nil
|
||||
}
|
||||
func (r *ContinuityRepository) Close() { r.pool.Close() }
|
||||
func (r *ContinuityRepository) Save(ctx context.Context, item continuity.ProspectiveItem) error {
|
||||
_, err := r.pool.Exec(ctx, `INSERT INTO continuity.prospective_items (prospective_item_id, commitment_id, owner_principal_id, scope_id, goal_id, trigger_at_unix_millis, state, revision) VALUES ($1,$2,$3,$4,$5,$6,$7,$8) ON CONFLICT (prospective_item_id) DO UPDATE SET state=EXCLUDED.state, revision=EXCLUDED.revision`, item.ID, item.CommitmentID, item.OwnerPrincipalID, item.ScopeID, item.GoalID, item.TriggerAtUnixMillis, item.State, item.Revision)
|
||||
return err
|
||||
}
|
||||
func (r *ContinuityRepository) Load(ctx context.Context, id continuity.ProspectiveItemID) (continuity.ProspectiveItem, error) {
|
||||
var item continuity.ProspectiveItem
|
||||
err := r.pool.QueryRow(ctx, `SELECT prospective_item_id, commitment_id, owner_principal_id, scope_id, goal_id, trigger_at_unix_millis, state, revision FROM continuity.prospective_items WHERE prospective_item_id=$1`, id).Scan(&item.ID, &item.CommitmentID, &item.OwnerPrincipalID, &item.ScopeID, &item.GoalID, &item.TriggerAtUnixMillis, &item.State, &item.Revision)
|
||||
if err != nil {
|
||||
return continuity.ProspectiveItem{}, fmt.Errorf("load prospective item: %w", err)
|
||||
}
|
||||
return item, nil
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package postgres
|
||||
|
||||
// Package postgres: PostgreSQL implementations of owner persistence ports. No domain meaning belongs here.
|
||||
@@ -0,0 +1,28 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.cin.su/m/Assistant/contracts/identity"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type IdentityRepository struct{ pool *pgxpool.Pool }
|
||||
|
||||
func OpenIdentity(ctx context.Context, config ContinuityConfig) (*IdentityRepository, error) {
|
||||
pool, err := pgxpool.New(ctx, fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", config.Host, config.Port, config.Database, config.User, config.Password))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &IdentityRepository{pool: pool}, nil
|
||||
}
|
||||
func (r *IdentityRepository) Close() { r.pool.Close() }
|
||||
func (r *IdentityRepository) LoadBinding(ctx context.Context, actor identity.ActorID, principal identity.PrincipalID) (identity.PrincipalBinding, error) {
|
||||
var binding identity.PrincipalBinding
|
||||
err := r.pool.QueryRow(ctx, `SELECT actor_id, principal_id, active FROM identity.principal_bindings WHERE actor_id=$1 AND principal_id=$2`, actor, principal).Scan(&binding.ActorID, &binding.PrincipalID, &binding.Active)
|
||||
if err != nil {
|
||||
return identity.PrincipalBinding{}, fmt.Errorf("load identity binding: %w", err)
|
||||
}
|
||||
return binding, nil
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.cin.su/m/Assistant/contracts/situation"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type SituationRepository struct{ pool *pgxpool.Pool }
|
||||
|
||||
func OpenSituation(ctx context.Context, config ContinuityConfig) (*SituationRepository, error) {
|
||||
dsn := fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", config.Host, config.Port, config.Database, config.User, config.Password)
|
||||
pool, err := pgxpool.New(ctx, dsn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &SituationRepository{pool: pool}, nil
|
||||
}
|
||||
func (r *SituationRepository) Close() { r.pool.Close() }
|
||||
func (r *SituationRepository) Save(ctx context.Context, binding situation.FocusBinding) error {
|
||||
_, err := r.pool.Exec(ctx, `INSERT INTO situation.focus_bindings (focus_binding_id, actor_id, session_id, workspace_id, project_id, goal_id, scope_id, active) VALUES ($1,$2,$3,$4,$5,$6,$7,$8) ON CONFLICT (focus_binding_id) DO UPDATE SET active=EXCLUDED.active`, binding.ID, binding.ActorID, binding.SessionID, binding.Workspace, binding.ProjectID, binding.GoalID, binding.ScopeID, binding.Active)
|
||||
return err
|
||||
}
|
||||
func (r *SituationRepository) ByRuntime(ctx context.Context, runtime situation.RuntimeBinding) ([]situation.FocusBinding, error) {
|
||||
rows, err := r.pool.Query(ctx, `SELECT focus_binding_id, actor_id, session_id, workspace_id, project_id, goal_id, scope_id, active FROM situation.focus_bindings WHERE session_id=$1 AND workspace_id=$2`, runtime.SessionID, runtime.Workspace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var bindings []situation.FocusBinding
|
||||
for rows.Next() {
|
||||
var binding situation.FocusBinding
|
||||
if err := rows.Scan(&binding.ID, &binding.ActorID, &binding.SessionID, &binding.Workspace, &binding.ProjectID, &binding.GoalID, &binding.ScopeID, &binding.Active); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bindings = append(bindings, binding)
|
||||
}
|
||||
return bindings, rows.Err()
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.cin.su/m/Assistant/contracts/work"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type WorkRepository struct{ pool *pgxpool.Pool }
|
||||
|
||||
func OpenWork(ctx context.Context, config ContinuityConfig) (*WorkRepository, error) {
|
||||
dsn := fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", config.Host, config.Port, config.Database, config.User, config.Password)
|
||||
pool, err := pgxpool.New(ctx, dsn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &WorkRepository{pool}, nil
|
||||
}
|
||||
func (r *WorkRepository) Close() { r.pool.Close() }
|
||||
func (r *WorkRepository) Create(ctx context.Context, target work.TaskTarget) error {
|
||||
_, err := r.pool.Exec(ctx, `INSERT INTO work.tasks (task_id,goal_id,scope_id,revision) VALUES ($1,$2,$3,$4) ON CONFLICT (task_id) DO NOTHING`, target.TaskID, target.GoalID, target.ScopeID, target.Revision)
|
||||
return err
|
||||
}
|
||||
func (r *WorkRepository) Commit(ctx context.Context, target work.TaskTarget) (work.TaskRevision, error) {
|
||||
var revision work.TaskRevision
|
||||
err := r.pool.QueryRow(ctx, `UPDATE work.tasks SET revision=revision+1 WHERE task_id=$1 AND goal_id=$2 AND scope_id=$3 AND revision=$4 RETURNING revision`, target.TaskID, target.GoalID, target.ScopeID, target.Revision).Scan(&revision)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("commit task: %w", err)
|
||||
}
|
||||
return revision, nil
|
||||
}
|
||||
func (r *WorkRepository) Load(ctx context.Context, id work.TaskID) (work.TaskTarget, error) {
|
||||
var target work.TaskTarget
|
||||
err := r.pool.QueryRow(ctx, `SELECT task_id, goal_id, scope_id, revision FROM work.tasks WHERE task_id=$1`, id).Scan(&target.TaskID, &target.GoalID, &target.ScopeID, &target.Revision)
|
||||
if err != nil {
|
||||
return work.TaskTarget{}, fmt.Errorf("load task: %w", err)
|
||||
}
|
||||
return target, nil
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package temporal
|
||||
|
||||
// Package temporal: Optional Temporal workflow adapter. Temporal never owns the only copy of a future obligation.
|
||||
@@ -0,0 +1,32 @@
|
||||
package testexecutor
|
||||
|
||||
import (
|
||||
commitcontract "git.cin.su/m/Assistant/contracts/commit"
|
||||
"git.cin.su/m/Assistant/modules/commit/ports"
|
||||
)
|
||||
|
||||
// Executor is a deterministic external-system simulator. ActionIntentID is
|
||||
// the idempotency identity, so replay can never create a second effect.
|
||||
type Executor struct {
|
||||
LoseAcknowledgement bool
|
||||
effects map[commitcontract.ActionIntentID]bool
|
||||
}
|
||||
|
||||
func New(loseAcknowledgement bool) *Executor {
|
||||
return &Executor{LoseAcknowledgement: loseAcknowledgement, effects: make(map[commitcontract.ActionIntentID]bool)}
|
||||
}
|
||||
|
||||
func (e *Executor) Execute(action commitcontract.AuthorizedAction) ports.ExecutionResult {
|
||||
e.effects[action.Proposal.IntentID] = true
|
||||
if e.LoseAcknowledgement {
|
||||
return ports.ExecutionResult{Known: false}
|
||||
}
|
||||
return ports.ExecutionResult{Known: true, Succeeded: true}
|
||||
}
|
||||
|
||||
func (e *Executor) Reconcile(action commitcontract.AuthorizedAction) ports.ExecutionResult {
|
||||
applied, known := e.effects[action.Proposal.IntentID]
|
||||
return ports.ExecutionResult{Known: known, Succeeded: applied}
|
||||
}
|
||||
|
||||
func (e *Executor) EffectCount() int { return len(e.effects) }
|
||||
@@ -0,0 +1,76 @@
|
||||
# 1. ARCHITECTURE_CONSTITUTION.md
|
||||
|
||||
## 1.1 Назначение
|
||||
|
||||
Этот документ — краткий набор законов репозитория и production-архитектуры. Он выше обычных task packets, примеров и локальных README. Codex не является архитектурным authority: он реализует только то, на что выдана task authority.
|
||||
|
||||
## 1.2 Иерархия архитектурной власти
|
||||
|
||||
1. Architecture Constitution.
|
||||
2. Accepted ADR / Foundation Decision.
|
||||
3. Machine-readable Architecture Registry.
|
||||
4. Versioned semantic contracts and state machines.
|
||||
5. Module architecture specification.
|
||||
6. Codex Task Packet.
|
||||
7. Implementation and examples.
|
||||
|
||||
Если нижний уровень противоречит верхнему, нижний считается ошибочным. Существующий код является evidence of implementation, но не authority to redefine architecture.
|
||||
|
||||
## 1.3 Неприкосновенные инварианты V1
|
||||
|
||||
1. LLM/model/provider не является Assistant.
|
||||
2. Capability не означает Authority.
|
||||
3. Observation, Claim, Belief, Prediction, Action и Outcome — разные семантические классы.
|
||||
4. Model output никогда напрямую не мутирует canonical semantic state и не выполняет external mutation.
|
||||
5. Любая реальная мутация проходит Proposal → semantic owner validation → Authority/Integrity checks → Commit → Executor → Outcome/Verification.
|
||||
6. Любая executable activity имеет live justification path к действующей Goal, Commitment, Responsibility или Policy.
|
||||
7. Отмена/суперсессия justification должна распространяться до зависимых работ перед следующим commit.
|
||||
8. Canonical owner — один на конкретный mutable semantic state в конкретной semantic generation.
|
||||
9. Другие модули не пишут canonical storage владельца напрямую.
|
||||
10. Cross-owner SQL writes, cross-owner FK и скрытая cross-owner trigger logic запрещены по умолчанию.
|
||||
11. Derived projections/caches/indexes не являются source of truth и должны быть rebuildable либо явно classified otherwise.
|
||||
12. Temporal/NATS/Redis/vector index/model memory не являются единственным местом хранения commitments, authority, semantic history или future obligations.
|
||||
13. Durable future obligations живут в canonical prospective state независимо от workflow/scheduler engine.
|
||||
14. External side effect должен быть idempotent/reconcilable; timeout не равен failure; UNKNOWN_OUTCOME — first-class state.
|
||||
15. No correctness property may depend on a shared in-process lock across bounded modules.
|
||||
16. Semantic topology, process topology, storage topology и model topology независимы и меняются отдельно.
|
||||
17. Co-location — deployment optimization, не архитектурная привилегия.
|
||||
18. Major bounded contracts должны быть serializable и не зависеть от Go pointers, shared memory, global variables или ambient process state.
|
||||
19. Core/domain не импортирует PostgreSQL/NATS/Temporal/MCP/model-provider packages.
|
||||
20. Никакого giant `common/shared` domain package; technical shared mechanisms допускаются только в `platform` и не владеют domain semantics.
|
||||
21. Semantic duplication предпочтительнее ложной абстракции.
|
||||
22. Event-driven взаимодействие используется ради temporal decoupling/history, а не потому, что два модуля разные.
|
||||
23. Public query не должен скрыто изменять canonical state.
|
||||
24. Durable background responsibility не реализуется unmanaged goroutine/timer.
|
||||
25. `context.Context` не переносит скрытый user/scope/authority/task state; это явные typed fields.
|
||||
26. Unknown/Conflict/NotApplicable/NotObserved не схлопываются в nil/false/default.
|
||||
27. Type system, package visibility, DB ACL и CI должны делать критические ошибки невозможными там, где это возможно.
|
||||
28. Architecture guardrails themselves are protected and cannot validate their own weakening alone.
|
||||
29. Codex ordinary feature task не меняет Constitution, Architecture Registry, public semantic topology, guardrails или canonical ownership без отдельного approved change.
|
||||
30. Codex может завершить задачу typed gap (`BLOCKED_BY_SPEC_GAP`, `BLOCKED_BY_ARCHITECTURE_GAP`) вместо архитектурного обхода.
|
||||
31. Every persistent thing has lifecycle, owner/justification, stop/retirement path and recovery semantics appropriate to criticality.
|
||||
32. Historical meaning is not rewritten by current interpretation; corrections/supersessions are appended/versioned.
|
||||
33. Newer/stronger model never automatically receives broader authority.
|
||||
34. More intelligence, more code, more services or more automations are not goals themselves.
|
||||
35. KEEP/WAIT/DO_NOTHING are valid decisions.
|
||||
36. The system must remain recoverable, exportable and replaceable.
|
||||
|
||||
## 1.4 Codex-specific hard prohibitions
|
||||
|
||||
- No direct cross-module DB access “temporarily”.
|
||||
- No cross-schema JOIN as application dependency between canonical owners.
|
||||
- No direct provider/model call outside Cognitive Gateway/adapters.
|
||||
- No external mutation outside Commit/Executor path.
|
||||
- No generic `SaveEntity(any)`, `Invoke(any)`, global Service Locator or God Context.
|
||||
- No semantic side effects in Go package `init()`.
|
||||
- No semantic durable timers using `time.After`/sleep in request process.
|
||||
- No production semantic behavior hidden only in middleware, SQL trigger or YAML DSL.
|
||||
- No silent retry of ambiguous external mutation.
|
||||
- No weakening of architecture/security tests inside unrelated feature task.
|
||||
- No new third-party dependency, canonical table, integration contract or privileged secret access without declared change classification.
|
||||
|
||||
## 1.5 Core change rule
|
||||
|
||||
Change the lowest layer that eliminates the causal class of the problem. Escalate only when necessary:
|
||||
|
||||
`data/config → local implementation → skill/strategy → module contract → ownership/schema → architecture → constitutional invariant`.
|
||||
@@ -0,0 +1,164 @@
|
||||
# 3. CORE_SEMANTIC_MODEL_V1.md
|
||||
|
||||
## 3.1 Scope
|
||||
|
||||
This is a V1 semantic freeze, not an eternal ontology. It defines the minimum durable concepts required to build the walking skeleton and preserve future migration freedom.
|
||||
|
||||
## 3.2 Canonical Core V1 concepts
|
||||
|
||||
### Identity
|
||||
Stable semantic identity independent of current name, locator, account, process or key. Supports identifier history and future merge/split corrections.
|
||||
|
||||
### Actor
|
||||
Entity capable of requests/actions/representation. Actor is not automatically a Principal.
|
||||
|
||||
### Principal
|
||||
The person/organization/accounting/legal/operational interest on whose behalf an action is performed. Same human may act for multiple principals.
|
||||
|
||||
### Scope
|
||||
Boundary for data, authority, project/context and permissible propagation.
|
||||
|
||||
### AuthorityGrant / AuthorityContext
|
||||
Evidence that an Actor may perform a class of actions for a Principal within Scope and validity conditions. Capability never implies grant.
|
||||
|
||||
### Situation
|
||||
Time-bounded interpretation of “what is happening now”: actor, interface/session, focus, project/workspace/environment bindings, active task, relevant resources, confidence/provenance. Situation is derived and expires/revalidates.
|
||||
|
||||
### Observation
|
||||
Something obtained from a source/sensor/tool/user report. Carries provenance, observed time, coverage and source semantics.
|
||||
|
||||
### Claim
|
||||
A proposition asserted by a source or derived system. It is not automatically fact.
|
||||
|
||||
### Belief/Assessment
|
||||
Current system interpretation supported by evidence; versioned/revisable and scoped.
|
||||
|
||||
### Intent
|
||||
Current request/desired change inferred from interaction; can be revised/superseded. Intent is not automatically long-term preference.
|
||||
|
||||
### Goal
|
||||
Desired world/state transition or outcome with lifecycle and lineage. Goal may be refined/superseded; method is not identical to goal.
|
||||
|
||||
### Task
|
||||
Durable unit of work that must survive session/process, coordinate actors, or carry lifecycle significance. Ephemeral reasoning steps are not Tasks.
|
||||
|
||||
### Decision
|
||||
Selection/commitment among alternatives with rationale/evidence refs where consequence warrants. Decision can have validity/revisit conditions.
|
||||
|
||||
### ActionProposal
|
||||
Structured candidate to change canonical state, communicate, allocate resources or mutate external world. Proposal has no execution authority by itself.
|
||||
|
||||
### AuthorizedAction
|
||||
Proposal that passed owner validation, current authority, revision/target/integrity checks and received commit identity.
|
||||
|
||||
### ActionAttempt
|
||||
Concrete execution attempt of an AuthorizedAction. Multiple attempts may serve one ActionIntent; attempt is not outcome.
|
||||
|
||||
### Outcome
|
||||
Observed/verifiable result attributable with stated confidence. Supports UNKNOWN/partial/provisional maturity.
|
||||
|
||||
### Commitment
|
||||
A future obligation/expectation created by promise/agreement/explicit user request/policy. Must have owner/beneficiary, fulfilment or renegotiation path and prospective continuity.
|
||||
|
||||
### ProspectiveItem
|
||||
Canonical future-relevance object used by Continuity for reminder/wake/review/expected transition. V1 may implement only reminder/wake subset; it remains independent of Temporal.
|
||||
|
||||
### Event
|
||||
Meaningful semantic transition or occurrence. Event is not a log line and not every low-level tool callback becomes Event.
|
||||
|
||||
### Artifact
|
||||
Durable content/resource with identity, content/schema metadata, provenance and scope. Payload may live outside PostgreSQL.
|
||||
|
||||
### Capability
|
||||
Declared/tested ability to observe, reason, communicate or act, with contracts, limits, provenance, health and allowed-use metadata. Capability availability ≠ authority.
|
||||
|
||||
### Revision
|
||||
Optimistic semantic version/precondition for mutable canonical objects and contracts.
|
||||
|
||||
### Provenance
|
||||
Lineage linking observations, claims, derived states, actions and artifacts to sources/derivations without treating copies as independent evidence.
|
||||
|
||||
## 3.3 Concepts intentionally NOT Core primitives in V1
|
||||
|
||||
These remain extension/derived concepts until evidence requires promotion: `Thread`, `Journey`, `Program`, `Trajectory`, `Portfolio`, `Responsibility`, `Risk`, `Opportunity`, `Monitor`, `ControlLoop`, `Routine`, `Theory`, `Frontier`. Foundation must permit them later but Codex must not materialize separate Core tables/services merely because they were discussed.
|
||||
|
||||
## 3.4 Required semantic distinctions
|
||||
|
||||
`Actor ≠ Principal`
|
||||
`Identity ≠ Identifier ≠ Locator`
|
||||
`Situation ≠ RequestContext ≠ ModelContext`
|
||||
`Observation ≠ Claim ≠ Belief`
|
||||
`Intent ≠ Goal ≠ Task`
|
||||
`Task ≠ ActionProposal ≠ AuthorizedAction ≠ ActionAttempt ≠ Outcome`
|
||||
`Commitment ≠ Reminder delivery`
|
||||
`Capability ≠ Authority`
|
||||
`Event ≠ Integration message ≠ Log`
|
||||
`Canonical state ≠ Projection ≠ Cache`
|
||||
`Prediction ≠ Expected-by-process ≠ Required-by-commitment`.
|
||||
|
||||
## 3.5 Required state semantics
|
||||
|
||||
### Goal lifecycle (minimum)
|
||||
`ACTIVE | WAITING | DORMANT | SATISFIED | SUPERSEDED | ABANDONED`
|
||||
|
||||
Transitions must preserve reason and lineage. `ABANDONED` does not mean failure; `SUPERSEDED` must point to successor when known.
|
||||
|
||||
### Task lifecycle (minimum)
|
||||
`PENDING | ACTIVE | WAITING | COMPLETED | CANCELLED | FAILED`
|
||||
|
||||
Task has `revision`, `justification_ref`, optional `wake_condition_ref`, owner and completion evidence. `WAITING` must say what it waits for or be explicitly dormant at higher level.
|
||||
|
||||
### Action lifecycle
|
||||
`PROPOSED → VALIDATED → AUTHORIZED/REJECTED → EXECUTING → SUCCEEDED | FAILED | UNKNOWN_OUTCOME | COMPENSATED`.
|
||||
|
||||
Retry preserves ActionIntent identity and creates a new attempt identity. `UNKNOWN_OUTCOME` blocks blind retry when duplicate effect is possible.
|
||||
|
||||
### Commitment lifecycle
|
||||
`ACTIVE | WAITING | AT_RISK | FULFILLED | RENEGOTIATED | REVOKED | EXPIRED`.
|
||||
|
||||
Future promise is not fulfilled by notification delivery alone unless the promise itself was only to notify.
|
||||
|
||||
### Prospective item lifecycle
|
||||
`REGISTERED | ARMED | TRIGGERED | REVALIDATING | DELIVERED/STARTED | SATISFIED | SUPPRESSED | EXPIRED`.
|
||||
|
||||
Trigger firing does not bypass relevance/authority revalidation.
|
||||
|
||||
## 3.6 Temporal model
|
||||
|
||||
Foundation must support distinguishing, where applicable:
|
||||
|
||||
- event/occurrence time;
|
||||
- observed time;
|
||||
- recorded time;
|
||||
- validity interval;
|
||||
- local-time intention vs absolute instant;
|
||||
- relative schedule relation (`after Event X + duration`) vs prematurely flattened timestamp.
|
||||
|
||||
Do not put four timestamps on every row blindly. Use common temporal value objects/contracts only where semantics require them.
|
||||
|
||||
## 3.7 Strong identifiers
|
||||
|
||||
Go Core should use distinct types for at least: `IdentityID`, `ActorID`, `PrincipalID`, `ScopeID`, `SituationID`, `GoalID`, `TaskID`, `CommitmentID`, `ActionIntentID`, `ActionAttemptID`, `ArtifactID`, `CapabilityID`, plus revision types. They serialize to language-neutral primitives.
|
||||
|
||||
## 3.8 Ownership baseline
|
||||
|
||||
| Semantic area | Canonical owner V1 | Notes |
|
||||
|---|---|---|
|
||||
| Identity/Actor/Principal bindings | Identity module | Other modules reference IDs/projections only. |
|
||||
| Scope/Authority grants | Authority module | Commit queries current validation; no hidden default authority. |
|
||||
| Situation/focus bindings | Situation module | Derived/ephemeral portions may use cache, but durable bindings/provenance explicitly classified. |
|
||||
| Goal/Task/Decision | Work module | Can later split; V1 owner chosen to preserve local consistency. |
|
||||
| Commitment/Prospective items | Continuity module | Temporal is execution engine adapter, not owner. |
|
||||
| Observations/Claims/Beliefs/Provenance | Epistemics module | Search/vector indexes derived. |
|
||||
| Action commit state | Commit module | External executor isolated. |
|
||||
| Artifact metadata/lineage | Artifact module or platform-owned artifact service | Payload storage replaceable. |
|
||||
| Capability registry/bindings | Capability module | Provider-specific adapters outside semantic owner. |
|
||||
|
||||
## 3.9 Consistency baseline
|
||||
|
||||
- Authority validation and Action authorization: strong owner-local consistency + revision preconditions.
|
||||
- Task state transitions: owner-local optimistic revision/CAS.
|
||||
- Cross-owner projections: eventual/rebuildable unless an explicit use case requires stronger semantics.
|
||||
- UI aggregate views: derived projections; no cross-owner canonical joins.
|
||||
- Integration reactions: owner-local commit + transactional outbox; consumers idempotent.
|
||||
- No global total event order requirement; causal/aggregate ordering only where needed.
|
||||
@@ -0,0 +1,87 @@
|
||||
# 2. DECISION_CONSOLIDATION_V1.md
|
||||
|
||||
## 2.1 Purpose
|
||||
|
||||
This inventory separates accepted decisions from explored ideas. Statuses are normative:
|
||||
|
||||
- **ACCEPTED_V1** — implementation may rely on it now.
|
||||
- **EXTENSION_POINT_V1** — foundation must not block it; no full implementation required.
|
||||
- **LATER** — explicitly excluded from current implementation scope.
|
||||
- **RESEARCH** — unresolved; Codex must not choose a permanent answer silently.
|
||||
- **REJECTED_V1** — do not implement this approach in V1.
|
||||
|
||||
## 2.2 Accepted foundation decisions
|
||||
|
||||
| ID | Decision | Status | Implementation consequence |
|
||||
|---|---|---|---|
|
||||
| FD-001 | Assistant ≠ LLM/model/provider/process | ACCEPTED_V1 | Cognitive providers are replaceable capabilities. |
|
||||
| FD-002 | Extractable Modular Architecture | ACCEPTED_V1 | Deploy together when useful, design bounded components separately. |
|
||||
| FD-003 | One PostgreSQL cluster may host V1, but canonical owners use separate schemas/roles | ACCEPTED_V1 | DB ACL physically prevents cross-owner writes. |
|
||||
| FD-004 | Cross-owner FK/trigger business logic forbidden by default | ACCEPTED_V1 | Relations use semantic IDs/contracts/projections. |
|
||||
| FD-005 | NATS/Temporal/Redis are implementation mechanisms, not semantic sources of truth | ACCEPTED_V1 | Canonical event/prospective state survives their loss. |
|
||||
| FD-006 | Major cross-boundary contracts are remote-capable | ACCEPTED_V1 | In-process and remote adapters satisfy same contract tests. |
|
||||
| FD-007 | No mandatory microservice-per-noun | ACCEPTED_V1 | Semantic modules and deployment runtimes are independent mappings. |
|
||||
| FD-008 | Commit/Executor is an early physical isolation boundary | ACCEPTED_V1 | External credentials and mutation authority are not globally available. |
|
||||
| FD-009 | Model output produces candidates/proposals, never direct canonical mutation | ACCEPTED_V1 | Typed semantic validation and commit gates. |
|
||||
| FD-010 | Canonical event/outbox pattern for cross-owner durable reactions | ACCEPTED_V1 | Owner-local ACID + outbox; no distributed ACID assumption. |
|
||||
| FD-011 | Prospective Memory canonicalized outside Temporal | ACCEPTED_V1 | Reminder/wake/commitment state rebuilds after workflow-engine loss. |
|
||||
| FD-012 | Identity, Principal, Scope and Authority are separate concepts | ACCEPTED_V1 | Strong typed IDs and explicit command envelopes. |
|
||||
| FD-013 | Goal/Task/Action/Outcome are distinct | ACCEPTED_V1 | Task completion does not imply goal/outcome success. |
|
||||
| FD-014 | Situation binds request to project/workspace/environment via runtime context, not keywords | ACCEPTED_V1 | Focus Isolation Suite is foundational acceptance test. |
|
||||
| FD-015 | Unknown and conflict states preserved | ACCEPTED_V1 | No premature boolean/default collapse. |
|
||||
| FD-016 | Bitemporal-capable history model | ACCEPTED_V1 | Separate event/observed/valid/recorded semantics where relevant. |
|
||||
| FD-017 | Canonical history append/supersede rather than retroactive semantic rewrite | ACCEPTED_V1 | Historical replay can reconstruct what was known then. |
|
||||
| FD-018 | Development through Codex requires Development Commit Gate | ACCEPTED_V1 | Task authority + CI/ACL/architecture checks precede merge. |
|
||||
| FD-019 | Architecture is executable | ACCEPTED_V1 | Critical rules need compiler/linter/ACL/test/observability enforcement. |
|
||||
| FD-020 | V1 uses explicit boring typed mechanisms over meta-frameworks/DSLs | ACCEPTED_V1 | No generic entity engine/universal workflow DSL. |
|
||||
| FD-021 | Contract/state ownership precedes DDL/protobuf | ACCEPTED_V1 | Schema is derived from semantic contracts. |
|
||||
| FD-022 | Walking Skeleton before broad subsystem implementation | ACCEPTED_V1 | Foundation validated vertically, not through stub zoo. |
|
||||
| FD-023 | Stronger future model is candidate, not automatic replacement | ACCEPTED_V1 | Eval/shadow/canary/promotion lifecycle. |
|
||||
| FD-024 | Architecture boundaries are hypotheses and may split/merge | ACCEPTED_V1 | Stable IDs/lineage; topology migration supported. |
|
||||
| FD-025 | Critical deterministic invariants are not delegated to free-form LLM judgment | ACCEPTED_V1 | Fuzzy cognition proposes; deterministic gates enforce. |
|
||||
|
||||
## 2.3 Extension points that must be preserved now
|
||||
|
||||
| ID | Topic | Status | V1 requirement |
|
||||
|---|---|---|---|
|
||||
| EP-001 | Portfolio/Trajectory engines | EXTENSION_POINT_V1 | Core goal/project/event model must permit later orchestration. |
|
||||
| EP-002 | Responsibilities/Risks/Opportunities/ControlLoops | EXTENSION_POINT_V1 | Semantic namespaces/lifecycles extensible; no full engines required. |
|
||||
| EP-003 | Self-development/self-migration | EXTENSION_POINT_V1 | Architecture/change provenance and replacement paths exist; autonomous self-editing absent. |
|
||||
| EP-004 | Collective/global learning | EXTENSION_POINT_V1 | Knowledge provenance/scope prevents unsafe future promotion. |
|
||||
| EP-005 | Multi-user/organization federation | EXTENSION_POINT_V1 | Actor/Principal/Scope not hardcoded to single user. |
|
||||
| EP-006 | Robotics/edge realtime control | EXTENSION_POINT_V1 | Capability/authority model supports out-of-process bounded controllers. |
|
||||
| EP-007 | Alternate coding agents | EXTENSION_POINT_V1 | Codex Task Packet provider-neutral; Codex adapter first. |
|
||||
| EP-008 | Semantic generation migration | EXTENSION_POINT_V1 | Version/schema IDs and migration framework exist; no universal ontology engine. |
|
||||
|
||||
## 2.4 Explicit V1 non-goals
|
||||
|
||||
The following are **LATER or RESEARCH**, not implementation requirements for Foundation V1:
|
||||
|
||||
- autonomous production self-modification;
|
||||
- autonomous installation of arbitrary plugins/components;
|
||||
- global collective learning between unrelated users;
|
||||
- Kubernetes requirement;
|
||||
- custom consensus protocol;
|
||||
- custom database or event-bus implementation;
|
||||
- full robotics stack;
|
||||
- universal ontology/DSL engine;
|
||||
- one service per semantic noun;
|
||||
- complete multi-tenant enterprise federation;
|
||||
- training custom foundation models as part of V1;
|
||||
- perfect global causal graph;
|
||||
- general autonomous portfolio optimization of human life;
|
||||
- fully autonomous Codex development swarm.
|
||||
|
||||
## 2.5 Rejected V1 approaches
|
||||
|
||||
- REJECTED: “Start as free modular monolith and split later.”
|
||||
- REJECTED: giant shared domain model/package.
|
||||
- REJECTED: cross-module joins because “same DB for now”.
|
||||
- REJECTED: event-sourcing everything by default.
|
||||
- REJECTED: microservices for every primitive.
|
||||
- REJECTED: direct LLM→tool→world mutation path.
|
||||
- REJECTED: Temporal workflow as canonical future obligation.
|
||||
- REJECTED: vector DB/Redis/model memory as canonical knowledge.
|
||||
- REJECTED: generic `entity(type,payload jsonb)` as primary Core model.
|
||||
- REJECTED: implicit global utility score for all goals.
|
||||
- REJECTED: relying on Codex remembering architecture from previous sessions.
|
||||
@@ -0,0 +1,7 @@
|
||||
# Architecture authority
|
||||
|
||||
This directory contains architecture authority artifacts. `ARCHITECTURE_CONSTITUTION.md` outranks all lower-level files. `architecture-registry.yaml` is the human-authoritative machine-readable registry; `architecture-registry.json` is the generated/bootstrapping mirror used by the initial stdlib-only `devctl`.
|
||||
|
||||
Do not casually edit either registry copy. A Tier E task must update both atomically until registry generation is automated.
|
||||
|
||||
`reference/FOUNDATION_FREEZE_PACK_V1.*` preserves the freeze package used to bootstrap this repository. It is reference/history, not higher authority than current accepted files in this directory.
|
||||
@@ -0,0 +1,33 @@
|
||||
# 7. UNRESOLVED_QUESTIONS.md
|
||||
|
||||
These questions are intentionally unresolved. Codex must not silently turn temporary assumptions into permanent architecture.
|
||||
|
||||
| ID | Question | Status | Temporary V1 position | Blocking? | Revisit trigger |
|
||||
|---|---|---|---|---|---|
|
||||
| UQ-001 | Exact split of `Work` into Goal/Task/Decision modules | RESEARCH | One canonical Work owner for V1 | No | Contract churn/co-change/consistency pressure |
|
||||
| UQ-002 | Artifact metadata as separate module vs platform service | PROPOSED | Keep separate semantic owner if persistence begins | No | First large artifact integration |
|
||||
| UQ-003 | Exact NATS subject taxonomy | DEFERRED | Define only subjects required by skeleton | No | First durable cross-owner event |
|
||||
| UQ-004 | Exact Temporal workflow topology | DEFERRED | Temporal adapter behind Continuity; canonical prospective state outside | No | WS-002 implementation |
|
||||
| UQ-005 | gRPC vs another remote transport for internal calls | DEFERRED | Contracts language-neutral; choose simplest baseline during remote drill | No | WS-004 |
|
||||
| UQ-006 | Extent of canonical event archive vs per-owner transition history | RESEARCH | Do not event-source everything; retain meaningful events/outbox | No | Replay/recovery requirements emerge |
|
||||
| UQ-007 | Formal policy engine technology | LATER | Deterministic typed Authority/Commit rules in Go V1 | No | Policy complexity outgrows code safely |
|
||||
| UQ-008 | Vector store implementation | LATER | Search indexes derived; no foundation dependency | No | Epistemic retrieval slice |
|
||||
| UQ-009 | Redis requirement | LATER | Optional cache only; correctness must not depend on it | No | Performance evidence |
|
||||
| UQ-010 | Full Identity merge/split production workflow | EXTENSION_POINT | IDs/lineage schema must not preclude it; test simplified correction later | No | Multi-source identity pressure |
|
||||
| UQ-011 | Portfolio/Trajectory/Responsibility primitives promotion | RESEARCH | Not Core V1 | No | Repeated distinct lifecycle/authority need |
|
||||
| UQ-012 | Self-development automation | LATER | Development Control Plane external/manual-governed | No | Foundation + safe change/recovery mature |
|
||||
| UQ-013 | Multi-user organization governance | LATER | Actor/Principal/Scope designed generally; expose single-user V1 if desired | No | Actual shared workspace requirement |
|
||||
| UQ-014 | Canonical wire codec longevity | RESEARCH | Versioned schema/envelope; initial protobuf acceptable, not eternal identity | No | First non-Go module or major semantic migration |
|
||||
| UQ-015 | Exact data retention/privacy policy engine | RESEARCH | Store scope/provenance/sensitivity hooks; implement concrete policies per product deployment | No | Product/legal requirements |
|
||||
|
||||
## 7.1 Spec-gap protocol
|
||||
|
||||
If implementation encounters a semantically material unknown not listed here, Codex emits a `SpecificationGap` with:
|
||||
|
||||
- exact scenario;
|
||||
- current contract insufficiency;
|
||||
- smallest temporary safe behavior if one exists;
|
||||
- whether work can continue independently;
|
||||
- proposed alternatives without choosing permanent architecture.
|
||||
|
||||
No architecture gap is solved by creating an unowned table, generic JSON object, cross-module direct read/write, or hidden provider-specific field.
|
||||
@@ -0,0 +1,132 @@
|
||||
# 6. WALKING_SKELETON_SPEC.md
|
||||
|
||||
## 6.1 Goal
|
||||
|
||||
Prove the Foundation through a small set of end-to-end semantic properties before broad implementation. Do not build all future modules/stubs first.
|
||||
|
||||
## 6.2 Skeleton topology
|
||||
|
||||
Initial process topology:
|
||||
|
||||
```text
|
||||
Client/Test Harness
|
||||
|
|
||||
Core Runtime
|
||||
- Identity
|
||||
- Situation
|
||||
- Work
|
||||
- Epistemics (minimal)
|
||||
- Capability registry (minimal)
|
||||
|
|
||||
+---- Cognitive Worker Adapter (deterministic fake first, real model later)
|
||||
|
|
||||
+---- Continuity Runtime ---- Temporal adapter (optional/replaceable)
|
||||
|
|
||||
+---- Commit Runtime (separate process, isolated credentials)
|
||||
|
|
||||
Test Executor
|
||||
```
|
||||
|
||||
One PostgreSQL cluster, separate owner schemas/roles. NATS may be used for integration events once owner-local outbox exists; skeleton must also prove semantics do not live only in NATS.
|
||||
|
||||
## 6.3 Scenario WS-001 — Focus Isolation / wrong-project prevention
|
||||
|
||||
**Given** one Actor has two simultaneously active Codex/workspace situations bound to Project/Goal contexts A and B. Both domains contain an identically named concept such as `temperature`.
|
||||
|
||||
**When** the identical user phrase is sent through each session without naming the project.
|
||||
|
||||
**Then** Situation resolution binds each request to its own session/workspace/project context using runtime bindings/provenance; no keyword shortcut is allowed; canonical writes carry target/revision/scope and cannot affect the other context.
|
||||
|
||||
Required failure cases:
|
||||
- stale focus binding;
|
||||
- two worktrees of same repository;
|
||||
- ambiguous target → typed ambiguity, no mutation;
|
||||
- Task revision changed between reasoning and commit → commit rejected/re-evaluated.
|
||||
|
||||
Acceptance property: **wrong-project mutation is mechanically prevented even if cognition proposes the wrong target**.
|
||||
|
||||
## 6.4 Scenario WS-002 — Durable prospective memory independent of Temporal
|
||||
|
||||
**Given** user creates a future reminder/commitment with semantic context and fulfilment condition.
|
||||
|
||||
**When** canonical Continuity transaction commits, process restarts, Temporal state is deleted/unavailable, then workflow infrastructure is rebuilt.
|
||||
|
||||
**Then** obligation remains in PostgreSQL canonical prospective state, is reconstructed, does not duplicate occurrence, revalidates relevance before delivery, and can distinguish `DELIVERED` from underlying `FULFILLED`.
|
||||
|
||||
Failure cases:
|
||||
- system offline past trigger;
|
||||
- 100 duplicate trigger messages;
|
||||
- goal superseded before trigger;
|
||||
- delivery channel unavailable;
|
||||
- recurrence missed during outage.
|
||||
|
||||
Acceptance property: **loss of workflow engine does not lose or blindly replay future obligations**.
|
||||
|
||||
## 6.5 Scenario WS-003 — Safe Action Commit and unknown outcome
|
||||
|
||||
**Given** cognition produces a structured external mutation proposal.
|
||||
|
||||
**When** Commit Runtime receives it.
|
||||
|
||||
**Then** it validates current Authority, Scope, Target identity, task/goal justification and relevant revisions before producing AuthorizedAction. Only isolated Executor has external mutation credentials.
|
||||
|
||||
Injected case: executor applies external effect but connection times out before acknowledgement.
|
||||
|
||||
Expected result: `UNKNOWN_OUTCOME`; no blind retry; reconciliation query/verification required. A retry uses same ActionIntentID and a new AttemptID only after semantics permit.
|
||||
|
||||
Acceptance property: **no external side effect can bypass authority/commit and timeout cannot cause duplicate mutation by default**.
|
||||
|
||||
## 6.6 Scenario WS-004 — Topology equivalence
|
||||
|
||||
Run WS-001/002/003 twice:
|
||||
|
||||
1. bounded modules co-located where allowed;
|
||||
2. Commit and Continuity accessed through remote adapters/processes.
|
||||
|
||||
Canonical semantic outcomes/invariants must be equivalent. Timing and expected temporary unavailability may differ; domain meaning must not.
|
||||
|
||||
Acceptance property: **process extraction does not require domain rewrite**.
|
||||
|
||||
## 6.7 Scenario WS-005 — No-LLM degraded continuity
|
||||
|
||||
Remove all cognitive providers.
|
||||
|
||||
System must still:
|
||||
- identify existing actors/sessions where deterministically available;
|
||||
- preserve events/state;
|
||||
- keep canonical commitments/prospective schedules;
|
||||
- perform deterministic authority/integrity checks;
|
||||
- expose degraded capability state;
|
||||
- avoid inventing new AI decisions/actions.
|
||||
|
||||
Acceptance property: **loss of cognition degrades intelligence, not continuity/integrity**.
|
||||
|
||||
## 6.8 Scenario WS-006 — Semantic evolution drill
|
||||
|
||||
Create a deliberately small v1→v2 contract/schema change in a non-critical skeleton concept. Prove:
|
||||
|
||||
- old historical object remains interpretable;
|
||||
- new writer/readers use new version;
|
||||
- unsupported semantics are explicit, not silently defaulted;
|
||||
- active live objects migrate/validate;
|
||||
- derived projections rebuild;
|
||||
- rollback/forward-fix mode is documented.
|
||||
|
||||
Acceptance property: **architecture evolution is tested as a transformation, not merely promised**.
|
||||
|
||||
## 6.9 Foundation Exit Criteria
|
||||
|
||||
Foundation V1 is eligible for freeze when all are true:
|
||||
|
||||
1. Fresh Codex session can implement a bounded feature from repository artifacts alone.
|
||||
2. Cross-owner DB write is physically denied.
|
||||
3. Wrong-project mutation fails even under adversarial cognition proposal.
|
||||
4. Stale/revoked authority cannot create AuthorizedAction.
|
||||
5. Duplicate/replay does not duplicate external side effects in covered semantics.
|
||||
6. Future obligation survives workflow-engine loss/rebuild.
|
||||
7. Core remains continuity-capable without any LLM.
|
||||
8. Same semantic scenarios pass in at least two process topologies.
|
||||
9. Provider can be swapped/faked without domain contract change.
|
||||
10. Declared and observed architecture graphs match or all drift has registered findings.
|
||||
11. One semantic contract migration drill succeeds.
|
||||
12. Architecture guardrail suite proves its own critical enforcement with negative tests.
|
||||
@@ -0,0 +1,14 @@
|
||||
# ADR-0001 — Extractable Modular Architecture
|
||||
|
||||
**Status:** ACCEPTED_V1
|
||||
|
||||
V1 may co-deploy modules, but major bounded components are designed separately and must remain extractable. Co-location is a deployment optimization, never an architectural privilege.
|
||||
|
||||
Semantic topology, process topology, storage topology and cognitive/provider topology are independent mappings.
|
||||
|
||||
Consequences:
|
||||
- remote-capable contracts are serializable and do not depend on shared mutable state;
|
||||
- cross-owner ACID transactions are forbidden;
|
||||
- separate PostgreSQL schemas/roles from day one;
|
||||
- Commit Runtime is physically isolated earlier because it holds mutation authority/secrets;
|
||||
- topology equivalence tests are Foundation criteria.
|
||||
@@ -0,0 +1,7 @@
|
||||
# ADR-0002 — Codex is an implementation capability
|
||||
|
||||
**Status:** ACCEPTED_V1
|
||||
|
||||
Codex is expected to implement most code but is not architectural authority. Repository structure, type system, DB ACLs, protected paths, CI and task packets must mechanically enforce what can be enforced.
|
||||
|
||||
A fresh Codex session must be able to work correctly from repository artifacts without prior chat history.
|
||||
@@ -0,0 +1,5 @@
|
||||
# ADRs
|
||||
|
||||
Accepted architecture decisions live here. Normal implementation tasks may read but not create/change accepted ADRs unless explicitly authorized.
|
||||
|
||||
Use `ADR-XXXX-title.md` with: problem, evidence, alternatives, decision, rationale, consequences, validity conditions, revisit triggers, migration/rollback, status.
|
||||
@@ -0,0 +1,283 @@
|
||||
{
|
||||
"registry_version": 1,
|
||||
"semantic_generation": 1,
|
||||
"architecture_generation": 1,
|
||||
"modules": {
|
||||
"identity": {
|
||||
"id": "mod.identity",
|
||||
"owns": [
|
||||
"Identity",
|
||||
"Actor",
|
||||
"PrincipalBinding"
|
||||
],
|
||||
"database_schema": "identity",
|
||||
"boundary_class": "remote_capable",
|
||||
"may_depend_on": [
|
||||
"platform.ids",
|
||||
"platform.events"
|
||||
],
|
||||
"forbidden": [
|
||||
"adapters.models",
|
||||
"adapters.temporal"
|
||||
]
|
||||
},
|
||||
"authority": {
|
||||
"id": "mod.authority",
|
||||
"owns": [
|
||||
"Scope",
|
||||
"AuthorityGrant",
|
||||
"AuthorityValidation"
|
||||
],
|
||||
"database_schema": "authority",
|
||||
"boundary_class": "remote_capable",
|
||||
"may_depend_on": [
|
||||
"contracts.identity",
|
||||
"platform.ids",
|
||||
"platform.events"
|
||||
]
|
||||
},
|
||||
"situation": {
|
||||
"id": "mod.situation",
|
||||
"owns": [
|
||||
"Situation",
|
||||
"FocusBinding"
|
||||
],
|
||||
"database_schema": "situation",
|
||||
"boundary_class": "remote_capable",
|
||||
"may_depend_on": [
|
||||
"contracts.identity",
|
||||
"contracts.authority",
|
||||
"contracts.work",
|
||||
"contracts.capability"
|
||||
]
|
||||
},
|
||||
"work": {
|
||||
"id": "mod.work",
|
||||
"owns": [
|
||||
"Goal",
|
||||
"Task",
|
||||
"Decision"
|
||||
],
|
||||
"database_schema": "work",
|
||||
"boundary_class": "remote_capable",
|
||||
"may_depend_on": [
|
||||
"contracts.identity",
|
||||
"contracts.authority",
|
||||
"platform.events"
|
||||
]
|
||||
},
|
||||
"epistemics": {
|
||||
"id": "mod.epistemics",
|
||||
"owns": [
|
||||
"Observation",
|
||||
"Claim",
|
||||
"Belief",
|
||||
"Provenance"
|
||||
],
|
||||
"database_schema": "epistemics",
|
||||
"boundary_class": "remote_capable",
|
||||
"may_depend_on": [
|
||||
"contracts.identity",
|
||||
"contracts.artifact",
|
||||
"platform.events"
|
||||
]
|
||||
},
|
||||
"continuity": {
|
||||
"id": "mod.continuity",
|
||||
"owns": [
|
||||
"Commitment",
|
||||
"ProspectiveItem"
|
||||
],
|
||||
"database_schema": "continuity",
|
||||
"boundary_class": "remote_capable",
|
||||
"may_depend_on": [
|
||||
"contracts.work",
|
||||
"contracts.identity",
|
||||
"contracts.authority",
|
||||
"platform.events"
|
||||
]
|
||||
},
|
||||
"capability": {
|
||||
"id": "mod.capability",
|
||||
"owns": [
|
||||
"Capability",
|
||||
"CapabilityBinding",
|
||||
"CapabilityHealth"
|
||||
],
|
||||
"database_schema": "capability",
|
||||
"boundary_class": "remote_capable",
|
||||
"may_depend_on": [
|
||||
"contracts.identity",
|
||||
"contracts.authority",
|
||||
"contracts.artifact"
|
||||
]
|
||||
},
|
||||
"commit": {
|
||||
"id": "mod.commit",
|
||||
"owns": [
|
||||
"ActionProposalRecord",
|
||||
"AuthorizedAction",
|
||||
"ActionAttemptRecord"
|
||||
],
|
||||
"database_schema": "commit",
|
||||
"boundary_class": "remote_capable",
|
||||
"may_depend_on": [
|
||||
"contracts.authority",
|
||||
"contracts.capability",
|
||||
"contracts.work",
|
||||
"platform.events"
|
||||
],
|
||||
"privileged": true
|
||||
},
|
||||
"artifact": {
|
||||
"id": "mod.artifact",
|
||||
"owns": [
|
||||
"ArtifactMetadata",
|
||||
"ArtifactLineage"
|
||||
],
|
||||
"database_schema": "artifact",
|
||||
"boundary_class": "remote_capable",
|
||||
"may_depend_on": [
|
||||
"contracts.identity"
|
||||
]
|
||||
}
|
||||
},
|
||||
"platform": {
|
||||
"allowed_packages": [
|
||||
"platform.ids",
|
||||
"platform.clock",
|
||||
"platform.outbox",
|
||||
"platform.inbox",
|
||||
"platform.telemetry",
|
||||
"platform.errors"
|
||||
],
|
||||
"rule": "platform owns mechanisms, never domain meaning"
|
||||
},
|
||||
"runtime_topology_v1": {
|
||||
"core_runtime": {
|
||||
"modules": [
|
||||
"identity",
|
||||
"situation",
|
||||
"work",
|
||||
"epistemics",
|
||||
"capability",
|
||||
"artifact"
|
||||
]
|
||||
},
|
||||
"continuity_runtime": {
|
||||
"modules": [
|
||||
"continuity"
|
||||
]
|
||||
},
|
||||
"commit_runtime": {
|
||||
"modules": [
|
||||
"authority",
|
||||
"commit"
|
||||
],
|
||||
"isolation_reason": [
|
||||
"secrets",
|
||||
"external_mutation_authority",
|
||||
"failure_isolation"
|
||||
]
|
||||
},
|
||||
"cognitive_workers": {
|
||||
"modules": [],
|
||||
"role": "replaceable cognition/context compilation workers; no canonical ownership"
|
||||
}
|
||||
},
|
||||
"storage_topology_v1": {
|
||||
"postgres_cluster": "assistant_primary",
|
||||
"schemas": {
|
||||
"identity": "identity_role",
|
||||
"authority": "authority_role",
|
||||
"situation": "situation_role",
|
||||
"work": "work_role",
|
||||
"epistemics": "epistemics_role",
|
||||
"continuity": "continuity_role",
|
||||
"capability": "capability_role",
|
||||
"commit": "commit_role",
|
||||
"artifact": "artifact_role"
|
||||
},
|
||||
"cross_owner_fk": "forbidden_by_default",
|
||||
"cross_owner_write": "forbidden",
|
||||
"cross_owner_application_join": "forbidden"
|
||||
},
|
||||
"invariants": [
|
||||
{
|
||||
"id": "INV-AUTH-001",
|
||||
"property": "No external mutation without current valid authority and target/revision checks",
|
||||
"class": "HARD",
|
||||
"enforcement": [
|
||||
"commit_runtime",
|
||||
"property_tests",
|
||||
"secret_acl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "INV-OWN-001",
|
||||
"property": "Only semantic owner writes canonical state",
|
||||
"class": "HARD",
|
||||
"enforcement": [
|
||||
"db_acl",
|
||||
"architecture_linter"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "INV-CONT-001",
|
||||
"property": "Future obligations survive workflow engine loss",
|
||||
"class": "HARD",
|
||||
"enforcement": [
|
||||
"canonical_prospective_store",
|
||||
"recovery_test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "INV-TOPO-001",
|
||||
"property": "Major bounded contracts preserve semantics across inproc and remote topology",
|
||||
"class": "HARD",
|
||||
"enforcement": [
|
||||
"topology_equivalence_tests"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "INV-EPI-001",
|
||||
"property": "Model output cannot directly become canonical fact/action",
|
||||
"class": "HARD",
|
||||
"enforcement": [
|
||||
"package_boundaries",
|
||||
"commit_apis",
|
||||
"semantic_validation_tests"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "INV-PROJ-001",
|
||||
"property": "Projection eventually converges from canonical state",
|
||||
"class": "CONVERGENCE",
|
||||
"enforcement": [
|
||||
"projection_rebuild_tests",
|
||||
"lag_metrics"
|
||||
]
|
||||
}
|
||||
],
|
||||
"protected_paths": [
|
||||
"architecture/ARCHITECTURE_CONSTITUTION.md",
|
||||
"architecture/architecture-registry.yaml",
|
||||
"architecture/adrs/**",
|
||||
"ci/architecture/**",
|
||||
"security/**"
|
||||
],
|
||||
"default_feature_task_authority": {
|
||||
"may_write": [
|
||||
"declared module paths",
|
||||
"module-owned tests"
|
||||
],
|
||||
"may_not_change": [
|
||||
"canonical_ownership",
|
||||
"public_cross_module_contracts",
|
||||
"protected_paths",
|
||||
"third_party_dependencies",
|
||||
"database_owner_roles",
|
||||
"privileged_capabilities"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
# 4. architecture-registry.yaml
|
||||
|
||||
Below is the normative starter registry. It is intentionally small. Tooling may extend the schema, but new relation types must have an enforcement/use case.
|
||||
|
||||
```yaml
|
||||
registry_version: 1
|
||||
semantic_generation: 1
|
||||
architecture_generation: 1
|
||||
|
||||
modules:
|
||||
identity:
|
||||
id: mod.identity
|
||||
owns: [Identity, Actor, PrincipalBinding]
|
||||
database_schema: identity
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [platform.ids, platform.events]
|
||||
forbidden: [adapters.models, adapters.temporal]
|
||||
|
||||
authority:
|
||||
id: mod.authority
|
||||
owns: [Scope, AuthorityGrant, AuthorityValidation]
|
||||
database_schema: authority
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity, platform.ids, platform.events]
|
||||
|
||||
situation:
|
||||
id: mod.situation
|
||||
owns: [Situation, FocusBinding]
|
||||
database_schema: situation
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity, contracts.work, contracts.capability]
|
||||
|
||||
work:
|
||||
id: mod.work
|
||||
owns: [Goal, Task, Decision]
|
||||
database_schema: work
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity, contracts.authority, platform.events]
|
||||
|
||||
epistemics:
|
||||
id: mod.epistemics
|
||||
owns: [Observation, Claim, Belief, Provenance]
|
||||
database_schema: epistemics
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity, contracts.artifact, platform.events]
|
||||
|
||||
continuity:
|
||||
id: mod.continuity
|
||||
owns: [Commitment, ProspectiveItem]
|
||||
database_schema: continuity
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.work, contracts.identity, contracts.authority, platform.events]
|
||||
|
||||
capability:
|
||||
id: mod.capability
|
||||
owns: [Capability, CapabilityBinding, CapabilityHealth]
|
||||
database_schema: capability
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity, contracts.authority, contracts.artifact]
|
||||
|
||||
commit:
|
||||
id: mod.commit
|
||||
owns: [ActionProposalRecord, AuthorizedAction, ActionAttemptRecord]
|
||||
database_schema: commit
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.authority, contracts.capability, contracts.work, platform.events]
|
||||
privileged: true
|
||||
|
||||
artifact:
|
||||
id: mod.artifact
|
||||
owns: [ArtifactMetadata, ArtifactLineage]
|
||||
database_schema: artifact
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity]
|
||||
|
||||
platform:
|
||||
allowed_packages:
|
||||
- platform.ids
|
||||
- platform.clock
|
||||
- platform.outbox
|
||||
- platform.inbox
|
||||
- platform.telemetry
|
||||
- platform.errors
|
||||
rule: "platform owns mechanisms, never domain meaning"
|
||||
|
||||
runtime_topology_v1:
|
||||
core_runtime:
|
||||
modules: [identity, situation, work, epistemics, capability, artifact]
|
||||
continuity_runtime:
|
||||
modules: [continuity]
|
||||
commit_runtime:
|
||||
modules: [authority, commit]
|
||||
isolation_reason: [secrets, external_mutation_authority, failure_isolation]
|
||||
cognitive_workers:
|
||||
modules: []
|
||||
role: "replaceable cognition/context compilation workers; no canonical ownership"
|
||||
|
||||
storage_topology_v1:
|
||||
postgres_cluster: assistant_primary
|
||||
schemas:
|
||||
identity: identity_role
|
||||
authority: authority_role
|
||||
situation: situation_role
|
||||
work: work_role
|
||||
epistemics: epistemics_role
|
||||
continuity: continuity_role
|
||||
capability: capability_role
|
||||
commit: commit_role
|
||||
artifact: artifact_role
|
||||
cross_owner_fk: forbidden_by_default
|
||||
cross_owner_write: forbidden
|
||||
cross_owner_application_join: forbidden
|
||||
|
||||
invariants:
|
||||
- id: INV-AUTH-001
|
||||
property: "No external mutation without current valid authority and target/revision checks"
|
||||
class: HARD
|
||||
enforcement: [commit_runtime, property_tests, secret_acl]
|
||||
- id: INV-OWN-001
|
||||
property: "Only semantic owner writes canonical state"
|
||||
class: HARD
|
||||
enforcement: [db_acl, architecture_linter]
|
||||
- id: INV-CONT-001
|
||||
property: "Future obligations survive workflow engine loss"
|
||||
class: HARD
|
||||
enforcement: [canonical_prospective_store, recovery_test]
|
||||
- id: INV-TOPO-001
|
||||
property: "Major bounded contracts preserve semantics across inproc and remote topology"
|
||||
class: HARD
|
||||
enforcement: [topology_equivalence_tests]
|
||||
- id: INV-EPI-001
|
||||
property: "Model output cannot directly become canonical fact/action"
|
||||
class: HARD
|
||||
enforcement: [package_boundaries, commit_apis, semantic_validation_tests]
|
||||
- id: INV-PROJ-001
|
||||
property: "Projection eventually converges from canonical state"
|
||||
class: CONVERGENCE
|
||||
enforcement: [projection_rebuild_tests, lag_metrics]
|
||||
|
||||
protected_paths:
|
||||
- architecture/ARCHITECTURE_CONSTITUTION.md
|
||||
- architecture/architecture-registry.yaml
|
||||
- architecture/adrs/**
|
||||
- ci/architecture/**
|
||||
- security/**
|
||||
|
||||
default_feature_task_authority:
|
||||
may_write: ["declared module paths", "module-owned tests"]
|
||||
may_not_change:
|
||||
- canonical_ownership
|
||||
- public_cross_module_contracts
|
||||
- protected_paths
|
||||
- third_party_dependencies
|
||||
- database_owner_roles
|
||||
- privileged_capabilities
|
||||
```
|
||||
|
||||
## 4.1 Registry enforcement required before large Codex implementation
|
||||
|
||||
Minimum deterministic checks:
|
||||
|
||||
1. Go import graph against `may_depend_on`/forbidden edges.
|
||||
2. No `/modules/*/domain` imports from adapters/runtime/provider packages.
|
||||
3. Migration scanner rejects cross-owner writes/FKs/triggers/views unless explicit approved exception.
|
||||
4. PostgreSQL role tests prove owner isolation.
|
||||
5. Diff-scope check against Codex Task Packet.
|
||||
6. Protected-path rule.
|
||||
7. Public contract change detection.
|
||||
8. Required CI guardrail health: missing checker result is failure, not pass.
|
||||
@@ -0,0 +1,150 @@
|
||||
registry_version: 1
|
||||
semantic_generation: 1
|
||||
architecture_generation: 1
|
||||
|
||||
modules:
|
||||
identity:
|
||||
id: mod.identity
|
||||
owns: [Identity, Actor, PrincipalBinding]
|
||||
database_schema: identity
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [platform.ids, platform.events]
|
||||
forbidden: [adapters.models, adapters.temporal]
|
||||
|
||||
authority:
|
||||
id: mod.authority
|
||||
owns: [Scope, AuthorityGrant, AuthorityValidation]
|
||||
database_schema: authority
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity, platform.ids, platform.events]
|
||||
|
||||
situation:
|
||||
id: mod.situation
|
||||
owns: [Situation, FocusBinding]
|
||||
database_schema: situation
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity, contracts.authority, contracts.work, contracts.capability]
|
||||
|
||||
work:
|
||||
id: mod.work
|
||||
owns: [Goal, Task, Decision]
|
||||
database_schema: work
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity, contracts.authority, platform.events]
|
||||
|
||||
epistemics:
|
||||
id: mod.epistemics
|
||||
owns: [Observation, Claim, Belief, Provenance]
|
||||
database_schema: epistemics
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity, contracts.artifact, platform.events]
|
||||
|
||||
continuity:
|
||||
id: mod.continuity
|
||||
owns: [Commitment, ProspectiveItem]
|
||||
database_schema: continuity
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.work, contracts.identity, contracts.authority, platform.events]
|
||||
|
||||
capability:
|
||||
id: mod.capability
|
||||
owns: [Capability, CapabilityBinding, CapabilityHealth]
|
||||
database_schema: capability
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity, contracts.authority, contracts.artifact]
|
||||
|
||||
commit:
|
||||
id: mod.commit
|
||||
owns: [ActionProposalRecord, AuthorizedAction, ActionAttemptRecord]
|
||||
database_schema: commit
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.authority, contracts.capability, contracts.work, platform.events]
|
||||
privileged: true
|
||||
|
||||
artifact:
|
||||
id: mod.artifact
|
||||
owns: [ArtifactMetadata, ArtifactLineage]
|
||||
database_schema: artifact
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity]
|
||||
|
||||
platform:
|
||||
allowed_packages:
|
||||
- platform.ids
|
||||
- platform.clock
|
||||
- platform.outbox
|
||||
- platform.inbox
|
||||
- platform.telemetry
|
||||
- platform.errors
|
||||
rule: "platform owns mechanisms, never domain meaning"
|
||||
|
||||
runtime_topology_v1:
|
||||
core_runtime:
|
||||
modules: [identity, situation, work, epistemics, capability, artifact]
|
||||
continuity_runtime:
|
||||
modules: [continuity]
|
||||
commit_runtime:
|
||||
modules: [authority, commit]
|
||||
isolation_reason: [secrets, external_mutation_authority, failure_isolation]
|
||||
cognitive_workers:
|
||||
modules: []
|
||||
role: "replaceable cognition/context compilation workers; no canonical ownership"
|
||||
|
||||
storage_topology_v1:
|
||||
postgres_cluster: assistant_primary
|
||||
schemas:
|
||||
identity: identity_role
|
||||
authority: authority_role
|
||||
situation: situation_role
|
||||
work: work_role
|
||||
epistemics: epistemics_role
|
||||
continuity: continuity_role
|
||||
capability: capability_role
|
||||
commit: commit_role
|
||||
artifact: artifact_role
|
||||
cross_owner_fk: forbidden_by_default
|
||||
cross_owner_write: forbidden
|
||||
cross_owner_application_join: forbidden
|
||||
|
||||
invariants:
|
||||
- id: INV-AUTH-001
|
||||
property: "No external mutation without current valid authority and target/revision checks"
|
||||
class: HARD
|
||||
enforcement: [commit_runtime, property_tests, secret_acl]
|
||||
- id: INV-OWN-001
|
||||
property: "Only semantic owner writes canonical state"
|
||||
class: HARD
|
||||
enforcement: [db_acl, architecture_linter]
|
||||
- id: INV-CONT-001
|
||||
property: "Future obligations survive workflow engine loss"
|
||||
class: HARD
|
||||
enforcement: [canonical_prospective_store, recovery_test]
|
||||
- id: INV-TOPO-001
|
||||
property: "Major bounded contracts preserve semantics across inproc and remote topology"
|
||||
class: HARD
|
||||
enforcement: [topology_equivalence_tests]
|
||||
- id: INV-EPI-001
|
||||
property: "Model output cannot directly become canonical fact/action"
|
||||
class: HARD
|
||||
enforcement: [package_boundaries, commit_apis, semantic_validation_tests]
|
||||
- id: INV-PROJ-001
|
||||
property: "Projection eventually converges from canonical state"
|
||||
class: CONVERGENCE
|
||||
enforcement: [projection_rebuild_tests, lag_metrics]
|
||||
|
||||
protected_paths:
|
||||
- architecture/ARCHITECTURE_CONSTITUTION.md
|
||||
- architecture/architecture-registry.yaml
|
||||
- architecture/adrs/**
|
||||
- ci/architecture/**
|
||||
- security/**
|
||||
|
||||
default_feature_task_authority:
|
||||
may_write: ["declared module paths", "module-owned tests"]
|
||||
may_not_change:
|
||||
- canonical_ownership
|
||||
- public_cross_module_contracts
|
||||
- protected_paths
|
||||
- third_party_dependencies
|
||||
- database_owner_roles
|
||||
- privileged_capabilities
|
||||
Binary file not shown.
@@ -0,0 +1,802 @@
|
||||
# Universal Assistant — Foundation Freeze Pack V1
|
||||
|
||||
Версия: 1.0
|
||||
Дата фиксации: 16 августа 2026
|
||||
Основание: Architecture Specification V2 + adversarial review + Codex-oriented development review
|
||||
Статус: **IMPLEMENTATION BASELINE CANDIDATE**
|
||||
|
||||
# 1. ARCHITECTURE_CONSTITUTION.md
|
||||
|
||||
## 1.1 Назначение
|
||||
|
||||
Этот документ — краткий набор законов репозитория и production-архитектуры. Он выше обычных task packets, примеров и локальных README. Codex не является архитектурным authority: он реализует только то, на что выдана task authority.
|
||||
|
||||
## 1.2 Иерархия архитектурной власти
|
||||
|
||||
1. Architecture Constitution.
|
||||
2. Accepted ADR / Foundation Decision.
|
||||
3. Machine-readable Architecture Registry.
|
||||
4. Versioned semantic contracts and state machines.
|
||||
5. Module architecture specification.
|
||||
6. Codex Task Packet.
|
||||
7. Implementation and examples.
|
||||
|
||||
Если нижний уровень противоречит верхнему, нижний считается ошибочным. Существующий код является evidence of implementation, но не authority to redefine architecture.
|
||||
|
||||
## 1.3 Неприкосновенные инварианты V1
|
||||
|
||||
1. LLM/model/provider не является Assistant.
|
||||
2. Capability не означает Authority.
|
||||
3. Observation, Claim, Belief, Prediction, Action и Outcome — разные семантические классы.
|
||||
4. Model output никогда напрямую не мутирует canonical semantic state и не выполняет external mutation.
|
||||
5. Любая реальная мутация проходит Proposal → semantic owner validation → Authority/Integrity checks → Commit → Executor → Outcome/Verification.
|
||||
6. Любая executable activity имеет live justification path к действующей Goal, Commitment, Responsibility или Policy.
|
||||
7. Отмена/суперсессия justification должна распространяться до зависимых работ перед следующим commit.
|
||||
8. Canonical owner — один на конкретный mutable semantic state в конкретной semantic generation.
|
||||
9. Другие модули не пишут canonical storage владельца напрямую.
|
||||
10. Cross-owner SQL writes, cross-owner FK и скрытая cross-owner trigger logic запрещены по умолчанию.
|
||||
11. Derived projections/caches/indexes не являются source of truth и должны быть rebuildable либо явно classified otherwise.
|
||||
12. Temporal/NATS/Redis/vector index/model memory не являются единственным местом хранения commitments, authority, semantic history или future obligations.
|
||||
13. Durable future obligations живут в canonical prospective state независимо от workflow/scheduler engine.
|
||||
14. External side effect должен быть idempotent/reconcilable; timeout не равен failure; UNKNOWN_OUTCOME — first-class state.
|
||||
15. No correctness property may depend on a shared in-process lock across bounded modules.
|
||||
16. Semantic topology, process topology, storage topology и model topology независимы и меняются отдельно.
|
||||
17. Co-location — deployment optimization, не архитектурная привилегия.
|
||||
18. Major bounded contracts должны быть serializable и не зависеть от Go pointers, shared memory, global variables или ambient process state.
|
||||
19. Core/domain не импортирует PostgreSQL/NATS/Temporal/MCP/model-provider packages.
|
||||
20. Никакого giant `common/shared` domain package; technical shared mechanisms допускаются только в `platform` и не владеют domain semantics.
|
||||
21. Semantic duplication предпочтительнее ложной абстракции.
|
||||
22. Event-driven взаимодействие используется ради temporal decoupling/history, а не потому, что два модуля разные.
|
||||
23. Public query не должен скрыто изменять canonical state.
|
||||
24. Durable background responsibility не реализуется unmanaged goroutine/timer.
|
||||
25. `context.Context` не переносит скрытый user/scope/authority/task state; это явные typed fields.
|
||||
26. Unknown/Conflict/NotApplicable/NotObserved не схлопываются в nil/false/default.
|
||||
27. Type system, package visibility, DB ACL и CI должны делать критические ошибки невозможными там, где это возможно.
|
||||
28. Architecture guardrails themselves are protected and cannot validate their own weakening alone.
|
||||
29. Codex ordinary feature task не меняет Constitution, Architecture Registry, public semantic topology, guardrails или canonical ownership без отдельного approved change.
|
||||
30. Codex может завершить задачу typed gap (`BLOCKED_BY_SPEC_GAP`, `BLOCKED_BY_ARCHITECTURE_GAP`) вместо архитектурного обхода.
|
||||
31. Every persistent thing has lifecycle, owner/justification, stop/retirement path and recovery semantics appropriate to criticality.
|
||||
32. Historical meaning is not rewritten by current interpretation; corrections/supersessions are appended/versioned.
|
||||
33. Newer/stronger model never automatically receives broader authority.
|
||||
34. More intelligence, more code, more services or more automations are not goals themselves.
|
||||
35. KEEP/WAIT/DO_NOTHING are valid decisions.
|
||||
36. The system must remain recoverable, exportable and replaceable.
|
||||
|
||||
## 1.4 Codex-specific hard prohibitions
|
||||
|
||||
- No direct cross-module DB access “temporarily”.
|
||||
- No cross-schema JOIN as application dependency between canonical owners.
|
||||
- No direct provider/model call outside Cognitive Gateway/adapters.
|
||||
- No external mutation outside Commit/Executor path.
|
||||
- No generic `SaveEntity(any)`, `Invoke(any)`, global Service Locator or God Context.
|
||||
- No semantic side effects in Go package `init()`.
|
||||
- No semantic durable timers using `time.After`/sleep in request process.
|
||||
- No production semantic behavior hidden only in middleware, SQL trigger or YAML DSL.
|
||||
- No silent retry of ambiguous external mutation.
|
||||
- No weakening of architecture/security tests inside unrelated feature task.
|
||||
- No new third-party dependency, canonical table, integration contract or privileged secret access without declared change classification.
|
||||
|
||||
## 1.5 Core change rule
|
||||
|
||||
Change the lowest layer that eliminates the causal class of the problem. Escalate only when necessary:
|
||||
|
||||
`data/config → local implementation → skill/strategy → module contract → ownership/schema → architecture → constitutional invariant`.
|
||||
|
||||
|
||||
---
|
||||
|
||||
# 2. DECISION_CONSOLIDATION_V1.md
|
||||
|
||||
## 2.1 Purpose
|
||||
|
||||
This inventory separates accepted decisions from explored ideas. Statuses are normative:
|
||||
|
||||
- **ACCEPTED_V1** — implementation may rely on it now.
|
||||
- **EXTENSION_POINT_V1** — foundation must not block it; no full implementation required.
|
||||
- **LATER** — explicitly excluded from current implementation scope.
|
||||
- **RESEARCH** — unresolved; Codex must not choose a permanent answer silently.
|
||||
- **REJECTED_V1** — do not implement this approach in V1.
|
||||
|
||||
## 2.2 Accepted foundation decisions
|
||||
|
||||
| ID | Decision | Status | Implementation consequence |
|
||||
|---|---|---|---|
|
||||
| FD-001 | Assistant ≠ LLM/model/provider/process | ACCEPTED_V1 | Cognitive providers are replaceable capabilities. |
|
||||
| FD-002 | Extractable Modular Architecture | ACCEPTED_V1 | Deploy together when useful, design bounded components separately. |
|
||||
| FD-003 | One PostgreSQL cluster may host V1, but canonical owners use separate schemas/roles | ACCEPTED_V1 | DB ACL physically prevents cross-owner writes. |
|
||||
| FD-004 | Cross-owner FK/trigger business logic forbidden by default | ACCEPTED_V1 | Relations use semantic IDs/contracts/projections. |
|
||||
| FD-005 | NATS/Temporal/Redis are implementation mechanisms, not semantic sources of truth | ACCEPTED_V1 | Canonical event/prospective state survives their loss. |
|
||||
| FD-006 | Major cross-boundary contracts are remote-capable | ACCEPTED_V1 | In-process and remote adapters satisfy same contract tests. |
|
||||
| FD-007 | No mandatory microservice-per-noun | ACCEPTED_V1 | Semantic modules and deployment runtimes are independent mappings. |
|
||||
| FD-008 | Commit/Executor is an early physical isolation boundary | ACCEPTED_V1 | External credentials and mutation authority are not globally available. |
|
||||
| FD-009 | Model output produces candidates/proposals, never direct canonical mutation | ACCEPTED_V1 | Typed semantic validation and commit gates. |
|
||||
| FD-010 | Canonical event/outbox pattern for cross-owner durable reactions | ACCEPTED_V1 | Owner-local ACID + outbox; no distributed ACID assumption. |
|
||||
| FD-011 | Prospective Memory canonicalized outside Temporal | ACCEPTED_V1 | Reminder/wake/commitment state rebuilds after workflow-engine loss. |
|
||||
| FD-012 | Identity, Principal, Scope and Authority are separate concepts | ACCEPTED_V1 | Strong typed IDs and explicit command envelopes. |
|
||||
| FD-013 | Goal/Task/Action/Outcome are distinct | ACCEPTED_V1 | Task completion does not imply goal/outcome success. |
|
||||
| FD-014 | Situation binds request to project/workspace/environment via runtime context, not keywords | ACCEPTED_V1 | Focus Isolation Suite is foundational acceptance test. |
|
||||
| FD-015 | Unknown and conflict states preserved | ACCEPTED_V1 | No premature boolean/default collapse. |
|
||||
| FD-016 | Bitemporal-capable history model | ACCEPTED_V1 | Separate event/observed/valid/recorded semantics where relevant. |
|
||||
| FD-017 | Canonical history append/supersede rather than retroactive semantic rewrite | ACCEPTED_V1 | Historical replay can reconstruct what was known then. |
|
||||
| FD-018 | Development through Codex requires Development Commit Gate | ACCEPTED_V1 | Task authority + CI/ACL/architecture checks precede merge. |
|
||||
| FD-019 | Architecture is executable | ACCEPTED_V1 | Critical rules need compiler/linter/ACL/test/observability enforcement. |
|
||||
| FD-020 | V1 uses explicit boring typed mechanisms over meta-frameworks/DSLs | ACCEPTED_V1 | No generic entity engine/universal workflow DSL. |
|
||||
| FD-021 | Contract/state ownership precedes DDL/protobuf | ACCEPTED_V1 | Schema is derived from semantic contracts. |
|
||||
| FD-022 | Walking Skeleton before broad subsystem implementation | ACCEPTED_V1 | Foundation validated vertically, not through stub zoo. |
|
||||
| FD-023 | Stronger future model is candidate, not automatic replacement | ACCEPTED_V1 | Eval/shadow/canary/promotion lifecycle. |
|
||||
| FD-024 | Architecture boundaries are hypotheses and may split/merge | ACCEPTED_V1 | Stable IDs/lineage; topology migration supported. |
|
||||
| FD-025 | Critical deterministic invariants are not delegated to free-form LLM judgment | ACCEPTED_V1 | Fuzzy cognition proposes; deterministic gates enforce. |
|
||||
|
||||
## 2.3 Extension points that must be preserved now
|
||||
|
||||
| ID | Topic | Status | V1 requirement |
|
||||
|---|---|---|---|
|
||||
| EP-001 | Portfolio/Trajectory engines | EXTENSION_POINT_V1 | Core goal/project/event model must permit later orchestration. |
|
||||
| EP-002 | Responsibilities/Risks/Opportunities/ControlLoops | EXTENSION_POINT_V1 | Semantic namespaces/lifecycles extensible; no full engines required. |
|
||||
| EP-003 | Self-development/self-migration | EXTENSION_POINT_V1 | Architecture/change provenance and replacement paths exist; autonomous self-editing absent. |
|
||||
| EP-004 | Collective/global learning | EXTENSION_POINT_V1 | Knowledge provenance/scope prevents unsafe future promotion. |
|
||||
| EP-005 | Multi-user/organization federation | EXTENSION_POINT_V1 | Actor/Principal/Scope not hardcoded to single user. |
|
||||
| EP-006 | Robotics/edge realtime control | EXTENSION_POINT_V1 | Capability/authority model supports out-of-process bounded controllers. |
|
||||
| EP-007 | Alternate coding agents | EXTENSION_POINT_V1 | Codex Task Packet provider-neutral; Codex adapter first. |
|
||||
| EP-008 | Semantic generation migration | EXTENSION_POINT_V1 | Version/schema IDs and migration framework exist; no universal ontology engine. |
|
||||
|
||||
## 2.4 Explicit V1 non-goals
|
||||
|
||||
The following are **LATER or RESEARCH**, not implementation requirements for Foundation V1:
|
||||
|
||||
- autonomous production self-modification;
|
||||
- autonomous installation of arbitrary plugins/components;
|
||||
- global collective learning between unrelated users;
|
||||
- Kubernetes requirement;
|
||||
- custom consensus protocol;
|
||||
- custom database or event-bus implementation;
|
||||
- full robotics stack;
|
||||
- universal ontology/DSL engine;
|
||||
- one service per semantic noun;
|
||||
- complete multi-tenant enterprise federation;
|
||||
- training custom foundation models as part of V1;
|
||||
- perfect global causal graph;
|
||||
- general autonomous portfolio optimization of human life;
|
||||
- fully autonomous Codex development swarm.
|
||||
|
||||
## 2.5 Rejected V1 approaches
|
||||
|
||||
- REJECTED: “Start as free modular monolith and split later.”
|
||||
- REJECTED: giant shared domain model/package.
|
||||
- REJECTED: cross-module joins because “same DB for now”.
|
||||
- REJECTED: event-sourcing everything by default.
|
||||
- REJECTED: microservices for every primitive.
|
||||
- REJECTED: direct LLM→tool→world mutation path.
|
||||
- REJECTED: Temporal workflow as canonical future obligation.
|
||||
- REJECTED: vector DB/Redis/model memory as canonical knowledge.
|
||||
- REJECTED: generic `entity(type,payload jsonb)` as primary Core model.
|
||||
- REJECTED: implicit global utility score for all goals.
|
||||
- REJECTED: relying on Codex remembering architecture from previous sessions.
|
||||
|
||||
|
||||
---
|
||||
|
||||
# 3. CORE_SEMANTIC_MODEL_V1.md
|
||||
|
||||
## 3.1 Scope
|
||||
|
||||
This is a V1 semantic freeze, not an eternal ontology. It defines the minimum durable concepts required to build the walking skeleton and preserve future migration freedom.
|
||||
|
||||
## 3.2 Canonical Core V1 concepts
|
||||
|
||||
### Identity
|
||||
Stable semantic identity independent of current name, locator, account, process or key. Supports identifier history and future merge/split corrections.
|
||||
|
||||
### Actor
|
||||
Entity capable of requests/actions/representation. Actor is not automatically a Principal.
|
||||
|
||||
### Principal
|
||||
The person/organization/accounting/legal/operational interest on whose behalf an action is performed. Same human may act for multiple principals.
|
||||
|
||||
### Scope
|
||||
Boundary for data, authority, project/context and permissible propagation.
|
||||
|
||||
### AuthorityGrant / AuthorityContext
|
||||
Evidence that an Actor may perform a class of actions for a Principal within Scope and validity conditions. Capability never implies grant.
|
||||
|
||||
### Situation
|
||||
Time-bounded interpretation of “what is happening now”: actor, interface/session, focus, project/workspace/environment bindings, active task, relevant resources, confidence/provenance. Situation is derived and expires/revalidates.
|
||||
|
||||
### Observation
|
||||
Something obtained from a source/sensor/tool/user report. Carries provenance, observed time, coverage and source semantics.
|
||||
|
||||
### Claim
|
||||
A proposition asserted by a source or derived system. It is not automatically fact.
|
||||
|
||||
### Belief/Assessment
|
||||
Current system interpretation supported by evidence; versioned/revisable and scoped.
|
||||
|
||||
### Intent
|
||||
Current request/desired change inferred from interaction; can be revised/superseded. Intent is not automatically long-term preference.
|
||||
|
||||
### Goal
|
||||
Desired world/state transition or outcome with lifecycle and lineage. Goal may be refined/superseded; method is not identical to goal.
|
||||
|
||||
### Task
|
||||
Durable unit of work that must survive session/process, coordinate actors, or carry lifecycle significance. Ephemeral reasoning steps are not Tasks.
|
||||
|
||||
### Decision
|
||||
Selection/commitment among alternatives with rationale/evidence refs where consequence warrants. Decision can have validity/revisit conditions.
|
||||
|
||||
### ActionProposal
|
||||
Structured candidate to change canonical state, communicate, allocate resources or mutate external world. Proposal has no execution authority by itself.
|
||||
|
||||
### AuthorizedAction
|
||||
Proposal that passed owner validation, current authority, revision/target/integrity checks and received commit identity.
|
||||
|
||||
### ActionAttempt
|
||||
Concrete execution attempt of an AuthorizedAction. Multiple attempts may serve one ActionIntent; attempt is not outcome.
|
||||
|
||||
### Outcome
|
||||
Observed/verifiable result attributable with stated confidence. Supports UNKNOWN/partial/provisional maturity.
|
||||
|
||||
### Commitment
|
||||
A future obligation/expectation created by promise/agreement/explicit user request/policy. Must have owner/beneficiary, fulfilment or renegotiation path and prospective continuity.
|
||||
|
||||
### ProspectiveItem
|
||||
Canonical future-relevance object used by Continuity for reminder/wake/review/expected transition. V1 may implement only reminder/wake subset; it remains independent of Temporal.
|
||||
|
||||
### Event
|
||||
Meaningful semantic transition or occurrence. Event is not a log line and not every low-level tool callback becomes Event.
|
||||
|
||||
### Artifact
|
||||
Durable content/resource with identity, content/schema metadata, provenance and scope. Payload may live outside PostgreSQL.
|
||||
|
||||
### Capability
|
||||
Declared/tested ability to observe, reason, communicate or act, with contracts, limits, provenance, health and allowed-use metadata. Capability availability ≠ authority.
|
||||
|
||||
### Revision
|
||||
Optimistic semantic version/precondition for mutable canonical objects and contracts.
|
||||
|
||||
### Provenance
|
||||
Lineage linking observations, claims, derived states, actions and artifacts to sources/derivations without treating copies as independent evidence.
|
||||
|
||||
## 3.3 Concepts intentionally NOT Core primitives in V1
|
||||
|
||||
These remain extension/derived concepts until evidence requires promotion: `Thread`, `Journey`, `Program`, `Trajectory`, `Portfolio`, `Responsibility`, `Risk`, `Opportunity`, `Monitor`, `ControlLoop`, `Routine`, `Theory`, `Frontier`. Foundation must permit them later but Codex must not materialize separate Core tables/services merely because they were discussed.
|
||||
|
||||
## 3.4 Required semantic distinctions
|
||||
|
||||
`Actor ≠ Principal`
|
||||
`Identity ≠ Identifier ≠ Locator`
|
||||
`Situation ≠ RequestContext ≠ ModelContext`
|
||||
`Observation ≠ Claim ≠ Belief`
|
||||
`Intent ≠ Goal ≠ Task`
|
||||
`Task ≠ ActionProposal ≠ AuthorizedAction ≠ ActionAttempt ≠ Outcome`
|
||||
`Commitment ≠ Reminder delivery`
|
||||
`Capability ≠ Authority`
|
||||
`Event ≠ Integration message ≠ Log`
|
||||
`Canonical state ≠ Projection ≠ Cache`
|
||||
`Prediction ≠ Expected-by-process ≠ Required-by-commitment`.
|
||||
|
||||
## 3.5 Required state semantics
|
||||
|
||||
### Goal lifecycle (minimum)
|
||||
`ACTIVE | WAITING | DORMANT | SATISFIED | SUPERSEDED | ABANDONED`
|
||||
|
||||
Transitions must preserve reason and lineage. `ABANDONED` does not mean failure; `SUPERSEDED` must point to successor when known.
|
||||
|
||||
### Task lifecycle (minimum)
|
||||
`PENDING | ACTIVE | WAITING | COMPLETED | CANCELLED | FAILED`
|
||||
|
||||
Task has `revision`, `justification_ref`, optional `wake_condition_ref`, owner and completion evidence. `WAITING` must say what it waits for or be explicitly dormant at higher level.
|
||||
|
||||
### Action lifecycle
|
||||
`PROPOSED → VALIDATED → AUTHORIZED/REJECTED → EXECUTING → SUCCEEDED | FAILED | UNKNOWN_OUTCOME | COMPENSATED`.
|
||||
|
||||
Retry preserves ActionIntent identity and creates a new attempt identity. `UNKNOWN_OUTCOME` blocks blind retry when duplicate effect is possible.
|
||||
|
||||
### Commitment lifecycle
|
||||
`ACTIVE | WAITING | AT_RISK | FULFILLED | RENEGOTIATED | REVOKED | EXPIRED`.
|
||||
|
||||
Future promise is not fulfilled by notification delivery alone unless the promise itself was only to notify.
|
||||
|
||||
### Prospective item lifecycle
|
||||
`REGISTERED | ARMED | TRIGGERED | REVALIDATING | DELIVERED/STARTED | SATISFIED | SUPPRESSED | EXPIRED`.
|
||||
|
||||
Trigger firing does not bypass relevance/authority revalidation.
|
||||
|
||||
## 3.6 Temporal model
|
||||
|
||||
Foundation must support distinguishing, where applicable:
|
||||
|
||||
- event/occurrence time;
|
||||
- observed time;
|
||||
- recorded time;
|
||||
- validity interval;
|
||||
- local-time intention vs absolute instant;
|
||||
- relative schedule relation (`after Event X + duration`) vs prematurely flattened timestamp.
|
||||
|
||||
Do not put four timestamps on every row blindly. Use common temporal value objects/contracts only where semantics require them.
|
||||
|
||||
## 3.7 Strong identifiers
|
||||
|
||||
Go Core should use distinct types for at least: `IdentityID`, `ActorID`, `PrincipalID`, `ScopeID`, `SituationID`, `GoalID`, `TaskID`, `CommitmentID`, `ActionIntentID`, `ActionAttemptID`, `ArtifactID`, `CapabilityID`, plus revision types. They serialize to language-neutral primitives.
|
||||
|
||||
## 3.8 Ownership baseline
|
||||
|
||||
| Semantic area | Canonical owner V1 | Notes |
|
||||
|---|---|---|
|
||||
| Identity/Actor/Principal bindings | Identity module | Other modules reference IDs/projections only. |
|
||||
| Scope/Authority grants | Authority module | Commit queries current validation; no hidden default authority. |
|
||||
| Situation/focus bindings | Situation module | Derived/ephemeral portions may use cache, but durable bindings/provenance explicitly classified. |
|
||||
| Goal/Task/Decision | Work module | Can later split; V1 owner chosen to preserve local consistency. |
|
||||
| Commitment/Prospective items | Continuity module | Temporal is execution engine adapter, not owner. |
|
||||
| Observations/Claims/Beliefs/Provenance | Epistemics module | Search/vector indexes derived. |
|
||||
| Action commit state | Commit module | External executor isolated. |
|
||||
| Artifact metadata/lineage | Artifact module or platform-owned artifact service | Payload storage replaceable. |
|
||||
| Capability registry/bindings | Capability module | Provider-specific adapters outside semantic owner. |
|
||||
|
||||
## 3.9 Consistency baseline
|
||||
|
||||
- Authority validation and Action authorization: strong owner-local consistency + revision preconditions.
|
||||
- Task state transitions: owner-local optimistic revision/CAS.
|
||||
- Cross-owner projections: eventual/rebuildable unless an explicit use case requires stronger semantics.
|
||||
- UI aggregate views: derived projections; no cross-owner canonical joins.
|
||||
- Integration reactions: owner-local commit + transactional outbox; consumers idempotent.
|
||||
- No global total event order requirement; causal/aggregate ordering only where needed.
|
||||
|
||||
|
||||
---
|
||||
|
||||
# 4. architecture-registry.yaml
|
||||
|
||||
Below is the normative starter registry. It is intentionally small. Tooling may extend the schema, but new relation types must have an enforcement/use case.
|
||||
|
||||
```yaml
|
||||
registry_version: 1
|
||||
semantic_generation: 1
|
||||
architecture_generation: 1
|
||||
|
||||
modules:
|
||||
identity:
|
||||
id: mod.identity
|
||||
owns: [Identity, Actor, PrincipalBinding]
|
||||
database_schema: identity
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [platform.ids, platform.events]
|
||||
forbidden: [adapters.models, adapters.temporal]
|
||||
|
||||
authority:
|
||||
id: mod.authority
|
||||
owns: [Scope, AuthorityGrant, AuthorityValidation]
|
||||
database_schema: authority
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity, platform.ids, platform.events]
|
||||
|
||||
situation:
|
||||
id: mod.situation
|
||||
owns: [Situation, FocusBinding]
|
||||
database_schema: situation
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity, contracts.work, contracts.capability]
|
||||
|
||||
work:
|
||||
id: mod.work
|
||||
owns: [Goal, Task, Decision]
|
||||
database_schema: work
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity, contracts.authority, platform.events]
|
||||
|
||||
epistemics:
|
||||
id: mod.epistemics
|
||||
owns: [Observation, Claim, Belief, Provenance]
|
||||
database_schema: epistemics
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity, contracts.artifact, platform.events]
|
||||
|
||||
continuity:
|
||||
id: mod.continuity
|
||||
owns: [Commitment, ProspectiveItem]
|
||||
database_schema: continuity
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.work, contracts.identity, contracts.authority, platform.events]
|
||||
|
||||
capability:
|
||||
id: mod.capability
|
||||
owns: [Capability, CapabilityBinding, CapabilityHealth]
|
||||
database_schema: capability
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity, contracts.authority, contracts.artifact]
|
||||
|
||||
commit:
|
||||
id: mod.commit
|
||||
owns: [ActionProposalRecord, AuthorizedAction, ActionAttemptRecord]
|
||||
database_schema: commit
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.authority, contracts.capability, contracts.work, platform.events]
|
||||
privileged: true
|
||||
|
||||
artifact:
|
||||
id: mod.artifact
|
||||
owns: [ArtifactMetadata, ArtifactLineage]
|
||||
database_schema: artifact
|
||||
boundary_class: remote_capable
|
||||
may_depend_on: [contracts.identity]
|
||||
|
||||
platform:
|
||||
allowed_packages:
|
||||
- platform.ids
|
||||
- platform.clock
|
||||
- platform.outbox
|
||||
- platform.inbox
|
||||
- platform.telemetry
|
||||
- platform.errors
|
||||
rule: "platform owns mechanisms, never domain meaning"
|
||||
|
||||
runtime_topology_v1:
|
||||
core_runtime:
|
||||
modules: [identity, situation, work, epistemics, capability, artifact]
|
||||
continuity_runtime:
|
||||
modules: [continuity]
|
||||
commit_runtime:
|
||||
modules: [authority, commit]
|
||||
isolation_reason: [secrets, external_mutation_authority, failure_isolation]
|
||||
cognitive_workers:
|
||||
modules: []
|
||||
role: "replaceable cognition/context compilation workers; no canonical ownership"
|
||||
|
||||
storage_topology_v1:
|
||||
postgres_cluster: assistant_primary
|
||||
schemas:
|
||||
identity: identity_role
|
||||
authority: authority_role
|
||||
situation: situation_role
|
||||
work: work_role
|
||||
epistemics: epistemics_role
|
||||
continuity: continuity_role
|
||||
capability: capability_role
|
||||
commit: commit_role
|
||||
artifact: artifact_role
|
||||
cross_owner_fk: forbidden_by_default
|
||||
cross_owner_write: forbidden
|
||||
cross_owner_application_join: forbidden
|
||||
|
||||
invariants:
|
||||
- id: INV-AUTH-001
|
||||
property: "No external mutation without current valid authority and target/revision checks"
|
||||
class: HARD
|
||||
enforcement: [commit_runtime, property_tests, secret_acl]
|
||||
- id: INV-OWN-001
|
||||
property: "Only semantic owner writes canonical state"
|
||||
class: HARD
|
||||
enforcement: [db_acl, architecture_linter]
|
||||
- id: INV-CONT-001
|
||||
property: "Future obligations survive workflow engine loss"
|
||||
class: HARD
|
||||
enforcement: [canonical_prospective_store, recovery_test]
|
||||
- id: INV-TOPO-001
|
||||
property: "Major bounded contracts preserve semantics across inproc and remote topology"
|
||||
class: HARD
|
||||
enforcement: [topology_equivalence_tests]
|
||||
- id: INV-EPI-001
|
||||
property: "Model output cannot directly become canonical fact/action"
|
||||
class: HARD
|
||||
enforcement: [package_boundaries, commit_apis, semantic_validation_tests]
|
||||
- id: INV-PROJ-001
|
||||
property: "Projection eventually converges from canonical state"
|
||||
class: CONVERGENCE
|
||||
enforcement: [projection_rebuild_tests, lag_metrics]
|
||||
|
||||
protected_paths:
|
||||
- architecture/ARCHITECTURE_CONSTITUTION.md
|
||||
- architecture/architecture-registry.yaml
|
||||
- architecture/adrs/**
|
||||
- ci/architecture/**
|
||||
- security/**
|
||||
|
||||
default_feature_task_authority:
|
||||
may_write: ["declared module paths", "module-owned tests"]
|
||||
may_not_change:
|
||||
- canonical_ownership
|
||||
- public_cross_module_contracts
|
||||
- protected_paths
|
||||
- third_party_dependencies
|
||||
- database_owner_roles
|
||||
- privileged_capabilities
|
||||
```
|
||||
|
||||
## 4.1 Registry enforcement required before large Codex implementation
|
||||
|
||||
Minimum deterministic checks:
|
||||
|
||||
1. Go import graph against `may_depend_on`/forbidden edges.
|
||||
2. No `/modules/*/domain` imports from adapters/runtime/provider packages.
|
||||
3. Migration scanner rejects cross-owner writes/FKs/triggers/views unless explicit approved exception.
|
||||
4. PostgreSQL role tests prove owner isolation.
|
||||
5. Diff-scope check against Codex Task Packet.
|
||||
6. Protected-path rule.
|
||||
7. Public contract change detection.
|
||||
8. Required CI guardrail health: missing checker result is failure, not pass.
|
||||
|
||||
|
||||
---
|
||||
|
||||
# 5. CODEX_DEVELOPMENT_CONTRACT.md
|
||||
|
||||
## 5.1 Role
|
||||
|
||||
Codex is an implementation capability. It can inspect, design locally, code, test and propose findings. It is **not** architectural authority and does not receive production authority merely because it can edit source.
|
||||
|
||||
## 5.2 Task Packet schema
|
||||
|
||||
Every non-trivial Codex implementation task must resolve to a packet similar to:
|
||||
|
||||
```yaml
|
||||
task_id: DEV-000123
|
||||
task_revision: 3
|
||||
architecture_revision: <git-sha-or-registry-revision>
|
||||
base_repo_revision: <git-sha>
|
||||
risk_tier: B
|
||||
intent: "..."
|
||||
requirement_ids: [REQ-...]
|
||||
allowed_change_scope:
|
||||
modules: [work]
|
||||
paths: [modules/work/**, contracts/work/**]
|
||||
forbidden_change_scope:
|
||||
paths: [architecture/**, security/**, modules/identity/**]
|
||||
allowed_architecture_delta:
|
||||
new_cross_module_dependencies: 0
|
||||
new_canonical_owners: 0
|
||||
new_privileges: 0
|
||||
contracts:
|
||||
consume: [contracts.identity@v1, contracts.authority@v1]
|
||||
may_change: []
|
||||
semantic_owner: work
|
||||
assumptions: []
|
||||
acceptance_scenarios: [SCN-...]
|
||||
required_tests: [unit, contract, architecture]
|
||||
terminal_gap_states:
|
||||
- BLOCKED_BY_SPEC_GAP
|
||||
- BLOCKED_BY_ARCHITECTURE_GAP
|
||||
- BLOCKED_BY_MISSING_CAPABILITY
|
||||
```
|
||||
|
||||
## 5.3 Risk tiers
|
||||
|
||||
- **Tier A — module-local:** no public contract/schema ownership/privilege changes. Fast path.
|
||||
- **Tier B — module contract/persistence local:** owner-local schema or stable port changes. Migration/contract tests.
|
||||
- **Tier C — cross-module:** integration contracts/events/topology interactions. Independent architecture review.
|
||||
- **Tier D — authority/canonical migration/external side effects:** adversarial/property/recovery tests and stricter promotion.
|
||||
- **Tier E — Core/guardrails/constitutional:** proposal first; changed verifier cannot self-certify.
|
||||
|
||||
## 5.4 Codex preflight for Tier B+
|
||||
|
||||
Before write, produce structured implementation plan containing:
|
||||
|
||||
- modules/files expected to change;
|
||||
- semantic owner(s);
|
||||
- contracts consumed/changed;
|
||||
- canonical state and state-machine transitions affected;
|
||||
- side effects/privileges;
|
||||
- persistence/migrations/events;
|
||||
- failure/retry/restart semantics;
|
||||
- tests to prove invariants.
|
||||
|
||||
Plan is machine-checked against Task Packet. Unexpected architecture delta becomes finding/gap.
|
||||
|
||||
## 5.5 Allowed local freedom
|
||||
|
||||
Inside an owned module Codex may choose ordinary data structures, algorithms, file decomposition and local refactoring, provided public contracts/invariants/task scope remain intact. Architecture defines constraints, not every function.
|
||||
|
||||
## 5.6 Mandatory Codex completion report
|
||||
|
||||
- changed files/modules;
|
||||
- contracts/schemas/events/dependencies/privileges touched;
|
||||
- tests actually executed (CI is authoritative evidence);
|
||||
- assumptions made;
|
||||
- known limitations;
|
||||
- unrelated findings not changed;
|
||||
- any specification/architecture gaps.
|
||||
|
||||
## 5.7 Development Commit Gate
|
||||
|
||||
Candidate patch → deterministic build/tests → architecture sentinel → DB/migration checks → contract checks → risk-specific review → exact-artifact promotion/merge.
|
||||
|
||||
Ordinary Codex tasks never write protected main directly. Promotion moves the evaluated artifact/commit, not a rebuilt unknown variant.
|
||||
|
||||
## 5.8 Architecture Sentinel responsibilities
|
||||
|
||||
Deterministically compare declared vs observed architecture:
|
||||
|
||||
- import/dependency graph;
|
||||
- DB writes/FKs/views/triggers;
|
||||
- event publishers/subscribers;
|
||||
- protected path and diff scope;
|
||||
- third-party dependency diff;
|
||||
- public contract diff;
|
||||
- privileged secret/capability access where enforceable;
|
||||
- guardrail execution health.
|
||||
|
||||
AI reviewer handles semantic smells that cannot be mechanically proven: God Ports, ownership leakage, false abstraction, orchestration absorbing domain semantics, hidden co-location assumptions, unsafe retry reasoning.
|
||||
|
||||
## 5.9 Architecture exceptions
|
||||
|
||||
No `nolint`/architecture ignore without registered exception ID containing reason, scope, expiry/removal condition. New debt cannot be introduced silently. Existing baseline debt can be ratcheted down.
|
||||
|
||||
## 5.10 Codex failure is valid
|
||||
|
||||
Codex is explicitly allowed to return a typed gap rather than “make it work somehow”. A gap becomes architecture/spec/research task and may revise the original task packet. This is preferred to an unapproved shortcut.
|
||||
|
||||
## 5.11 Cold Agent requirement
|
||||
|
||||
At major milestones, a fresh Codex session with no conversational history must be able to explain module ownership/boundaries and implement a bounded task using canonical repo artifacts only. Critical architecture cannot live only in chat history.
|
||||
|
||||
|
||||
---
|
||||
|
||||
# 6. WALKING_SKELETON_SPEC.md
|
||||
|
||||
## 6.1 Goal
|
||||
|
||||
Prove the Foundation through a small set of end-to-end semantic properties before broad implementation. Do not build all future modules/stubs first.
|
||||
|
||||
## 6.2 Skeleton topology
|
||||
|
||||
Initial process topology:
|
||||
|
||||
```text
|
||||
Client/Test Harness
|
||||
|
|
||||
Core Runtime
|
||||
- Identity
|
||||
- Situation
|
||||
- Work
|
||||
- Epistemics (minimal)
|
||||
- Capability registry (minimal)
|
||||
|
|
||||
+---- Cognitive Worker Adapter (deterministic fake first, real model later)
|
||||
|
|
||||
+---- Continuity Runtime ---- Temporal adapter (optional/replaceable)
|
||||
|
|
||||
+---- Commit Runtime (separate process, isolated credentials)
|
||||
|
|
||||
Test Executor
|
||||
```
|
||||
|
||||
One PostgreSQL cluster, separate owner schemas/roles. NATS may be used for integration events once owner-local outbox exists; skeleton must also prove semantics do not live only in NATS.
|
||||
|
||||
## 6.3 Scenario WS-001 — Focus Isolation / wrong-project prevention
|
||||
|
||||
**Given** one Actor has two simultaneously active Codex/workspace situations bound to Project/Goal contexts A and B. Both domains contain an identically named concept such as `temperature`.
|
||||
|
||||
**When** the identical user phrase is sent through each session without naming the project.
|
||||
|
||||
**Then** Situation resolution binds each request to its own session/workspace/project context using runtime bindings/provenance; no keyword shortcut is allowed; canonical writes carry target/revision/scope and cannot affect the other context.
|
||||
|
||||
Required failure cases:
|
||||
- stale focus binding;
|
||||
- two worktrees of same repository;
|
||||
- ambiguous target → typed ambiguity, no mutation;
|
||||
- Task revision changed between reasoning and commit → commit rejected/re-evaluated.
|
||||
|
||||
Acceptance property: **wrong-project mutation is mechanically prevented even if cognition proposes the wrong target**.
|
||||
|
||||
## 6.4 Scenario WS-002 — Durable prospective memory independent of Temporal
|
||||
|
||||
**Given** user creates a future reminder/commitment with semantic context and fulfilment condition.
|
||||
|
||||
**When** canonical Continuity transaction commits, process restarts, Temporal state is deleted/unavailable, then workflow infrastructure is rebuilt.
|
||||
|
||||
**Then** obligation remains in PostgreSQL canonical prospective state, is reconstructed, does not duplicate occurrence, revalidates relevance before delivery, and can distinguish `DELIVERED` from underlying `FULFILLED`.
|
||||
|
||||
Failure cases:
|
||||
- system offline past trigger;
|
||||
- 100 duplicate trigger messages;
|
||||
- goal superseded before trigger;
|
||||
- delivery channel unavailable;
|
||||
- recurrence missed during outage.
|
||||
|
||||
Acceptance property: **loss of workflow engine does not lose or blindly replay future obligations**.
|
||||
|
||||
## 6.5 Scenario WS-003 — Safe Action Commit and unknown outcome
|
||||
|
||||
**Given** cognition produces a structured external mutation proposal.
|
||||
|
||||
**When** Commit Runtime receives it.
|
||||
|
||||
**Then** it validates current Authority, Scope, Target identity, task/goal justification and relevant revisions before producing AuthorizedAction. Only isolated Executor has external mutation credentials.
|
||||
|
||||
Injected case: executor applies external effect but connection times out before acknowledgement.
|
||||
|
||||
Expected result: `UNKNOWN_OUTCOME`; no blind retry; reconciliation query/verification required. A retry uses same ActionIntentID and a new AttemptID only after semantics permit.
|
||||
|
||||
Acceptance property: **no external side effect can bypass authority/commit and timeout cannot cause duplicate mutation by default**.
|
||||
|
||||
## 6.6 Scenario WS-004 — Topology equivalence
|
||||
|
||||
Run WS-001/002/003 twice:
|
||||
|
||||
1. bounded modules co-located where allowed;
|
||||
2. Commit and Continuity accessed through remote adapters/processes.
|
||||
|
||||
Canonical semantic outcomes/invariants must be equivalent. Timing and expected temporary unavailability may differ; domain meaning must not.
|
||||
|
||||
Acceptance property: **process extraction does not require domain rewrite**.
|
||||
|
||||
## 6.7 Scenario WS-005 — No-LLM degraded continuity
|
||||
|
||||
Remove all cognitive providers.
|
||||
|
||||
System must still:
|
||||
- identify existing actors/sessions where deterministically available;
|
||||
- preserve events/state;
|
||||
- keep canonical commitments/prospective schedules;
|
||||
- perform deterministic authority/integrity checks;
|
||||
- expose degraded capability state;
|
||||
- avoid inventing new AI decisions/actions.
|
||||
|
||||
Acceptance property: **loss of cognition degrades intelligence, not continuity/integrity**.
|
||||
|
||||
## 6.8 Scenario WS-006 — Semantic evolution drill
|
||||
|
||||
Create a deliberately small v1→v2 contract/schema change in a non-critical skeleton concept. Prove:
|
||||
|
||||
- old historical object remains interpretable;
|
||||
- new writer/readers use new version;
|
||||
- unsupported semantics are explicit, not silently defaulted;
|
||||
- active live objects migrate/validate;
|
||||
- derived projections rebuild;
|
||||
- rollback/forward-fix mode is documented.
|
||||
|
||||
Acceptance property: **architecture evolution is tested as a transformation, not merely promised**.
|
||||
|
||||
## 6.9 Foundation Exit Criteria
|
||||
|
||||
Foundation V1 is eligible for freeze when all are true:
|
||||
|
||||
1. Fresh Codex session can implement a bounded feature from repository artifacts alone.
|
||||
2. Cross-owner DB write is physically denied.
|
||||
3. Wrong-project mutation fails even under adversarial cognition proposal.
|
||||
4. Stale/revoked authority cannot create AuthorizedAction.
|
||||
5. Duplicate/replay does not duplicate external side effects in covered semantics.
|
||||
6. Future obligation survives workflow-engine loss/rebuild.
|
||||
7. Core remains continuity-capable without any LLM.
|
||||
8. Same semantic scenarios pass in at least two process topologies.
|
||||
9. Provider can be swapped/faked without domain contract change.
|
||||
10. Declared and observed architecture graphs match or all drift has registered findings.
|
||||
11. One semantic contract migration drill succeeds.
|
||||
12. Architecture guardrail suite proves its own critical enforcement with negative tests.
|
||||
|
||||
|
||||
---
|
||||
|
||||
# 7. UNRESOLVED_QUESTIONS.md
|
||||
|
||||
These questions are intentionally unresolved. Codex must not silently turn temporary assumptions into permanent architecture.
|
||||
|
||||
| ID | Question | Status | Temporary V1 position | Blocking? | Revisit trigger |
|
||||
|---|---|---|---|---|---|
|
||||
| UQ-001 | Exact split of `Work` into Goal/Task/Decision modules | RESEARCH | One canonical Work owner for V1 | No | Contract churn/co-change/consistency pressure |
|
||||
| UQ-002 | Artifact metadata as separate module vs platform service | PROPOSED | Keep separate semantic owner if persistence begins | No | First large artifact integration |
|
||||
| UQ-003 | Exact NATS subject taxonomy | DEFERRED | Define only subjects required by skeleton | No | First durable cross-owner event |
|
||||
| UQ-004 | Exact Temporal workflow topology | DEFERRED | Temporal adapter behind Continuity; canonical prospective state outside | No | WS-002 implementation |
|
||||
| UQ-005 | gRPC vs another remote transport for internal calls | DEFERRED | Contracts language-neutral; choose simplest baseline during remote drill | No | WS-004 |
|
||||
| UQ-006 | Extent of canonical event archive vs per-owner transition history | RESEARCH | Do not event-source everything; retain meaningful events/outbox | No | Replay/recovery requirements emerge |
|
||||
| UQ-007 | Formal policy engine technology | LATER | Deterministic typed Authority/Commit rules in Go V1 | No | Policy complexity outgrows code safely |
|
||||
| UQ-008 | Vector store implementation | LATER | Search indexes derived; no foundation dependency | No | Epistemic retrieval slice |
|
||||
| UQ-009 | Redis requirement | LATER | Optional cache only; correctness must not depend on it | No | Performance evidence |
|
||||
| UQ-010 | Full Identity merge/split production workflow | EXTENSION_POINT | IDs/lineage schema must not preclude it; test simplified correction later | No | Multi-source identity pressure |
|
||||
| UQ-011 | Portfolio/Trajectory/Responsibility primitives promotion | RESEARCH | Not Core V1 | No | Repeated distinct lifecycle/authority need |
|
||||
| UQ-012 | Self-development automation | LATER | Development Control Plane external/manual-governed | No | Foundation + safe change/recovery mature |
|
||||
| UQ-013 | Multi-user organization governance | LATER | Actor/Principal/Scope designed generally; expose single-user V1 if desired | No | Actual shared workspace requirement |
|
||||
| UQ-014 | Canonical wire codec longevity | RESEARCH | Versioned schema/envelope; initial protobuf acceptable, not eternal identity | No | First non-Go module or major semantic migration |
|
||||
| UQ-015 | Exact data retention/privacy policy engine | RESEARCH | Store scope/provenance/sensitivity hooks; implement concrete policies per product deployment | No | Product/legal requirements |
|
||||
|
||||
## 7.1 Spec-gap protocol
|
||||
|
||||
If implementation encounters a semantically material unknown not listed here, Codex emits a `SpecificationGap` with:
|
||||
|
||||
- exact scenario;
|
||||
- current contract insufficiency;
|
||||
- smallest temporary safe behavior if one exists;
|
||||
- whether work can continue independently;
|
||||
- proposed alternatives without choosing permanent architecture.
|
||||
|
||||
No architecture gap is solved by creating an unowned table, generic JSON object, cross-module direct read/write, or hidden provider-specific field.
|
||||
\n\n---\n\n# 8. IMPLEMENTATION ORDER / NEXT TASKS\n\nThe first implementation sequence after this freeze pack is deliberately narrow:\n\n1. Create repository skeleton and protected architecture paths.\n2. Implement Architecture Registry validator and Go import boundary linter.\n3. Create PostgreSQL schemas/roles and negative ACL tests.\n4. Define strong IDs, revision/envelope primitives and platform outbox/inbox foundations.\n5. Define V1 semantic state machines and owner-local repository contracts for WS-001..003 only.\n6. Implement deterministic/fake cognition adapter and typed proposals.\n7. Build WS-001 Focus Isolation end-to-end.\n8. Build isolated Commit/Test-Executor path and WS-003.\n9. Build canonical Continuity/Prospective subset and WS-002.\n10. Add in-process/remote adapter contract suites and execute WS-004.\n11. Execute no-LLM and semantic migration drills WS-005/006.\n12. Only after Foundation Exit Criteria pass, expand into broader Epistemics/Context Compiler/Codex integration.\n\n**Codex must not be given a task like “implement the whole assistant”.** Each step above becomes a versioned Task Packet with a bounded architecture delta.\n
|
||||
@@ -0,0 +1,3 @@
|
||||
# Protected architecture CI
|
||||
|
||||
Changes here are Tier E. A feature task may not weaken or skip architecture checks. Missing guardrail execution is a failure, not a pass.
|
||||
@@ -0,0 +1,6 @@
|
||||
architecture/ARCHITECTURE_CONSTITUTION.md
|
||||
architecture/architecture-registry.yaml
|
||||
architecture/architecture-registry.json
|
||||
architecture/adrs/
|
||||
ci/architecture/
|
||||
security/
|
||||
@@ -0,0 +1,34 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"git.cin.su/m/Assistant/adapters/models"
|
||||
"git.cin.su/m/Assistant/runtime/health"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
addr := os.Getenv("LISTEN_ADDR")
|
||||
if addr == "" {
|
||||
addr = ":8083"
|
||||
}
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/healthz", health.Handler{Runtime: "cognitive-worker", SemanticGeneration: 1, ArchitectureGeneration: 1})
|
||||
mux.HandleFunc("POST /v1/proposals/deterministic", deterministicProposal)
|
||||
log.Printf("cognitive-worker listening on %s", addr)
|
||||
if err := http.ListenAndServe(addr, mux); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func deterministicProposal(w http.ResponseWriter, r *http.Request) {
|
||||
var request models.DeterministicRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, "invalid deterministic proposal request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(models.Propose(request))
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
"git.cin.su/m/Assistant/adapters/postgres"
|
||||
"git.cin.su/m/Assistant/contracts/authority"
|
||||
commitcontract "git.cin.su/m/Assistant/contracts/commit"
|
||||
"git.cin.su/m/Assistant/contracts/identity"
|
||||
authoritydomain "git.cin.su/m/Assistant/modules/authority/domain"
|
||||
commitdomain "git.cin.su/m/Assistant/modules/commit/domain"
|
||||
"git.cin.su/m/Assistant/runtime/health"
|
||||
)
|
||||
|
||||
type authorizationRequest struct {
|
||||
Proposal commitcontract.ActionProposal
|
||||
AuthorizedID commitcontract.AuthorizedActionID
|
||||
GrantID authority.GrantID
|
||||
PrincipalID identity.PrincipalID
|
||||
}
|
||||
type authorityValidator struct{}
|
||||
|
||||
func (authorityValidator) Validate(context authority.AuthorizationContext) error {
|
||||
return authoritydomain.ValidateGrant(context.Binding, context.Scope, context.Grant)
|
||||
}
|
||||
|
||||
func main() {
|
||||
addr := os.Getenv("LISTEN_ADDR")
|
||||
if addr == "" {
|
||||
addr = ":8082"
|
||||
}
|
||||
config := postgres.ContinuityConfig{Host: os.Getenv("POSTGRES_HOST"), Port: os.Getenv("POSTGRES_PORT"), Database: os.Getenv("POSTGRES_DATABASE")}
|
||||
config.User, config.Password = os.Getenv("POSTGRES_USER"), os.Getenv("POSTGRES_PASSWORD")
|
||||
repository, err := postgres.OpenCommit(context.Background(), config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer repository.Close()
|
||||
config.User, config.Password = os.Getenv("AUTHORITY_POSTGRES_USER"), os.Getenv("AUTHORITY_POSTGRES_PASSWORD")
|
||||
authorityRepository, err := postgres.OpenAuthority(context.Background(), config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer authorityRepository.Close()
|
||||
coreURL := os.Getenv("CORE_RUNTIME_URL")
|
||||
if coreURL == "" {
|
||||
log.Fatal("CORE_RUNTIME_URL is required")
|
||||
}
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/healthz", health.Handler{Runtime: "commit-runtime", SemanticGeneration: 1, ArchitectureGeneration: 1})
|
||||
mux.HandleFunc("POST /v1/authorized-actions", func(w http.ResponseWriter, r *http.Request) {
|
||||
var request authorizationRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, "invalid authorization request", 400)
|
||||
return
|
||||
}
|
||||
grant, scope, err := authorityRepository.LoadGrant(r.Context(), request.GrantID)
|
||||
if err != nil {
|
||||
http.Error(w, "authority grant not found", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
binding, err := loadJSON[identity.PrincipalBinding](r.Context(), coreURL+"/v1/principal-bindings/"+url.PathEscape(string(request.Proposal.ActorID))+"/"+url.PathEscape(string(request.PrincipalID)))
|
||||
if err != nil {
|
||||
http.Error(w, "identity binding unavailable", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
target, err := loadJSON[struct {
|
||||
TaskID string
|
||||
GoalID string
|
||||
ScopeID string
|
||||
Revision uint64
|
||||
}](r.Context(), coreURL+"/v1/tasks/"+url.PathEscape(string(request.Proposal.Target.TaskID)))
|
||||
if err != nil || target.TaskID != string(request.Proposal.Target.TaskID) || target.GoalID != string(request.Proposal.Target.GoalID) || target.ScopeID != string(request.Proposal.Target.ScopeID) || target.Revision != uint64(request.Proposal.Target.Revision) {
|
||||
http.Error(w, "work target is stale or unavailable", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
action, err := commitdomain.Authorize(request.Proposal, commitdomain.AuthorizationContext{Binding: binding, Scope: scope, Grant: grant}, authorityValidator{}, request.AuthorizedID)
|
||||
if err != nil {
|
||||
http.Error(w, "authorization denied", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
if err := repository.SaveAuthorized(r.Context(), action); err != nil {
|
||||
http.Error(w, "save authorized action", 500)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
})
|
||||
mux.HandleFunc("POST /v1/action-attempts", func(w http.ResponseWriter, r *http.Request) {
|
||||
var attempt commitcontract.ActionAttempt
|
||||
if err := json.NewDecoder(r.Body).Decode(&attempt); err != nil {
|
||||
http.Error(w, "invalid action attempt", 400)
|
||||
return
|
||||
}
|
||||
if attempt.State != commitcontract.ActionUnknownOutcome && attempt.State != commitcontract.ActionSucceeded && attempt.State != commitcontract.ActionFailed {
|
||||
http.Error(w, "attempt must have terminal outcome", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
if err := repository.SaveAttempt(r.Context(), attempt); err != nil {
|
||||
http.Error(w, "save action attempt", 500)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
})
|
||||
log.Printf("commit-runtime listening on %s", addr)
|
||||
if err := http.ListenAndServe(addr, mux); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func loadJSON[T any](ctx context.Context, endpoint string) (T, error) {
|
||||
var value T
|
||||
request, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
|
||||
if err != nil {
|
||||
return value, err
|
||||
}
|
||||
response, err := http.DefaultClient.Do(request)
|
||||
if err != nil {
|
||||
return value, err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
if response.StatusCode != http.StatusOK {
|
||||
return value, fmt.Errorf("remote query status %d", response.StatusCode)
|
||||
}
|
||||
return value, json.NewDecoder(response.Body).Decode(&value)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"git.cin.su/m/Assistant/adapters/postgres"
|
||||
"git.cin.su/m/Assistant/contracts/continuity"
|
||||
"git.cin.su/m/Assistant/runtime/health"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
addr := os.Getenv("LISTEN_ADDR")
|
||||
if addr == "" {
|
||||
addr = ":8081"
|
||||
}
|
||||
repository, err := postgres.OpenContinuity(context.Background(), postgres.ContinuityConfig{Host: os.Getenv("POSTGRES_HOST"), Port: os.Getenv("POSTGRES_PORT"), Database: os.Getenv("POSTGRES_DATABASE"), User: os.Getenv("POSTGRES_USER"), Password: os.Getenv("POSTGRES_PASSWORD")})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer repository.Close()
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/healthz", health.Handler{Runtime: "continuity-runtime", SemanticGeneration: 1, ArchitectureGeneration: 1})
|
||||
mux.HandleFunc("POST /v1/prospective-items", func(w http.ResponseWriter, r *http.Request) {
|
||||
var item continuity.ProspectiveItem
|
||||
if err := json.NewDecoder(r.Body).Decode(&item); err != nil {
|
||||
http.Error(w, "invalid prospective item", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := repository.Save(r.Context(), item); err != nil {
|
||||
http.Error(w, "save prospective item", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
})
|
||||
mux.HandleFunc("GET /v1/prospective-items/{id}", func(w http.ResponseWriter, r *http.Request) {
|
||||
item, err := repository.Load(r.Context(), continuity.ProspectiveItemID(r.PathValue("id")))
|
||||
if err != nil {
|
||||
http.Error(w, "prospective item not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(item)
|
||||
})
|
||||
log.Printf("continuity-runtime listening on %s", addr)
|
||||
if err := http.ListenAndServe(addr, mux); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"git.cin.su/m/Assistant/adapters/postgres"
|
||||
"git.cin.su/m/Assistant/contracts/capability"
|
||||
"git.cin.su/m/Assistant/contracts/identity"
|
||||
"git.cin.su/m/Assistant/contracts/situation"
|
||||
"git.cin.su/m/Assistant/contracts/work"
|
||||
capabilitydomain "git.cin.su/m/Assistant/modules/capability/domain"
|
||||
identitydomain "git.cin.su/m/Assistant/modules/identity/domain"
|
||||
situationdomain "git.cin.su/m/Assistant/modules/situation/domain"
|
||||
"git.cin.su/m/Assistant/runtime/health"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
addr := os.Getenv("LISTEN_ADDR")
|
||||
if addr == "" {
|
||||
addr = ":8080"
|
||||
}
|
||||
bootstrapToken, sessionKey := os.Getenv("CREATOR_BOOTSTRAP_TOKEN"), []byte(os.Getenv("CREATOR_SESSION_SIGNING_KEY"))
|
||||
repository, err := postgres.OpenSituation(context.Background(), postgres.ContinuityConfig{Host: os.Getenv("POSTGRES_HOST"), Port: os.Getenv("POSTGRES_PORT"), Database: os.Getenv("POSTGRES_DATABASE"), User: os.Getenv("POSTGRES_USER"), Password: os.Getenv("POSTGRES_PASSWORD")})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer repository.Close()
|
||||
workRepository, err := postgres.OpenWork(context.Background(), postgres.ContinuityConfig{Host: os.Getenv("POSTGRES_HOST"), Port: os.Getenv("POSTGRES_PORT"), Database: os.Getenv("POSTGRES_DATABASE"), User: os.Getenv("WORK_POSTGRES_USER"), Password: os.Getenv("WORK_POSTGRES_PASSWORD")})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer workRepository.Close()
|
||||
capabilityRepository, err := postgres.OpenCapability(context.Background(), postgres.ContinuityConfig{Host: os.Getenv("POSTGRES_HOST"), Port: os.Getenv("POSTGRES_PORT"), Database: os.Getenv("POSTGRES_DATABASE"), User: os.Getenv("CAPABILITY_POSTGRES_USER"), Password: os.Getenv("CAPABILITY_POSTGRES_PASSWORD")})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer capabilityRepository.Close()
|
||||
identityRepository, err := postgres.OpenIdentity(context.Background(), postgres.ContinuityConfig{Host: os.Getenv("POSTGRES_HOST"), Port: os.Getenv("POSTGRES_PORT"), Database: os.Getenv("POSTGRES_DATABASE"), User: os.Getenv("IDENTITY_POSTGRES_USER"), Password: os.Getenv("IDENTITY_POSTGRES_PASSWORD")})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer identityRepository.Close()
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/healthz", health.Handler{Runtime: "core-runtime", SemanticGeneration: 1, ArchitectureGeneration: 1})
|
||||
mux.HandleFunc("POST /v1/creator/sessions", func(w http.ResponseWriter, r *http.Request) {
|
||||
if !identitydomain.BootstrapMatches(bootstrapToken, bearerToken(r)) {
|
||||
http.Error(w, "creator authentication denied", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
token, session, err := identitydomain.IssueCreatorSession(sessionKey, time.Now(), 8*time.Hour)
|
||||
if err != nil {
|
||||
http.Error(w, "creator session unavailable", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(struct {
|
||||
Token string
|
||||
Session identity.CreatorSession
|
||||
}{token, session})
|
||||
})
|
||||
mux.HandleFunc("GET /v1/creator/sessions/current", func(w http.ResponseWriter, r *http.Request) {
|
||||
session, err := identitydomain.ValidateCreatorSession(sessionKey, bearerToken(r), time.Now())
|
||||
if err != nil {
|
||||
http.Error(w, "creator session denied", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(session)
|
||||
})
|
||||
mux.HandleFunc("GET /v1/principal-bindings/{actor}/{principal}", func(w http.ResponseWriter, r *http.Request) {
|
||||
binding, err := identityRepository.LoadBinding(r.Context(), identity.ActorID(r.PathValue("actor")), identity.PrincipalID(r.PathValue("principal")))
|
||||
if err != nil {
|
||||
http.Error(w, "principal binding not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(binding)
|
||||
})
|
||||
mux.HandleFunc("GET /v1/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
|
||||
target, err := workRepository.Load(r.Context(), work.TaskID(r.PathValue("id")))
|
||||
if err != nil {
|
||||
http.Error(w, "task not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(target)
|
||||
})
|
||||
mux.HandleFunc("POST /v1/capabilities/health", func(w http.ResponseWriter, r *http.Request) {
|
||||
var status capability.Health
|
||||
if err := json.NewDecoder(r.Body).Decode(&status); err != nil {
|
||||
http.Error(w, "invalid capability health", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := capabilitydomain.ValidateHealth(status); err != nil {
|
||||
http.Error(w, "invalid capability health", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := capabilityRepository.SaveHealth(r.Context(), status); err != nil {
|
||||
http.Error(w, "save capability health", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
})
|
||||
mux.HandleFunc("GET /v1/capabilities/{id}/health", func(w http.ResponseWriter, r *http.Request) {
|
||||
status, err := capabilityRepository.LoadHealth(r.Context(), capability.CapabilityID(r.PathValue("id")))
|
||||
if err != nil {
|
||||
http.Error(w, "capability health not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(status)
|
||||
})
|
||||
mux.HandleFunc("POST /v1/capabilities/health-projection/rebuild", func(w http.ResponseWriter, r *http.Request) {
|
||||
rebuilt, err := capabilityRepository.RebuildHealthProjection(r.Context())
|
||||
if err != nil {
|
||||
http.Error(w, "rebuild capability health projection", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(struct{ Rebuilt int64 }{rebuilt})
|
||||
})
|
||||
mux.HandleFunc("POST /v1/focus-bindings", func(w http.ResponseWriter, r *http.Request) {
|
||||
var binding situation.FocusBinding
|
||||
if err := json.NewDecoder(r.Body).Decode(&binding); err != nil {
|
||||
http.Error(w, "invalid focus binding", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := repository.Save(r.Context(), binding); err != nil {
|
||||
http.Error(w, "save focus binding", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
})
|
||||
mux.HandleFunc("GET /v1/focus", func(w http.ResponseWriter, r *http.Request) {
|
||||
runtime := situation.RuntimeBinding{SessionID: situation.SessionID(r.URL.Query().Get("session_id")), Workspace: situation.WorkspaceID(r.URL.Query().Get("workspace_id"))}
|
||||
bindings, err := repository.ByRuntime(r.Context(), runtime)
|
||||
if err != nil {
|
||||
http.Error(w, "load focus", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
focus, err := situationdomain.NewResolver(bindings).Resolve(runtime)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusConflict)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(focus)
|
||||
})
|
||||
mux.HandleFunc("POST /v1/tasks", func(w http.ResponseWriter, r *http.Request) {
|
||||
var target work.TaskTarget
|
||||
if err := json.NewDecoder(r.Body).Decode(&target); err != nil {
|
||||
http.Error(w, "invalid task", 400)
|
||||
return
|
||||
}
|
||||
if err := workRepository.Create(r.Context(), target); err != nil {
|
||||
http.Error(w, "create task", 500)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
})
|
||||
mux.HandleFunc("POST /v1/tasks/{id}/commit", func(w http.ResponseWriter, r *http.Request) {
|
||||
var target work.TaskTarget
|
||||
if err := json.NewDecoder(r.Body).Decode(&target); err != nil {
|
||||
http.Error(w, "invalid task commit", 400)
|
||||
return
|
||||
}
|
||||
target.TaskID = work.TaskID(r.PathValue("id"))
|
||||
revision, err := workRepository.Commit(r.Context(), target)
|
||||
if err != nil {
|
||||
http.Error(w, "task revision conflict", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(struct{ Revision work.TaskRevision }{revision})
|
||||
})
|
||||
mux.HandleFunc("POST /v1/focus-task-commits", func(w http.ResponseWriter, r *http.Request) {
|
||||
var request struct {
|
||||
SessionID situation.SessionID
|
||||
Workspace situation.WorkspaceID
|
||||
Target work.TaskTarget
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, "invalid guarded commit", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
bindings, err := repository.ByRuntime(r.Context(), situation.RuntimeBinding{SessionID: request.SessionID, Workspace: request.Workspace})
|
||||
if err != nil {
|
||||
http.Error(w, "load focus", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
focus, err := situationdomain.NewResolver(bindings).Resolve(situation.RuntimeBinding{SessionID: request.SessionID, Workspace: request.Workspace})
|
||||
if err != nil {
|
||||
http.Error(w, "focus unavailable", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
if err := situationdomain.ValidateTaskTarget(focus, request.Target); err != nil {
|
||||
http.Error(w, "target outside resolved focus", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
revision, err := workRepository.Commit(r.Context(), request.Target)
|
||||
if err != nil {
|
||||
http.Error(w, "task revision conflict", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(struct{ Revision work.TaskRevision }{revision})
|
||||
})
|
||||
log.Printf("core-runtime listening on %s", addr)
|
||||
if err := http.ListenAndServe(addr, mux); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func bearerToken(r *http.Request) string {
|
||||
value := r.Header.Get("Authorization")
|
||||
if !strings.HasPrefix(value, "Bearer ") {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimPrefix(value, "Bearer ")
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestArchitectureSentinelNegativeCases(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
importPath string
|
||||
want string
|
||||
}{
|
||||
{"domain infrastructure import", "git.cin.su/m/Assistant/adapters/postgres", "domain imports forbidden /adapters/"},
|
||||
{"cross-module implementation import", "git.cin.su/m/Assistant/modules/beta/domain", "cross-module implementation import beta"},
|
||||
{"undeclared contract dependency", "git.cin.su/m/Assistant/contracts/beta", "undeclared contract dependency contracts.beta"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
root := architectureFixture(t, test.importPath)
|
||||
err := checkArchitectureAt(root)
|
||||
if err == nil || !strings.Contains(err.Error(), test.want) {
|
||||
t.Fatalf("sentinel error = %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestArchitectureSentinelAcceptsDeclaredContractDependency(t *testing.T) {
|
||||
root := architectureFixture(t, "git.cin.su/m/Assistant/contracts/beta")
|
||||
registry := `{"registry_version":1,"semantic_generation":1,"architecture_generation":1,"modules":{"alpha":{"id":"mod.alpha","owns":[],"database_schema":"alpha","boundary_class":"remote_capable","may_depend_on":["contracts.beta"]},"beta":{"id":"mod.beta","owns":[],"database_schema":"beta","boundary_class":"remote_capable","may_depend_on":[]}}}`
|
||||
writeFixture(t, filepath.Join(root, "architecture", "architecture-registry.json"), registry)
|
||||
if err := checkArchitectureAt(root); err != nil {
|
||||
t.Fatalf("declared dependency rejected: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreflightRejectsProtectedPathBelowTierE(t *testing.T) {
|
||||
registry := Registry{ProtectedPaths: []string{"architecture/**", "security/**"}}
|
||||
taskPacket := TaskPacket{TaskID: "DEV-bad", RiskTier: "C", Intent: "weaken guardrail"}
|
||||
taskPacket.AllowedChangeScope.Paths = []string{"architecture/architecture-registry.json"}
|
||||
if err := validateTaskScope(taskPacket, registry); err == nil || !strings.Contains(err.Error(), "protected path") {
|
||||
t.Fatalf("protected path task error = %v", err)
|
||||
}
|
||||
taskPacket.RiskTier = "E"
|
||||
if err := validateTaskScope(taskPacket, registry); err != nil {
|
||||
t.Fatalf("Tier E protected path rejected: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func architectureFixture(t *testing.T, importPath string) string {
|
||||
t.Helper()
|
||||
root := t.TempDir()
|
||||
registry := `{"registry_version":1,"semantic_generation":1,"architecture_generation":1,"modules":{"alpha":{"id":"mod.alpha","owns":[],"database_schema":"alpha","boundary_class":"remote_capable","may_depend_on":[]},"beta":{"id":"mod.beta","owns":[],"database_schema":"beta","boundary_class":"remote_capable","may_depend_on":[]}}}`
|
||||
writeFixture(t, filepath.Join(root, "architecture", "architecture-registry.json"), registry)
|
||||
writeFixture(t, filepath.Join(root, "modules", "alpha", "domain", "fixture.go"), "package domain\nimport _ \""+importPath+"\"\n")
|
||||
return root
|
||||
}
|
||||
|
||||
func writeFixture(t *testing.T, path, content string) {
|
||||
t.Helper()
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io/fs"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Registry struct {
|
||||
RegistryVersion int `json:"registry_version"`
|
||||
SemanticGeneration int `json:"semantic_generation"`
|
||||
ArchitectureGeneration int `json:"architecture_generation"`
|
||||
Modules map[string]struct {
|
||||
ID string `json:"id"`
|
||||
Owns []string `json:"owns"`
|
||||
DatabaseSchema string `json:"database_schema"`
|
||||
BoundaryClass string `json:"boundary_class"`
|
||||
MayDependOn []string `json:"may_depend_on"`
|
||||
Forbidden []string `json:"forbidden"`
|
||||
} `json:"modules"`
|
||||
ProtectedPaths []string `json:"protected_paths"`
|
||||
}
|
||||
|
||||
type TaskPacket struct {
|
||||
TaskID string `json:"task_id"`
|
||||
RiskTier string `json:"risk_tier"`
|
||||
Intent string `json:"intent"`
|
||||
AllowedChangeScope struct {
|
||||
Paths []string `json:"paths"`
|
||||
} `json:"allowed_change_scope"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
var err error
|
||||
switch os.Args[1] {
|
||||
case "doctor":
|
||||
err = doctor()
|
||||
case "check-architecture":
|
||||
err = checkArchitecture()
|
||||
case "show-registry":
|
||||
err = showRegistry()
|
||||
case "preflight":
|
||||
err = preflight(os.Args[2:])
|
||||
default:
|
||||
usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "devctl:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Println("devctl doctor | check-architecture | show-registry | preflight -task <json>")
|
||||
}
|
||||
|
||||
func loadRegistry() (Registry, error) {
|
||||
b, err := os.ReadFile("architecture/architecture-registry.json")
|
||||
if err != nil {
|
||||
return Registry{}, err
|
||||
}
|
||||
var r Registry
|
||||
if err = json.Unmarshal(b, &r); err != nil {
|
||||
return Registry{}, err
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func doctor() error {
|
||||
r, err := loadRegistry()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("architecture generation=%d semantic generation=%d modules=%d\n", r.ArchitectureGeneration, r.SemanticGeneration, len(r.Modules))
|
||||
for _, tool := range []string{"git", "go", "docker"} {
|
||||
p, e := exec.LookPath(tool)
|
||||
if e != nil {
|
||||
fmt.Printf("WARN: %s not found\n", tool)
|
||||
} else {
|
||||
fmt.Printf("OK: %s -> %s\n", tool, p)
|
||||
}
|
||||
}
|
||||
cmd := exec.Command("git", "remote", "get-url", "origin")
|
||||
out, e := cmd.CombinedOutput()
|
||||
if e == nil {
|
||||
fmt.Printf("git origin: %s", out)
|
||||
} else {
|
||||
fmt.Println("WARN: git origin not configured; run scripts/bootstrap.ps1")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func showRegistry() error {
|
||||
r, e := loadRegistry()
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
b, _ := json.MarshalIndent(r, "", " ")
|
||||
fmt.Println(string(b))
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkArchitecture() error {
|
||||
return checkArchitectureAt(".")
|
||||
}
|
||||
|
||||
func checkArchitectureAt(root string) error {
|
||||
b, err := os.ReadFile(filepath.Join(root, "architecture", "architecture-registry.json"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var r Registry
|
||||
if err := json.Unmarshal(b, &r); err != nil {
|
||||
return err
|
||||
}
|
||||
var violations []string
|
||||
err = filepath.WalkDir(filepath.Join(root, "modules"), func(path string, d fs.DirEntry, e error) error {
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
if d.IsDir() || !strings.HasSuffix(path, ".go") {
|
||||
return nil
|
||||
}
|
||||
relative, err := filepath.Rel(root, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
parts := strings.Split(filepath.ToSlash(relative), "/")
|
||||
if len(parts) < 3 {
|
||||
return nil
|
||||
}
|
||||
owner := parts[1]
|
||||
module, ok := r.Modules[owner]
|
||||
if !ok {
|
||||
violations = append(violations, relative+": unknown module owner "+owner)
|
||||
return nil
|
||||
}
|
||||
parsed, parseErr := parser.ParseFile(token.NewFileSet(), path, nil, parser.ImportsOnly)
|
||||
if parseErr != nil {
|
||||
return parseErr
|
||||
}
|
||||
allowed := map[string]bool{}
|
||||
for _, dependency := range module.MayDependOn {
|
||||
allowed[dependency] = true
|
||||
}
|
||||
for _, imported := range parsed.Imports {
|
||||
importPath := strings.Trim(imported.Path.Value, "\"")
|
||||
if strings.Contains(filepath.ToSlash(relative), "/domain/") {
|
||||
for _, bad := range []string{"/adapters/", "/runtime/", "/cmd/"} {
|
||||
if strings.Contains(importPath, "git.cin.su/m/Assistant"+bad) {
|
||||
violations = append(violations, relative+": domain imports forbidden "+bad)
|
||||
}
|
||||
}
|
||||
}
|
||||
modulePrefix := "git.cin.su/m/Assistant/modules/"
|
||||
if strings.HasPrefix(importPath, modulePrefix) {
|
||||
other := strings.Split(strings.TrimPrefix(importPath, modulePrefix), "/")[0]
|
||||
if other != owner {
|
||||
violations = append(violations, relative+": cross-module implementation import "+other)
|
||||
}
|
||||
}
|
||||
contractPrefix := "git.cin.su/m/Assistant/contracts/"
|
||||
if strings.HasPrefix(importPath, contractPrefix) {
|
||||
contractOwner := strings.Split(strings.TrimPrefix(importPath, contractPrefix), "/")[0]
|
||||
if contractOwner != owner && !allowed["contracts."+contractOwner] {
|
||||
violations = append(violations, relative+": undeclared contract dependency contracts."+contractOwner)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(violations) > 0 {
|
||||
for _, v := range violations {
|
||||
fmt.Println("VIOLATION:", v)
|
||||
}
|
||||
return fmt.Errorf("%d architecture violation(s): %s", len(violations), strings.Join(violations, "; "))
|
||||
}
|
||||
fmt.Println("architecture checks: OK")
|
||||
return nil
|
||||
}
|
||||
|
||||
func preflight(args []string) error {
|
||||
var task string
|
||||
for i := 0; i < len(args); i++ {
|
||||
if args[i] == "-task" && i+1 < len(args) {
|
||||
task = args[i+1]
|
||||
i++
|
||||
}
|
||||
}
|
||||
if task == "" {
|
||||
return errors.New("missing -task <json>")
|
||||
}
|
||||
b, err := os.ReadFile(task)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var taskPacket TaskPacket
|
||||
if err = json.Unmarshal(b, &taskPacket); err != nil {
|
||||
return fmt.Errorf("task packet must be valid JSON in V1: %w", err)
|
||||
}
|
||||
if taskPacket.TaskID == "" || taskPacket.Intent == "" || taskPacket.RiskTier == "" {
|
||||
return errors.New("task packet missing task_id, intent, or risk_tier")
|
||||
}
|
||||
registry, err := loadRegistry()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateTaskScope(taskPacket, registry); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("task preflight loaded: %s tier=%s\n", taskPacket.TaskID, taskPacket.RiskTier)
|
||||
return checkArchitecture()
|
||||
}
|
||||
|
||||
func validateTaskScope(taskPacket TaskPacket, registry Registry) error {
|
||||
if taskPacket.RiskTier == "E" {
|
||||
return nil
|
||||
}
|
||||
for _, allowed := range taskPacket.AllowedChangeScope.Paths {
|
||||
allowed = filepath.ToSlash(allowed)
|
||||
for _, protected := range registry.ProtectedPaths {
|
||||
prefix := strings.TrimSuffix(filepath.ToSlash(protected), "/**")
|
||||
if allowed == prefix || strings.HasPrefix(allowed, prefix+"/") {
|
||||
return fmt.Errorf("task %s tier %s may not write protected path %s", taskPacket.TaskID, taskPacket.RiskTier, allowed)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package artifact
|
||||
|
||||
// Package artifact contains stable boundary contract types for the artifact semantic owner.
|
||||
@@ -0,0 +1,5 @@
|
||||
package artifact
|
||||
|
||||
import "git.cin.su/m/Assistant/platform/ids"
|
||||
|
||||
type ArtifactID ids.ID
|
||||
@@ -0,0 +1,3 @@
|
||||
package authority
|
||||
|
||||
// Package authority contains stable boundary contract types for the authority semantic owner.
|
||||
@@ -0,0 +1,40 @@
|
||||
package authority
|
||||
|
||||
import (
|
||||
"git.cin.su/m/Assistant/contracts/identity"
|
||||
"git.cin.su/m/Assistant/platform/ids"
|
||||
)
|
||||
|
||||
type ScopeID ids.ID
|
||||
type GrantID ids.ID
|
||||
type AuthorityRevision uint64
|
||||
|
||||
type GrantClass string
|
||||
|
||||
const GrantClassCreator GrantClass = "CREATOR"
|
||||
|
||||
type Scope struct {
|
||||
ID ScopeID
|
||||
Global bool
|
||||
Label string
|
||||
}
|
||||
|
||||
// AuthorityGrant is an explicit, revisable authority record. It does not
|
||||
// derive authority from a capability, provider, or product display name.
|
||||
type AuthorityGrant struct {
|
||||
ID GrantID
|
||||
ActorID identity.ActorID
|
||||
PrincipalID identity.PrincipalID
|
||||
ScopeID ScopeID
|
||||
Class GrantClass
|
||||
Revision AuthorityRevision
|
||||
Active bool
|
||||
}
|
||||
|
||||
// AuthorizationContext is the Authority owner's serializable validation
|
||||
// input. Consumers do not depend directly on Identity's contract.
|
||||
type AuthorizationContext struct {
|
||||
Binding identity.PrincipalBinding
|
||||
Scope Scope
|
||||
Grant AuthorityGrant
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package capability
|
||||
|
||||
// Package capability contains stable boundary contract types for the capability semantic owner.
|
||||
@@ -0,0 +1,39 @@
|
||||
package capability
|
||||
|
||||
import "git.cin.su/m/Assistant/platform/ids"
|
||||
|
||||
type CapabilityID ids.ID
|
||||
type CapabilityBindingID ids.ID
|
||||
|
||||
type HealthState string
|
||||
|
||||
const (
|
||||
HealthAvailable HealthState = "AVAILABLE"
|
||||
HealthDegraded HealthState = "DEGRADED"
|
||||
HealthUnavailable HealthState = "UNAVAILABLE"
|
||||
)
|
||||
|
||||
type HealthReason string
|
||||
|
||||
const (
|
||||
ReasonCognitiveProvidersUnavailable HealthReason = "COGNITIVE_PROVIDERS_UNAVAILABLE"
|
||||
ReasonNone HealthReason = "NONE"
|
||||
)
|
||||
|
||||
type HealthSemanticVersion int
|
||||
|
||||
const (
|
||||
HealthV1 HealthSemanticVersion = 1
|
||||
HealthV2 HealthSemanticVersion = 2
|
||||
)
|
||||
|
||||
// Health is the Capability owner's current, explicit statement about whether
|
||||
// a capability can be used. It is not an authority grant.
|
||||
type Health struct {
|
||||
CapabilityID CapabilityID
|
||||
State HealthState
|
||||
Reason HealthReason
|
||||
Revision int64
|
||||
SemanticVersion HealthSemanticVersion
|
||||
ObservedAtUnixMillis *int64
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package commit
|
||||
|
||||
// Package commit contains stable boundary contract types for the commit semantic owner.
|
||||
@@ -0,0 +1,51 @@
|
||||
package commit
|
||||
|
||||
import (
|
||||
"git.cin.su/m/Assistant/contracts/authority"
|
||||
"git.cin.su/m/Assistant/contracts/capability"
|
||||
"git.cin.su/m/Assistant/contracts/identity"
|
||||
"git.cin.su/m/Assistant/contracts/work"
|
||||
"git.cin.su/m/Assistant/platform/ids"
|
||||
)
|
||||
|
||||
type ActionIntentID ids.ID
|
||||
type ActionAttemptID ids.ID
|
||||
type AttemptID = ActionAttemptID
|
||||
type AuthorizedActionID ids.ID
|
||||
|
||||
type ActionState string
|
||||
|
||||
const (
|
||||
ActionProposed ActionState = "PROPOSED"
|
||||
ActionAuthorized ActionState = "AUTHORIZED"
|
||||
ActionExecuting ActionState = "EXECUTING"
|
||||
ActionSucceeded ActionState = "SUCCEEDED"
|
||||
ActionFailed ActionState = "FAILED"
|
||||
ActionUnknownOutcome ActionState = "UNKNOWN_OUTCOME"
|
||||
)
|
||||
|
||||
type ExternalOperation string
|
||||
|
||||
type ActionProposal struct {
|
||||
IntentID ActionIntentID
|
||||
ActorID identity.ActorID
|
||||
CapabilityID capability.CapabilityID
|
||||
Target work.TaskTarget
|
||||
Operation ExternalOperation
|
||||
State ActionState
|
||||
}
|
||||
|
||||
type AuthorizedAction struct {
|
||||
ID AuthorizedActionID
|
||||
Proposal ActionProposal
|
||||
GrantID authority.GrantID
|
||||
ScopeID authority.ScopeID
|
||||
State ActionState
|
||||
}
|
||||
|
||||
type ActionAttempt struct {
|
||||
ID ActionAttemptID
|
||||
AuthorizedID AuthorizedActionID
|
||||
IntentID ActionIntentID
|
||||
State ActionState
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package continuity
|
||||
|
||||
// Package continuity contains stable boundary contract types for the continuity semantic owner.
|
||||
@@ -0,0 +1,38 @@
|
||||
package continuity
|
||||
|
||||
import (
|
||||
"git.cin.su/m/Assistant/contracts/authority"
|
||||
"git.cin.su/m/Assistant/contracts/identity"
|
||||
"git.cin.su/m/Assistant/contracts/work"
|
||||
"git.cin.su/m/Assistant/platform/ids"
|
||||
)
|
||||
|
||||
type CommitmentID ids.ID
|
||||
type ProspectiveItemID ids.ID
|
||||
type ProspectiveRevision uint64
|
||||
|
||||
type ProspectiveState string
|
||||
|
||||
const (
|
||||
ProspectiveRegistered ProspectiveState = "REGISTERED"
|
||||
ProspectiveArmed ProspectiveState = "ARMED"
|
||||
ProspectiveTriggered ProspectiveState = "TRIGGERED"
|
||||
ProspectiveRevalidating ProspectiveState = "REVALIDATING"
|
||||
ProspectiveDelivered ProspectiveState = "DELIVERED"
|
||||
ProspectiveSatisfied ProspectiveState = "SATISFIED"
|
||||
ProspectiveSuppressed ProspectiveState = "SUPPRESSED"
|
||||
ProspectiveExpired ProspectiveState = "EXPIRED"
|
||||
)
|
||||
|
||||
// ProspectiveItem is canonical future relevance. TriggerAtUnixMillis is an
|
||||
// absolute instant; scheduling engines are derived delivery mechanisms only.
|
||||
type ProspectiveItem struct {
|
||||
ID ProspectiveItemID
|
||||
CommitmentID CommitmentID
|
||||
OwnerPrincipalID identity.PrincipalID
|
||||
ScopeID authority.ScopeID
|
||||
GoalID work.GoalID
|
||||
TriggerAtUnixMillis int64
|
||||
State ProspectiveState
|
||||
Revision ProspectiveRevision
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package epistemics
|
||||
|
||||
// Package epistemics contains stable boundary contract types for the epistemics semantic owner.
|
||||
@@ -0,0 +1,7 @@
|
||||
package epistemics
|
||||
|
||||
import "git.cin.su/m/Assistant/platform/ids"
|
||||
|
||||
type ObservationID ids.ID
|
||||
type ClaimID ids.ID
|
||||
type BeliefID ids.ID
|
||||
@@ -0,0 +1,3 @@
|
||||
package identity
|
||||
|
||||
// Package identity contains stable boundary contract types for the identity semantic owner.
|
||||
@@ -0,0 +1,7 @@
|
||||
package identity
|
||||
|
||||
type CreatorSession struct {
|
||||
ActorID ActorID
|
||||
PrincipalID PrincipalID
|
||||
ExpiresAtUnix int64
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package identity
|
||||
|
||||
import "git.cin.su/m/Assistant/platform/ids"
|
||||
|
||||
type ActorID ids.ID
|
||||
type PrincipalID ids.ID
|
||||
type IdentityID ids.ID
|
||||
|
||||
// PrincipalBinding keeps the operational actor separate from the interest on
|
||||
// whose behalf it acts. A Creator is not exempt from this distinction.
|
||||
type PrincipalBinding struct {
|
||||
ActorID ActorID
|
||||
PrincipalID PrincipalID
|
||||
Active bool
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package situation
|
||||
|
||||
// Package situation contains stable boundary contract types for the situation semantic owner.
|
||||
@@ -0,0 +1,32 @@
|
||||
package situation
|
||||
|
||||
import (
|
||||
"git.cin.su/m/Assistant/contracts/authority"
|
||||
"git.cin.su/m/Assistant/contracts/identity"
|
||||
"git.cin.su/m/Assistant/contracts/work"
|
||||
"git.cin.su/m/Assistant/platform/ids"
|
||||
)
|
||||
|
||||
type SituationID ids.ID
|
||||
type FocusBindingID ids.ID
|
||||
type SessionID ids.ID
|
||||
type WorkspaceID ids.ID
|
||||
type ProjectID ids.ID
|
||||
|
||||
// FocusBinding is the situation-owned runtime context used to resolve a request.
|
||||
// User text is deliberately absent: textual similarity is not a routing signal.
|
||||
type FocusBinding struct {
|
||||
ID FocusBindingID
|
||||
ActorID identity.ActorID
|
||||
SessionID SessionID
|
||||
Workspace WorkspaceID
|
||||
ProjectID ProjectID
|
||||
GoalID work.GoalID
|
||||
ScopeID authority.ScopeID
|
||||
Active bool
|
||||
}
|
||||
|
||||
type RuntimeBinding struct {
|
||||
SessionID SessionID
|
||||
Workspace WorkspaceID
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package work
|
||||
|
||||
// Package work contains stable boundary contract types for the work semantic owner.
|
||||
@@ -0,0 +1,19 @@
|
||||
package work
|
||||
|
||||
import (
|
||||
"git.cin.su/m/Assistant/contracts/authority"
|
||||
"git.cin.su/m/Assistant/platform/ids"
|
||||
)
|
||||
|
||||
type GoalID ids.ID
|
||||
type TaskID ids.ID
|
||||
type DecisionID ids.ID
|
||||
type TaskRevision uint64
|
||||
|
||||
// TaskTarget carries the integrity context that a work-owned mutation must match.
|
||||
type TaskTarget struct {
|
||||
TaskID TaskID
|
||||
GoalID GoalID
|
||||
ScopeID authority.ScopeID
|
||||
Revision TaskRevision
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# Database ownership
|
||||
|
||||
One PostgreSQL cluster is allowed in V1, but each semantic owner has its own schema and login role. Cross-owner writes and application JOINs are forbidden. Cross-owner foreign keys are forbidden by default.
|
||||
|
||||
`bootstrap/001_roles_and_schemas.sql` is run by a dedicated bootstrap/migration principal, never automatically by every runtime replica.
|
||||
@@ -0,0 +1,146 @@
|
||||
-- Bootstrap roles/schemas. Replace passwords via ALTER ROLE from secret-aware deployment; do not hardcode real passwords.
|
||||
BEGIN;
|
||||
DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'identity_role') THEN CREATE ROLE identity_role LOGIN; END IF; END $$;
|
||||
CREATE SCHEMA IF NOT EXISTS identity AUTHORIZATION identity_role;
|
||||
REVOKE ALL ON SCHEMA identity FROM PUBLIC;
|
||||
DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'authority_role') THEN CREATE ROLE authority_role LOGIN; END IF; END $$;
|
||||
CREATE SCHEMA IF NOT EXISTS authority AUTHORIZATION authority_role;
|
||||
REVOKE ALL ON SCHEMA authority FROM PUBLIC;
|
||||
DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'situation_role') THEN CREATE ROLE situation_role LOGIN; END IF; END $$;
|
||||
CREATE SCHEMA IF NOT EXISTS situation AUTHORIZATION situation_role;
|
||||
REVOKE ALL ON SCHEMA situation FROM PUBLIC;
|
||||
DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'work_role') THEN CREATE ROLE work_role LOGIN; END IF; END $$;
|
||||
CREATE SCHEMA IF NOT EXISTS work AUTHORIZATION work_role;
|
||||
REVOKE ALL ON SCHEMA work FROM PUBLIC;
|
||||
DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'epistemics_role') THEN CREATE ROLE epistemics_role LOGIN; END IF; END $$;
|
||||
CREATE SCHEMA IF NOT EXISTS epistemics AUTHORIZATION epistemics_role;
|
||||
REVOKE ALL ON SCHEMA epistemics FROM PUBLIC;
|
||||
DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'continuity_role') THEN CREATE ROLE continuity_role LOGIN; END IF; END $$;
|
||||
CREATE SCHEMA IF NOT EXISTS continuity AUTHORIZATION continuity_role;
|
||||
REVOKE ALL ON SCHEMA continuity FROM PUBLIC;
|
||||
DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'capability_role') THEN CREATE ROLE capability_role LOGIN; END IF; END $$;
|
||||
CREATE SCHEMA IF NOT EXISTS capability AUTHORIZATION capability_role;
|
||||
REVOKE ALL ON SCHEMA capability FROM PUBLIC;
|
||||
DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'commit_role') THEN CREATE ROLE commit_role LOGIN; END IF; END $$;
|
||||
CREATE SCHEMA IF NOT EXISTS commit AUTHORIZATION commit_role;
|
||||
REVOKE ALL ON SCHEMA commit FROM PUBLIC;
|
||||
DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'artifact_role') THEN CREATE ROLE artifact_role LOGIN; END IF; END $$;
|
||||
CREATE SCHEMA IF NOT EXISTS artifact AUTHORIZATION artifact_role;
|
||||
REVOKE ALL ON SCHEMA artifact FROM PUBLIC;
|
||||
|
||||
SET ROLE identity_role;
|
||||
CREATE TABLE IF NOT EXISTS identity.actors (
|
||||
actor_id TEXT PRIMARY KEY,
|
||||
display_name TEXT NOT NULL,
|
||||
recorded_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS identity.principals (
|
||||
principal_id TEXT PRIMARY KEY,
|
||||
display_name TEXT NOT NULL,
|
||||
recorded_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS identity.principal_bindings (
|
||||
actor_id TEXT NOT NULL,
|
||||
principal_id TEXT NOT NULL,
|
||||
active BOOLEAN NOT NULL,
|
||||
recorded_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (actor_id, principal_id)
|
||||
);
|
||||
INSERT INTO identity.actors (actor_id, display_name) VALUES ('domovoy-creator-actor', 'Domovoy Creator') ON CONFLICT (actor_id) DO NOTHING;
|
||||
INSERT INTO identity.principals (principal_id, display_name) VALUES ('domovoy-creator-principal', 'Domovoy Creator Principal') ON CONFLICT (principal_id) DO NOTHING;
|
||||
INSERT INTO identity.principal_bindings (actor_id, principal_id, active) VALUES ('domovoy-creator-actor', 'domovoy-creator-principal', TRUE) ON CONFLICT (actor_id, principal_id) DO NOTHING;
|
||||
RESET ROLE;
|
||||
|
||||
SET ROLE authority_role;
|
||||
CREATE TABLE IF NOT EXISTS authority.scopes (
|
||||
scope_id TEXT PRIMARY KEY,
|
||||
label TEXT NOT NULL,
|
||||
global_scope BOOLEAN NOT NULL,
|
||||
recorded_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS authority.authority_grants (
|
||||
grant_id TEXT PRIMARY KEY,
|
||||
actor_id TEXT NOT NULL,
|
||||
principal_id TEXT NOT NULL,
|
||||
scope_id TEXT NOT NULL,
|
||||
grant_class TEXT NOT NULL,
|
||||
revision BIGINT NOT NULL,
|
||||
active BOOLEAN NOT NULL,
|
||||
valid_from TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
valid_until TIMESTAMPTZ,
|
||||
CHECK (revision > 0)
|
||||
);
|
||||
INSERT INTO authority.scopes (scope_id, label, global_scope) VALUES ('domovoy-global-scope', 'All Domovoy scopes', TRUE) ON CONFLICT (scope_id) DO NOTHING;
|
||||
INSERT INTO authority.authority_grants (grant_id, actor_id, principal_id, scope_id, grant_class, revision, active) VALUES ('domovoy-creator-grant', 'domovoy-creator-actor', 'domovoy-creator-principal', 'domovoy-global-scope', 'CREATOR', 1, TRUE) ON CONFLICT (grant_id) DO NOTHING;
|
||||
RESET ROLE;
|
||||
|
||||
SET ROLE commit_role;
|
||||
CREATE TABLE IF NOT EXISTS commit.authorized_actions (
|
||||
authorized_action_id TEXT PRIMARY KEY, action_intent_id TEXT NOT NULL,
|
||||
state TEXT NOT NULL, revision BIGINT NOT NULL, CHECK (revision > 0)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS commit.action_attempts (
|
||||
action_attempt_id TEXT PRIMARY KEY, authorized_action_id TEXT NOT NULL,
|
||||
action_intent_id TEXT NOT NULL, state TEXT NOT NULL,
|
||||
recorded_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
RESET ROLE;
|
||||
|
||||
SET ROLE work_role;
|
||||
CREATE TABLE IF NOT EXISTS work.tasks (
|
||||
task_id TEXT PRIMARY KEY, goal_id TEXT NOT NULL, scope_id TEXT NOT NULL,
|
||||
revision BIGINT NOT NULL, CHECK (revision > 0)
|
||||
);
|
||||
RESET ROLE;
|
||||
|
||||
SET ROLE situation_role;
|
||||
CREATE TABLE IF NOT EXISTS situation.focus_bindings (
|
||||
focus_binding_id TEXT PRIMARY KEY,
|
||||
actor_id TEXT NOT NULL,
|
||||
session_id TEXT NOT NULL,
|
||||
workspace_id TEXT NOT NULL,
|
||||
project_id TEXT NOT NULL,
|
||||
goal_id TEXT NOT NULL,
|
||||
scope_id TEXT NOT NULL,
|
||||
active BOOLEAN NOT NULL,
|
||||
recorded_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
RESET ROLE;
|
||||
|
||||
SET ROLE capability_role;
|
||||
CREATE TABLE IF NOT EXISTS capability.health (
|
||||
capability_id TEXT PRIMARY KEY,
|
||||
state TEXT NOT NULL,
|
||||
reason TEXT NOT NULL,
|
||||
revision BIGINT NOT NULL,
|
||||
semantic_version INTEGER NOT NULL,
|
||||
observed_at_unix_millis BIGINT,
|
||||
recorded_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CHECK (revision > 0),
|
||||
CHECK ((semantic_version = 1 AND observed_at_unix_millis IS NULL) OR (semantic_version = 2 AND observed_at_unix_millis > 0))
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS capability.health_projection (
|
||||
capability_id TEXT PRIMARY KEY,
|
||||
state TEXT NOT NULL,
|
||||
reason TEXT NOT NULL,
|
||||
revision BIGINT NOT NULL,
|
||||
semantic_version INTEGER NOT NULL,
|
||||
observed_at_unix_millis BIGINT
|
||||
);
|
||||
RESET ROLE;
|
||||
|
||||
SET ROLE continuity_role;
|
||||
CREATE TABLE IF NOT EXISTS continuity.prospective_items (
|
||||
prospective_item_id TEXT PRIMARY KEY,
|
||||
commitment_id TEXT NOT NULL,
|
||||
owner_principal_id TEXT NOT NULL,
|
||||
scope_id TEXT NOT NULL,
|
||||
goal_id TEXT NOT NULL,
|
||||
trigger_at_unix_millis BIGINT NOT NULL,
|
||||
state TEXT NOT NULL,
|
||||
revision BIGINT NOT NULL,
|
||||
recorded_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CHECK (revision > 0)
|
||||
);
|
||||
RESET ROLE;
|
||||
COMMIT;
|
||||
@@ -0,0 +1,16 @@
|
||||
BEGIN;
|
||||
SET ROLE identity_role;
|
||||
CREATE TABLE IF NOT EXISTS identity.actors (actor_id TEXT PRIMARY KEY, display_name TEXT NOT NULL, recorded_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP);
|
||||
CREATE TABLE IF NOT EXISTS identity.principals (principal_id TEXT PRIMARY KEY, display_name TEXT NOT NULL, recorded_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP);
|
||||
CREATE TABLE IF NOT EXISTS identity.principal_bindings (actor_id TEXT NOT NULL, principal_id TEXT NOT NULL, active BOOLEAN NOT NULL, recorded_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (actor_id, principal_id));
|
||||
INSERT INTO identity.actors (actor_id, display_name) VALUES ('domovoy-creator-actor', 'Domovoy Creator') ON CONFLICT (actor_id) DO NOTHING;
|
||||
INSERT INTO identity.principals (principal_id, display_name) VALUES ('domovoy-creator-principal', 'Domovoy Creator Principal') ON CONFLICT (principal_id) DO NOTHING;
|
||||
INSERT INTO identity.principal_bindings (actor_id, principal_id, active) VALUES ('domovoy-creator-actor', 'domovoy-creator-principal', TRUE) ON CONFLICT (actor_id, principal_id) DO NOTHING;
|
||||
RESET ROLE;
|
||||
SET ROLE authority_role;
|
||||
CREATE TABLE IF NOT EXISTS authority.scopes (scope_id TEXT PRIMARY KEY, label TEXT NOT NULL, global_scope BOOLEAN NOT NULL, recorded_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP);
|
||||
CREATE TABLE IF NOT EXISTS authority.authority_grants (grant_id TEXT PRIMARY KEY, actor_id TEXT NOT NULL, principal_id TEXT NOT NULL, scope_id TEXT NOT NULL, grant_class TEXT NOT NULL, revision BIGINT NOT NULL, active BOOLEAN NOT NULL, valid_from TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, valid_until TIMESTAMPTZ, CHECK (revision > 0));
|
||||
INSERT INTO authority.scopes (scope_id, label, global_scope) VALUES ('domovoy-global-scope', 'All Domovoy scopes', TRUE) ON CONFLICT (scope_id) DO NOTHING;
|
||||
INSERT INTO authority.authority_grants (grant_id, actor_id, principal_id, scope_id, grant_class, revision, active) VALUES ('domovoy-creator-grant', 'domovoy-creator-actor', 'domovoy-creator-principal', 'domovoy-global-scope', 'CREATOR', 1, TRUE) ON CONFLICT (grant_id) DO NOTHING;
|
||||
RESET ROLE;
|
||||
COMMIT;
|
||||
@@ -0,0 +1,16 @@
|
||||
BEGIN;
|
||||
SET ROLE continuity_role;
|
||||
CREATE TABLE IF NOT EXISTS continuity.prospective_items (
|
||||
prospective_item_id TEXT PRIMARY KEY,
|
||||
commitment_id TEXT NOT NULL,
|
||||
owner_principal_id TEXT NOT NULL,
|
||||
scope_id TEXT NOT NULL,
|
||||
goal_id TEXT NOT NULL,
|
||||
trigger_at_unix_millis BIGINT NOT NULL,
|
||||
state TEXT NOT NULL,
|
||||
revision BIGINT NOT NULL,
|
||||
recorded_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CHECK (revision > 0)
|
||||
);
|
||||
RESET ROLE;
|
||||
COMMIT;
|
||||
@@ -0,0 +1,15 @@
|
||||
BEGIN;
|
||||
SET ROLE situation_role;
|
||||
CREATE TABLE IF NOT EXISTS situation.focus_bindings (
|
||||
focus_binding_id TEXT PRIMARY KEY,
|
||||
actor_id TEXT NOT NULL,
|
||||
session_id TEXT NOT NULL,
|
||||
workspace_id TEXT NOT NULL,
|
||||
project_id TEXT NOT NULL,
|
||||
goal_id TEXT NOT NULL,
|
||||
scope_id TEXT NOT NULL,
|
||||
active BOOLEAN NOT NULL,
|
||||
recorded_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
RESET ROLE;
|
||||
COMMIT;
|
||||
@@ -0,0 +1,5 @@
|
||||
BEGIN;
|
||||
SET ROLE work_role;
|
||||
CREATE TABLE IF NOT EXISTS work.tasks (task_id TEXT PRIMARY KEY, goal_id TEXT NOT NULL, scope_id TEXT NOT NULL, revision BIGINT NOT NULL, CHECK (revision > 0));
|
||||
RESET ROLE;
|
||||
COMMIT;
|
||||
@@ -0,0 +1,6 @@
|
||||
BEGIN;
|
||||
SET ROLE commit_role;
|
||||
CREATE TABLE IF NOT EXISTS commit.authorized_actions (authorized_action_id TEXT PRIMARY KEY, action_intent_id TEXT NOT NULL, state TEXT NOT NULL, revision BIGINT NOT NULL, CHECK (revision > 0));
|
||||
CREATE TABLE IF NOT EXISTS commit.action_attempts (action_attempt_id TEXT PRIMARY KEY, authorized_action_id TEXT NOT NULL, action_intent_id TEXT NOT NULL, state TEXT NOT NULL, recorded_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP);
|
||||
RESET ROLE;
|
||||
COMMIT;
|
||||
@@ -0,0 +1,12 @@
|
||||
BEGIN;
|
||||
SET ROLE capability_role;
|
||||
CREATE TABLE IF NOT EXISTS capability.health (
|
||||
capability_id TEXT PRIMARY KEY,
|
||||
state TEXT NOT NULL,
|
||||
reason TEXT NOT NULL,
|
||||
revision BIGINT NOT NULL,
|
||||
recorded_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CHECK (revision > 0)
|
||||
);
|
||||
RESET ROLE;
|
||||
COMMIT;
|
||||
@@ -0,0 +1,18 @@
|
||||
BEGIN;
|
||||
SET ROLE capability_role;
|
||||
ALTER TABLE capability.health ADD COLUMN IF NOT EXISTS semantic_version INTEGER;
|
||||
ALTER TABLE capability.health ADD COLUMN IF NOT EXISTS observed_at_unix_millis BIGINT;
|
||||
UPDATE capability.health SET semantic_version = 1 WHERE semantic_version IS NULL;
|
||||
ALTER TABLE capability.health ALTER COLUMN semantic_version SET NOT NULL;
|
||||
ALTER TABLE capability.health DROP CONSTRAINT IF EXISTS capability_health_semantic_shape;
|
||||
ALTER TABLE capability.health ADD CONSTRAINT capability_health_semantic_shape CHECK ((semantic_version = 1 AND observed_at_unix_millis IS NULL) OR (semantic_version = 2 AND observed_at_unix_millis > 0));
|
||||
CREATE TABLE IF NOT EXISTS capability.health_projection (
|
||||
capability_id TEXT PRIMARY KEY,
|
||||
state TEXT NOT NULL,
|
||||
reason TEXT NOT NULL,
|
||||
revision BIGINT NOT NULL,
|
||||
semantic_version INTEGER NOT NULL,
|
||||
observed_at_unix_millis BIGINT
|
||||
);
|
||||
RESET ROLE;
|
||||
COMMIT;
|
||||
@@ -0,0 +1,3 @@
|
||||
# artifact migrations
|
||||
|
||||
Only the `artifact` semantic owner may introduce canonical writes in this schema. Migrations must be explicit, versioned and tested.
|
||||
@@ -0,0 +1,3 @@
|
||||
# authority migrations
|
||||
|
||||
Only the `authority` semantic owner may introduce canonical writes in this schema. Migrations must be explicit, versioned and tested.
|
||||
@@ -0,0 +1,3 @@
|
||||
# capability migrations
|
||||
|
||||
Only the `capability` semantic owner may introduce canonical writes in this schema. Migrations must be explicit, versioned and tested.
|
||||
@@ -0,0 +1,3 @@
|
||||
# commit migrations
|
||||
|
||||
Only the `commit` semantic owner may introduce canonical writes in this schema. Migrations must be explicit, versioned and tested.
|
||||
@@ -0,0 +1,3 @@
|
||||
# continuity migrations
|
||||
|
||||
Only the `continuity` semantic owner may introduce canonical writes in this schema. Migrations must be explicit, versioned and tested.
|
||||
@@ -0,0 +1,3 @@
|
||||
# epistemics migrations
|
||||
|
||||
Only the `epistemics` semantic owner may introduce canonical writes in this schema. Migrations must be explicit, versioned and tested.
|
||||
@@ -0,0 +1,3 @@
|
||||
# identity migrations
|
||||
|
||||
Only the `identity` semantic owner may introduce canonical writes in this schema. Migrations must be explicit, versioned and tested.
|
||||
@@ -0,0 +1,3 @@
|
||||
# situation migrations
|
||||
|
||||
Only the `situation` semantic owner may introduce canonical writes in this schema. Migrations must be explicit, versioned and tested.
|
||||
@@ -0,0 +1,3 @@
|
||||
# work migrations
|
||||
|
||||
Only the `work` semantic owner may introduce canonical writes in this schema. Migrations must be explicit, versioned and tested.
|
||||
@@ -0,0 +1,14 @@
|
||||
# Portainer deployment target
|
||||
|
||||
Target: `https://docker.cin.su`.
|
||||
|
||||
The initial recommended stack file is `deploy/docker-compose.prod.yml`.
|
||||
|
||||
## Credential behavior for Codex
|
||||
|
||||
1. Try existing `PORTAINER_API_KEY` / endpoint metadata from the environment or an already configured secret store.
|
||||
2. Do not print the key.
|
||||
3. Do not scan unrelated repositories for plaintext passwords.
|
||||
4. If no usable credential exists, ask the user for a Portainer API key (preferred) and endpoint ID if needed.
|
||||
|
||||
The exact Portainer API call used for automated stack creation must be verified against the Portainer version actually running before Codex implements automation. Until then deployment through Portainer's Git/stack UI is valid.
|
||||
@@ -0,0 +1,95 @@
|
||||
name: assistant-dev
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18.6-alpine
|
||||
environment:
|
||||
POSTGRES_DB: assistant
|
||||
POSTGRES_USER: assistant_bootstrap
|
||||
POSTGRES_PASSWORD: ${POSTGRES_SUPERUSER_PASSWORD:-assistant_dev_only}
|
||||
CONTINUITY_DB_PASSWORD: ${CONTINUITY_DB_PASSWORD:-assistant_continuity_dev_only}
|
||||
IDENTITY_DB_PASSWORD: ${IDENTITY_DB_PASSWORD:-assistant_identity_dev_only}
|
||||
AUTHORITY_DB_PASSWORD: ${AUTHORITY_DB_PASSWORD:-assistant_authority_dev_only}
|
||||
SITUATION_DB_PASSWORD: ${SITUATION_DB_PASSWORD:-assistant_situation_dev_only}
|
||||
WORK_DB_PASSWORD: ${WORK_DB_PASSWORD:-assistant_work_dev_only}
|
||||
CAPABILITY_DB_PASSWORD: ${CAPABILITY_DB_PASSWORD:-assistant_capability_dev_only}
|
||||
COMMIT_DB_PASSWORD: ${COMMIT_DB_PASSWORD:-assistant_commit_dev_only}
|
||||
ports: ["15432:5432"]
|
||||
volumes:
|
||||
- assistant_pg_dev:/var/lib/postgresql
|
||||
- ../database/bootstrap/001_roles_and_schemas.sql:/docker-entrypoint-initdb.d/001_roles_and_schemas.sql:ro
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U assistant_bootstrap -d assistant"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 20
|
||||
|
||||
nats:
|
||||
image: nats:2-alpine
|
||||
command: ["-js", "-m", "8222"]
|
||||
ports: ["14222:4222", "19222:8222"]
|
||||
|
||||
core-runtime:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: deploy/images/runtime.Dockerfile
|
||||
args: { TARGET: core-runtime }
|
||||
environment:
|
||||
LISTEN_ADDR: ":8080"
|
||||
POSTGRES_HOST: postgres
|
||||
POSTGRES_PORT: "5432"
|
||||
POSTGRES_DATABASE: assistant
|
||||
POSTGRES_USER: situation_role
|
||||
POSTGRES_PASSWORD: ${SITUATION_DB_PASSWORD:-assistant_situation_dev_only}
|
||||
IDENTITY_POSTGRES_USER: identity_role
|
||||
IDENTITY_POSTGRES_PASSWORD: ${IDENTITY_DB_PASSWORD:-assistant_identity_dev_only}
|
||||
CREATOR_BOOTSTRAP_TOKEN: ${CREATOR_BOOTSTRAP_TOKEN:-creator_dev_only_replace_me}
|
||||
CREATOR_SESSION_SIGNING_KEY: ${CREATOR_SESSION_SIGNING_KEY:-creator_dev_only_signing_key_32_bytes}
|
||||
WORK_POSTGRES_USER: work_role
|
||||
WORK_POSTGRES_PASSWORD: ${WORK_DB_PASSWORD:-assistant_work_dev_only}
|
||||
CAPABILITY_POSTGRES_USER: capability_role
|
||||
CAPABILITY_POSTGRES_PASSWORD: ${CAPABILITY_DB_PASSWORD:-assistant_capability_dev_only}
|
||||
ports: ["19080:8080"]
|
||||
depends_on:
|
||||
postgres: { condition: service_healthy }
|
||||
|
||||
continuity-runtime:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: deploy/images/runtime.Dockerfile
|
||||
args: { TARGET: continuity-runtime }
|
||||
environment:
|
||||
LISTEN_ADDR: ":8081"
|
||||
POSTGRES_HOST: postgres
|
||||
POSTGRES_PORT: "5432"
|
||||
POSTGRES_DATABASE: assistant
|
||||
POSTGRES_USER: continuity_role
|
||||
POSTGRES_PASSWORD: ${CONTINUITY_DB_PASSWORD:-assistant_continuity_dev_only}
|
||||
ports: ["19081:8081"]
|
||||
|
||||
commit-runtime:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: deploy/images/runtime.Dockerfile
|
||||
args: { TARGET: commit-runtime }
|
||||
environment:
|
||||
LISTEN_ADDR: ":8082"
|
||||
POSTGRES_HOST: postgres
|
||||
POSTGRES_PORT: "5432"
|
||||
POSTGRES_DATABASE: assistant
|
||||
POSTGRES_USER: commit_role
|
||||
POSTGRES_PASSWORD: ${COMMIT_DB_PASSWORD:-assistant_commit_dev_only}
|
||||
AUTHORITY_POSTGRES_USER: authority_role
|
||||
AUTHORITY_POSTGRES_PASSWORD: ${AUTHORITY_DB_PASSWORD:-assistant_authority_dev_only}
|
||||
CORE_RUNTIME_URL: http://core-runtime:8080
|
||||
ports: ["19082:8082"]
|
||||
|
||||
cognitive-worker:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: deploy/images/runtime.Dockerfile
|
||||
args: { TARGET: cognitive-worker }
|
||||
environment: { LISTEN_ADDR: ":8083" }
|
||||
ports: ["19083:8083"]
|
||||
|
||||
volumes:
|
||||
assistant_pg_dev:
|
||||
@@ -0,0 +1,86 @@
|
||||
name: assistant
|
||||
services:
|
||||
postgres:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: deploy/images/postgres.Dockerfile
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: ${POSTGRES_DB:-assistant}
|
||||
POSTGRES_USER: ${POSTGRES_SUPERUSER}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_SUPERUSER_PASSWORD}
|
||||
CONTINUITY_DB_PASSWORD: ${CONTINUITY_DB_PASSWORD}
|
||||
IDENTITY_DB_PASSWORD: ${IDENTITY_DB_PASSWORD}
|
||||
AUTHORITY_DB_PASSWORD: ${AUTHORITY_DB_PASSWORD}
|
||||
SITUATION_DB_PASSWORD: ${SITUATION_DB_PASSWORD}
|
||||
WORK_DB_PASSWORD: ${WORK_DB_PASSWORD}
|
||||
CAPABILITY_DB_PASSWORD: ${CAPABILITY_DB_PASSWORD}
|
||||
COMMIT_DB_PASSWORD: ${COMMIT_DB_PASSWORD}
|
||||
volumes:
|
||||
- assistant_pg:/var/lib/postgresql
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_SUPERUSER} -d ${POSTGRES_DB:-assistant}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
|
||||
nats:
|
||||
image: nats:2-alpine
|
||||
restart: unless-stopped
|
||||
command: ["-js", "-m", "8222"]
|
||||
volumes: ["assistant_nats:/data"]
|
||||
|
||||
core-runtime:
|
||||
build: { context: .., dockerfile: deploy/images/runtime.Dockerfile, args: { TARGET: core-runtime } }
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
LISTEN_ADDR: ":8080"
|
||||
POSTGRES_HOST: postgres
|
||||
POSTGRES_PORT: "5432"
|
||||
POSTGRES_DATABASE: ${POSTGRES_DB:-assistant}
|
||||
POSTGRES_USER: situation_role
|
||||
POSTGRES_PASSWORD: ${SITUATION_DB_PASSWORD}
|
||||
IDENTITY_POSTGRES_USER: identity_role
|
||||
IDENTITY_POSTGRES_PASSWORD: ${IDENTITY_DB_PASSWORD}
|
||||
CREATOR_BOOTSTRAP_TOKEN: ${CREATOR_BOOTSTRAP_TOKEN}
|
||||
CREATOR_SESSION_SIGNING_KEY: ${CREATOR_SESSION_SIGNING_KEY}
|
||||
WORK_POSTGRES_USER: work_role
|
||||
WORK_POSTGRES_PASSWORD: ${WORK_DB_PASSWORD}
|
||||
CAPABILITY_POSTGRES_USER: capability_role
|
||||
CAPABILITY_POSTGRES_PASSWORD: ${CAPABILITY_DB_PASSWORD}
|
||||
depends_on: { postgres: { condition: service_healthy } }
|
||||
|
||||
continuity-runtime:
|
||||
build: { context: .., dockerfile: deploy/images/runtime.Dockerfile, args: { TARGET: continuity-runtime } }
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
LISTEN_ADDR: ":8081"
|
||||
POSTGRES_HOST: postgres
|
||||
POSTGRES_PORT: "5432"
|
||||
POSTGRES_DATABASE: ${POSTGRES_DB:-assistant}
|
||||
POSTGRES_USER: continuity_role
|
||||
POSTGRES_PASSWORD: ${CONTINUITY_DB_PASSWORD}
|
||||
|
||||
commit-runtime:
|
||||
build: { context: .., dockerfile: deploy/images/runtime.Dockerfile, args: { TARGET: commit-runtime } }
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
LISTEN_ADDR: ":8082"
|
||||
POSTGRES_HOST: postgres
|
||||
POSTGRES_PORT: "5432"
|
||||
POSTGRES_DATABASE: ${POSTGRES_DB:-assistant}
|
||||
POSTGRES_USER: commit_role
|
||||
POSTGRES_PASSWORD: ${COMMIT_DB_PASSWORD}
|
||||
AUTHORITY_POSTGRES_USER: authority_role
|
||||
AUTHORITY_POSTGRES_PASSWORD: ${AUTHORITY_DB_PASSWORD}
|
||||
CORE_RUNTIME_URL: http://core-runtime:8080
|
||||
# External mutation credentials belong here only via Portainer/Docker secrets/env injection.
|
||||
|
||||
cognitive-worker:
|
||||
build: { context: .., dockerfile: deploy/images/runtime.Dockerfile, args: { TARGET: cognitive-worker } }
|
||||
restart: unless-stopped
|
||||
environment: { LISTEN_ADDR: ":8083" }
|
||||
|
||||
volumes:
|
||||
assistant_pg:
|
||||
assistant_nats:
|
||||
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -v ON_ERROR_STOP=1 -v continuity_password="$CONTINUITY_DB_PASSWORD" <<'SQL'
|
||||
ALTER ROLE continuity_role PASSWORD :'continuity_password';
|
||||
SQL
|
||||
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -v ON_ERROR_STOP=1 -v identity_password="$IDENTITY_DB_PASSWORD" <<'SQL'
|
||||
ALTER ROLE identity_role PASSWORD :'identity_password';
|
||||
SQL
|
||||
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -v ON_ERROR_STOP=1 -v authority_password="$AUTHORITY_DB_PASSWORD" <<'SQL'
|
||||
ALTER ROLE authority_role PASSWORD :'authority_password';
|
||||
SQL
|
||||
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -v ON_ERROR_STOP=1 -v situation_password="$SITUATION_DB_PASSWORD" <<'SQL'
|
||||
ALTER ROLE situation_role PASSWORD :'situation_password';
|
||||
SQL
|
||||
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -v ON_ERROR_STOP=1 -v work_password="$WORK_DB_PASSWORD" <<'SQL'
|
||||
ALTER ROLE work_role PASSWORD :'work_password';
|
||||
SQL
|
||||
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -v ON_ERROR_STOP=1 -v capability_password="$CAPABILITY_DB_PASSWORD" <<'SQL'
|
||||
ALTER ROLE capability_role PASSWORD :'capability_password';
|
||||
SQL
|
||||
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -v ON_ERROR_STOP=1 -v commit_password="$COMMIT_DB_PASSWORD" <<'SQL'
|
||||
ALTER ROLE commit_role PASSWORD :'commit_password';
|
||||
SQL
|
||||
@@ -0,0 +1,5 @@
|
||||
FROM postgres:18.6-alpine
|
||||
|
||||
COPY database/bootstrap/001_roles_and_schemas.sql /docker-entrypoint-initdb.d/001_roles_and_schemas.sql
|
||||
COPY deploy/images/002_owner_passwords.sh /docker-entrypoint-initdb.d/002_owner_passwords.sh
|
||||
RUN chmod 0555 /docker-entrypoint-initdb.d/002_owner_passwords.sh
|
||||
@@ -0,0 +1,13 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM golang:1.26.6-alpine AS build
|
||||
WORKDIR /src
|
||||
COPY go.mod ./
|
||||
COPY . .
|
||||
ARG TARGET
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -o /out/runtime ./cmd/${TARGET}
|
||||
|
||||
FROM alpine:3.23
|
||||
RUN addgroup -S assistant && adduser -S -G assistant assistant
|
||||
USER assistant
|
||||
COPY --from=build /out/runtime /usr/local/bin/assistant-runtime
|
||||
ENTRYPOINT ["/usr/local/bin/assistant-runtime"]
|
||||
@@ -0,0 +1,5 @@
|
||||
# Codex tasks
|
||||
|
||||
`DEV-000001` is the first task after placing this folder at `Z:\mst\codex\assistent`.
|
||||
|
||||
Do not start `DEV-000002` until the guardrails, Git remote, CI and local stack in DEV-000001 are healthy.
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "Codex Task Packet V1",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"task_id",
|
||||
"task_revision",
|
||||
"architecture_revision",
|
||||
"risk_tier",
|
||||
"intent",
|
||||
"allowed_change_scope",
|
||||
"acceptance_scenarios",
|
||||
"required_tests"
|
||||
],
|
||||
"properties": {
|
||||
"task_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"task_revision": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"architecture_revision": {
|
||||
"type": "string"
|
||||
},
|
||||
"base_repo_revision": {
|
||||
"type": "string"
|
||||
},
|
||||
"risk_tier": {
|
||||
"enum": [
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"E"
|
||||
]
|
||||
},
|
||||
"intent": {
|
||||
"type": "string"
|
||||
},
|
||||
"requirement_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"allowed_change_scope": {
|
||||
"type": "object"
|
||||
},
|
||||
"forbidden_change_scope": {
|
||||
"type": "object"
|
||||
},
|
||||
"allowed_architecture_delta": {
|
||||
"type": "object"
|
||||
},
|
||||
"semantic_owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"acceptance_scenarios": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required_tests": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"terminal_gap_states": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"task_id": "DEV-000001",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "bootstrap-1",
|
||||
"base_repo_revision": "INITIAL",
|
||||
"risk_tier": "E",
|
||||
"intent": "Validate and complete the repository guardrail skeleton without changing accepted semantic architecture. Make devctl checks, Go build/test, DB ownership bootstrap, CI and local Docker development stack operational.",
|
||||
"requirement_ids": ["INV-OWN-001", "INV-TOPO-001"],
|
||||
"allowed_change_scope": {
|
||||
"paths": ["cmd/devctl/**", "scripts/**", "ci/**", ".gitea/**", "deploy/**", "database/bootstrap/**", "tests/architecture/**"]
|
||||
},
|
||||
"forbidden_change_scope": {
|
||||
"paths": ["architecture/ARCHITECTURE_CONSTITUTION.md", "architecture/CORE_SEMANTIC_MODEL_V1.md"],
|
||||
"semantic_changes": true
|
||||
},
|
||||
"allowed_architecture_delta": {
|
||||
"new_cross_module_dependencies": 0,
|
||||
"new_canonical_owners": 0,
|
||||
"new_privileges": 0,
|
||||
"semantic_topology_changes": 0
|
||||
},
|
||||
"semantic_owner": "development-control-plane",
|
||||
"acceptance_scenarios": [
|
||||
"Fresh Codex session can identify module owners and protected paths",
|
||||
"Forbidden cross-module internal import makes architecture check fail",
|
||||
"Project builds and tests with Go 1.26.x",
|
||||
"Development docker compose starts PostgreSQL/NATS/runtime health endpoints",
|
||||
"Git origin is https://git.cin.su/m/Assistant.git without embedded credentials"
|
||||
],
|
||||
"required_tests": ["go test ./...", "go vet ./...", "go run ./cmd/devctl check-architecture", "docker compose config"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_SPEC_GAP", "BLOCKED_BY_ARCHITECTURE_GAP", "BLOCKED_BY_MISSING_CAPABILITY"]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"task_id": "DEV-000002",
|
||||
"task_revision": 2,
|
||||
"architecture_revision": "bootstrap-1",
|
||||
"base_repo_revision": "AFTER_DEV_000001",
|
||||
"risk_tier": "C",
|
||||
"intent": "Implement the first vertical walking-skeleton slice for situation/focus isolation across two simultaneous project contexts, without keyword-based project selection.",
|
||||
"allowed_change_scope": {
|
||||
"paths": ["architecture/architecture-registry.yaml", "architecture/architecture-registry.json", "modules/situation/**", "modules/work/**", "contracts/situation/**", "contracts/work/**", "tests/walking_skeleton/**"]
|
||||
},
|
||||
"forbidden_change_scope": {"paths": ["security/**", "modules/commit/**"]},
|
||||
"allowed_architecture_delta": {"new_cross_module_dependencies": 1, "new_canonical_owners": 0, "new_privileges": 0},
|
||||
"semantic_owner": "situation",
|
||||
"acceptance_scenarios": ["WS-001"],
|
||||
"required_tests": ["unit", "contract", "focus-isolation black-box", "architecture"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_SPEC_GAP", "BLOCKED_BY_ARCHITECTURE_GAP"]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"task_id": "DEV-000003",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "bootstrap-1",
|
||||
"base_repo_revision": "AFTER_DEV_000002",
|
||||
"risk_tier": "D",
|
||||
"intent": "Build and deploy the production Docker walking-skeleton stack to docker.cin.su without modifying unrelated workloads.",
|
||||
"allowed_change_scope": {
|
||||
"paths": ["deploy/**", "dev/tasks/DEV-000003-production-docker-stack.json"]
|
||||
},
|
||||
"forbidden_change_scope": {
|
||||
"paths": ["architecture/**", "security/**", "modules/**", "contracts/**"]
|
||||
},
|
||||
"allowed_architecture_delta": {
|
||||
"new_cross_module_dependencies": 0,
|
||||
"new_canonical_owners": 0,
|
||||
"new_privileges": 0
|
||||
},
|
||||
"semantic_owner": "deployment-control-plane",
|
||||
"acceptance_scenarios": ["production Docker stack builds on docker.cin.su", "PostgreSQL is healthy", "all runtime health endpoints respond inside the stack"],
|
||||
"required_tests": ["docker compose config", "remote Docker build", "runtime health checks"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_CONFLICT"]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"task_id": "DEV-000004",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "bootstrap-1",
|
||||
"base_repo_revision": "AFTER_DEV_000003",
|
||||
"risk_tier": "D",
|
||||
"intent": "Bootstrap Domovoy's Creator as a distinct Actor and Principal with an explicit active global AuthorityGrant, without conflating identity, principal, scope, or authority.",
|
||||
"allowed_change_scope": {
|
||||
"paths": ["contracts/identity/**", "contracts/authority/**", "modules/identity/**", "modules/authority/**", "database/bootstrap/**", "database/migrations/**", "tests/creator_authority/**", "dev/tasks/DEV-000004-bootstrap-creator-authority.json"]
|
||||
},
|
||||
"forbidden_change_scope": {
|
||||
"paths": ["architecture/**", "security/**", "modules/commit/**"]
|
||||
},
|
||||
"allowed_architecture_delta": {
|
||||
"new_cross_module_dependencies": 0,
|
||||
"new_canonical_owners": 0,
|
||||
"new_privileges": 0
|
||||
},
|
||||
"semantic_owner": "authority",
|
||||
"acceptance_scenarios": ["Creator Actor and Principal remain distinct", "Creator grant has an explicit global scope and revision", "revoked or malformed Creator grant is denied", "production database migration is idempotent"],
|
||||
"required_tests": ["unit", "canonical schema bootstrap", "migration idempotency", "architecture"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_SPEC_GAP", "BLOCKED_BY_ARCHITECTURE_GAP", "REQUIRES_MIGRATION_DECISION"]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"task_id": "DEV-000005",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "bootstrap-1",
|
||||
"base_repo_revision": "AFTER_DEV_000004",
|
||||
"risk_tier": "D",
|
||||
"intent": "Implement the deterministic WS-003 Commit authorization state machine with explicit Authority, Scope, Capability, Task revision, executor isolation, and UNKNOWN_OUTCOME handling.",
|
||||
"allowed_change_scope": {
|
||||
"paths": ["contracts/commit/**", "contracts/authority/**", "contracts/capability/**", "modules/commit/**", "modules/authority/**", "tests/action_commit/**", "dev/tasks/DEV-000005-safe-action-commit.json"]
|
||||
},
|
||||
"forbidden_change_scope": {
|
||||
"paths": ["architecture/**", "security/**", "adapters/**", "modules/situation/**", "modules/work/**"]
|
||||
},
|
||||
"allowed_architecture_delta": {
|
||||
"new_cross_module_dependencies": 0,
|
||||
"new_canonical_owners": 0,
|
||||
"new_privileges": 0
|
||||
},
|
||||
"semantic_owner": "commit",
|
||||
"acceptance_scenarios": ["WS-003"],
|
||||
"required_tests": ["unit", "authority rejection", "unknown outcome", "no-blind-retry", "architecture"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_SPEC_GAP", "BLOCKED_BY_ARCHITECTURE_GAP"]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"task_id": "DEV-000006",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "bootstrap-1",
|
||||
"base_repo_revision": "AFTER_DEV_000005",
|
||||
"risk_tier": "D",
|
||||
"intent": "Implement WS-002 canonical ProspectiveItem state that survives scheduler loss and revalidates before delivery.",
|
||||
"allowed_change_scope": {
|
||||
"paths": ["contracts/continuity/**", "modules/continuity/**", "database/bootstrap/**", "database/migrations/**", "tests/prospective_memory/**", "dev/tasks/DEV-000006-durable-prospective-memory.json"]
|
||||
},
|
||||
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "adapters/temporal/**", "modules/commit/**"]},
|
||||
"allowed_architecture_delta": {"new_cross_module_dependencies": 0, "new_canonical_owners": 0, "new_privileges": 0},
|
||||
"semantic_owner": "continuity",
|
||||
"acceptance_scenarios": ["WS-002"],
|
||||
"required_tests": ["unit", "recovery", "revalidation", "duplicate-trigger", "architecture"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_SPEC_GAP", "BLOCKED_BY_ARCHITECTURE_GAP"]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"task_id": "DEV-000007",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "bootstrap-1",
|
||||
"base_repo_revision": "AFTER_DEV_000006",
|
||||
"risk_tier": "C",
|
||||
"intent": "Expose a deterministic cognitive fake that emits typed ActionProposal candidates only and cannot mutate canonical state or invoke an Executor.",
|
||||
"allowed_change_scope": {"paths": ["adapters/models/**", "cmd/cognitive-worker/**", "tests/cognitive_fake/**", "dev/tasks/DEV-000007-deterministic-cognitive-fake.json"]},
|
||||
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "modules/**", "adapters/postgres/**", "adapters/temporal/**"]},
|
||||
"allowed_architecture_delta": {"new_cross_module_dependencies": 0, "new_canonical_owners": 0, "new_privileges": 0},
|
||||
"semantic_owner": "none-cognitive-worker",
|
||||
"acceptance_scenarios": ["deterministic fake produces identical candidate for identical typed request", "candidate cannot mutate canonical state", "candidate cannot execute external side effect"],
|
||||
"required_tests": ["unit", "HTTP contract", "architecture"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_SPEC_GAP", "BLOCKED_BY_ARCHITECTURE_GAP"]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"task_id": "DEV-000008",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "bootstrap-1",
|
||||
"base_repo_revision": "AFTER_DEV_000007",
|
||||
"risk_tier": "D",
|
||||
"intent": "Persist Continuity ProspectiveItems in its owner-local PostgreSQL schema and expose a continuity-runtime HTTP API without leaking PostgreSQL into domain code.",
|
||||
"allowed_change_scope": {"paths": ["go.mod", "go.sum", "adapters/postgres/**", "modules/continuity/**", "cmd/continuity-runtime/**", "deploy/**", "tests/continuity_api/**", "dev/tasks/DEV-000008-continuity-postgres-api.json"]},
|
||||
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "modules/commit/**", "modules/work/**"]},
|
||||
"allowed_architecture_delta": {"new_cross_module_dependencies": 0, "new_canonical_owners": 0, "new_privileges": 0, "new_third_party_dependencies": 1},
|
||||
"semantic_owner": "continuity",
|
||||
"acceptance_scenarios": ["ProspectiveItem survives continuity-runtime restart", "continuity API writes only continuity schema", "domain package imports no PostgreSQL types"],
|
||||
"required_tests": ["unit", "repository integration", "runtime HTTP", "architecture"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "REQUIRES_MIGRATION_DECISION"]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"task_id": "DEV-000009",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "bootstrap-1",
|
||||
"base_repo_revision": "AFTER_DEV_000008",
|
||||
"risk_tier": "D",
|
||||
"intent": "Persist Situation focus bindings in its owner-local PostgreSQL schema and resolve focus only from runtime session/workspace bindings.",
|
||||
"allowed_change_scope": {"paths": ["adapters/postgres/**", "modules/situation/**", "cmd/core-runtime/**", "database/bootstrap/**", "database/migrations/**", "deploy/**", "tests/situation_api/**", "dev/tasks/DEV-000009-situation-focus-postgres-api.json"]},
|
||||
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "modules/work/**", "modules/commit/**"]},
|
||||
"allowed_architecture_delta": {"new_cross_module_dependencies": 0, "new_canonical_owners": 0, "new_privileges": 0},
|
||||
"semantic_owner": "situation",
|
||||
"acceptance_scenarios": ["WS-001 runtime binding resolves its own focus", "ambiguous runtime binding has no mutation"],
|
||||
"required_tests": ["unit", "repository integration", "runtime HTTP", "architecture"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "REQUIRES_MIGRATION_DECISION"]
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user