PROJ is CyberOS's project tracker, sprint engine, and Engagement billing surface in one. The data model is Issue → Cycle → Project plus Engagement (the contract). Status is a closed enum (backlog · todo · in-progress · in-review · done · cancelled) with a configurable per-project workflow on top. Priority is the standard urgent · high · medium · low · none. Mutations are optimistic locally, server-canonical eventually; Yjs CRDTs let two Members edit the same description offline and merge without conflict. Every issue can link to BRAIN entries — a memory becomes a citation, a decision-log row becomes a sub-task. AI features are first-class: CUO drafts the cycle review at end-of-cycle; the blocker-detector watches comments for "blocked by"; estimate calibration tracks estimated vs actual hours per Member per task class. PRD §9.5.
Why PROJ exists
Linear's data-model insight was that three primitives — Issue, Cycle, Project — cover almost every workflow that product and services teams actually do, and that a fourth primitive ("Engagement") covers the consultancy case once you add a rate card and a billable / non-billable distinction. The UX insight was sync-engine: the user never waits for a server round-trip; the server is the eventual authority, but the local copy is the one being typed into. PROJ replicates both insights and adds the CyberOS-specific bindings: every issue links to BRAIN memories (so a decision-log row can spawn a sub-task), every comment is a candidate for a blocker-detection nudge, every cycle ends with a CUO-drafted review the Account Manager can edit before sending to the Client.
Optimistic local updates, WebSocket fan-out, server-canonical rebase on conflict. No spinners on the hot path; offline edits merge via Yjs CRDT.
Where Linear has "Project", we have "Project under Engagement". Rate cards, billable rules, and TIME → INV flow ride on the Engagement.
Every issue can cite a BRAIN memory; tasks are ingested into Layer 3; cross-project pattern queries answer "what's the pattern in late tasks?".
The bet is that consultancies do not need a different tracker per client — they need one tracker that understands the consulting shape natively. Linear validated the three-primitive model; CyberOS extends it with the contract layer and the AI-native loop. The sync-engine is the rest of the way to "feels instant" — Linear documented the pattern; we re-implement it because the consulting cycle is two-weeks-anchored to a Client review, and that review needs to be CUO-draftable from the comment stream.
What it does — 5W1H2C5M
A structured decomposition of PROJ's scope. Every cell traces back to PRD §9.5.
| Axis | Question | Answer |
|---|---|---|
| 5W · What | What is PROJ? | An issue tracker with four primitives (Issue, Cycle, Project, Engagement). Sync-engine for the SPA; Yjs CRDT for offline-edit merges; PGroonga for Vietnamese full-text; BRAIN integration both ways (issues link to memories, completed issues ingested as Layer 3 nodes). |
| 5W · Who | Who uses it? | Members: create / assign / progress issues; review their own cycle queue daily. Account Managers: own the Engagement; edit + send CUO-drafted cycle reviews. Clients: read-only Project view via PORTAL (P2). Agents: CUO Notify on blocker detection; CUO/COO-skill triage suggestions. |
| 5W · When | When does it run? | Continuous: WebSocket fan-out on every mutation; nightly batch for estimate-calibration metric refresh; end-of-cycle batch for review draft generation. Auto-roll of incomplete tasks at cycle close (configurable per team). |
| 5W · Where | Where does it run? | P1: single region (SG-1) with VN-residency S3 for tenant uploads. P3+: multi-region active-active. The sync server is a per-tenant axum binary; the SPA is hosted as static assets. |
| 5W · Why | Why a separate tracker? | Existing trackers do not natively model the Engagement / rate-card / billable-time loop; sync-engine UX is rare outside Linear; and BRAIN-linked work is a CyberOS-specific need that no off-the-shelf tracker provides. |
| 1H · How | How does it work? | Mutations: client-side optimistic apply → JMAP-like RPC over WebSocket → server validates → server-canonical state broadcast to all connected SPAs → conflicts resolved server-side and rebased into the client. CRDT: long-form fields (description, comment body) are Yjs documents; the rest is last-write-wins with a vector clock. |
| 2C · Cost | Cost budget? | P1: ~$80 / month for SG-1 single-tenant pilot. 50-tenant: ~$340 / month (RDS + Redis + Fargate + S3). Per-issue write cost ~$0.0000004. |
| 2C · Constraints | Constraints? | (a) Issues ingested into BRAIN Layer 3 — but body content gates as per (FR pending). (b) Per-task ACL — private engagements MUST NOT be visible to non-engaged Members. (c) Vietnamese localisation of status / UI strings — non-negotiable for P1 launch. |
| 5M · Materials | Stack? | Rust 1.81 · axum 0.7 · sqlx · PostgreSQL 16 + PGroonga · Redis 7 · S3 + KMS · Yjs (server-side ywasm + client TS) · TypeScript SPA (React + Zustand) · WebSocket fan-out via NATS JetStream · OpenTelemetry SDK. |
| 5M · Methods | Method choices? | Three-primitive model (Linear). Sync-engine UX (Linear). Yjs for CRDT long-form (because OT is too brittle at scale). Closed status enum + workflow overlay (not free-form labels). PGroonga for VN search. NATS JetStream for fan-out (not a Postgres LISTEN/NOTIFY — won't scale past 1k WS connections). |
| 5M · Machines | Deployment? | Per-tenant Fargate axum binary handling WebSocket + REST. Postgres RDS Multi-AZ. Redis for hot-cache and WS rooms. NATS JetStream cluster (3 nodes P2+). S3 for attachments. |
| 5M · Manpower | Who maintains? | 0.75 FTE (CTO seat) at P1 launch. By P2+: COO seat owns product + Account Manager workflow; CTO owns engine + sync layer. |
| 5M · Measurement | How measured? | Issue write p95 ≤ 120 ms; SPA list-view load p95 ≤ 250 ms; offline-merge correctness ≥ 99.9% (property tests); BRAIN ingestion p95 ≤ 5 s; cycle-review draft acceptance rate ≥ 60% by Account Manager. |
Architecture
PROJ is one axum binary with four surfaces (sync-engine WebSocket, REST admin, GraphQL federated subgraph, MCP tool catalogue) and three stores (Postgres for canonical state + Yjs document snapshots, Redis for WS rooms and search cache, S3 for attachments). NATS JetStream fans mutations out to every connected SPA.
React + Zustand"] MOBILE["Mobile (P3)"] AGENT["🎯 CUO agent
via MCP"] end subgraph EDGE ["Edge"] WSGW["WebSocket gateway
JWT-authed"] GQL["GraphQL subgraph
(federated)"] REST["Admin REST"] MCP["MCP tool surface"] end subgraph CORE ["PROJ service (Rust)"] SYNC["Sync engine
optimistic + rebase"] CRDT["Yjs document server
(ywasm)"] WF["Workflow engine
status transitions"] AI["AI hooks
blocker · review · calibration"] BRAIN_ING["BRAIN ingestor
Layer 3"] AUTH_CHK["RBAC + per-task ACL"] end subgraph STORES ["Stores"] PG[("PostgreSQL + PGroonga
issues · cycles · projects
RLS by tenant_id")] RED[("Redis 7
WS rooms · search cache")] S3[("S3 + KMS
attachments")] NATS[("NATS JetStream
mutation fan-out")] end subgraph SINKS ["Sinks"] BRAIN["🧠 BRAIN
Layer 3 ingest · audit"] TIME["⏱ TIME
billable / non-billable"] INV["🧾 INV
billable hours → invoice"] OBS["👁 OBS
traces + SLO"] CUO["🎯 CUO
Notify · review draft"] end SPA --> WSGW MOBILE --> WSGW AGENT --> MCP WSGW --> SYNC GQL --> SYNC REST --> SYNC MCP --> SYNC SYNC --> CRDT SYNC --> WF SYNC --> AI SYNC --> BRAIN_ING SYNC --> AUTH_CHK SYNC --> PG SYNC --> RED SYNC --> NATS NATS --> WSGW CRDT --> PG AI --> CUO BRAIN_ING --> BRAIN WF --> TIME TIME --> INV SYNC --> S3 SYNC --> OBS classDef planned fill:#cba88a,stroke:#45210e classDef store fill:#f5f3ff,stroke:#7c3aed classDef sink fill:#f5ede6,stroke:#45210e class SPA,MOBILE,AGENT,WSGW,GQL,REST,MCP,SYNC,CRDT,WF,AI,BRAIN_ING,AUTH_CHK planned class PG,RED,S3,NATS store class BRAIN,TIME,INV,OBS,CUO sink
The four primitives
A discrete piece of work. Has title, description (Yjs), status, priority, assignee, estimate, labels, dependencies, parent issue, cycle binding. Comments are sub-resources.
A time-boxed bucket of Issues. Has start / end dates, target velocity, retro link. Incomplete Issues auto-roll to the next cycle if the team configures it ((FR pending)).
A multi-cycle initiative. Has roadmap view, status (planned / active / paused / completed), client visibility flag (visible via PORTAL when the Engagement permits).
The contract under which a Project is delivered for a Client. Carries rate card, billable / non-billable rules, ACL. TIME → INV pulls from here. Vietnamese-consultancy-specific.
Internal components
| Component | Path (planned) | Responsibility |
|---|---|---|
sync.rs | services/proj/src/sync.rs | Sync-engine — optimistic apply, conflict detection, server-canonical broadcast. |
crdt.rs | services/proj/src/crdt.rs | Yjs document server via ywasm. Long-form fields (description, comment body) are Yjs; the rest is LWW with vector clock. |
workflow.rs | services/proj/src/workflow.rs | Per-project workflow overlay on the closed status enum. |
ai_blocker.rs | services/proj/src/ai_blocker.rs | Blocker detection from comment stream. "blocked by", "waiting on", and dwell-time heuristics → CUO Notify. |
ai_review.rs | services/proj/src/ai_review.rs | End-of-cycle review draft generator. Pulls from issue changelog + comments; CUO-stamped persona; AM edits before sending. |
ai_calibration.rs | services/proj/src/ai_calibration.rs | Estimate vs actual hours per Member per task class. Surfaces calibration drift to Member's dashboard. |
brain_ingest.rs | services/proj/src/brain_ingest.rs | Layer 3 ingestion of issues + comments ((FR pending)). Body content gates per ACL. |
acl.rs | services/proj/src/acl.rs | Per-task / per-engagement ACL. Private engagements not visible to non-engaged Members ((FR pending)). |
autoroll.rs | services/proj/src/autoroll.rs | End-of-cycle auto-roll. Incomplete issues move to next cycle if team config permits ((FR pending)). |
nats_fanout.rs | services/proj/src/nats_fanout.rs | NATS JetStream publisher / subscriber for mutation fan-out. |
search.rs | services/proj/src/search.rs | PGroonga query builder; VN bigram tokenisation. |
graphql.rs | services/proj/src/graphql.rs | Federated subgraph; @key(fields:"id") on every primitive. |
mcp.rs | services/proj/src/mcp.rs | MCP tool catalogue exported to CUO. |
i18n.rs | services/proj/src/i18n.rs | vi + en string tables; locale resolved from JWT claim; status names localised. |
migrations/ | services/proj/migrations/ | sqlx migrations with RLS on every table. |
Data model
The canonical state is PostgreSQL with row-level security by tenant_id and, for private engagements, additional ACL enforcement by engagement_id membership. Long-form fields are Yjs document snapshots stored as bytea blobs; the active CRDT state lives in Redis for the duration of a session.
Status enum + workflow overlay
The status enum is closed (backlog · todo · in-progress · in-review · done · cancelled). Per-project workflows can rename and re-order the visible states but always map back to a category in the closed set. The category is what drives velocity calculation, auto-roll, and BRAIN ingestion.
| Status | vi name | en name | Category | Velocity counts? |
|---|---|---|---|---|
backlog | Tồn đọng | Backlog | todo | no |
todo | Cần làm | Todo | todo | no |
in-progress | Đang làm | In progress | in-progress | yes |
in-review | Đang review | In review | in-progress | yes |
done | Hoàn thành | Done | done | yes |
cancelled | Huỷ bỏ | Cancelled | cancelled | no |
API surface
Four surfaces: a WebSocket sync-engine for the SPA, a GraphQL federated subgraph for cross-module queries, an admin REST for migration and bulk import, and an MCP tool catalogue for CUO. All four share the same RBAC predicate.
GraphQL subgraph (federated)
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.5", import: ["@key", "@requiresScopes"])
type Engagement @key(fields: "id") {
id: ID!
name: String!
clientAccountId: ID!
startDate: Date!
endDate: Date
billingMode: BillingMode!
projects: [Project!]!
rateCards: [RateCard!]!
}
type Project @key(fields: "id") {
id: ID!
engagementId: ID!
name: String!
status: ProjectStatus!
clientVisible: Boolean!
cycles(active: Boolean): [Cycle!]!
issues(filter: IssueFilter, limit: Int = 50, cursor: String): IssueConnection!
}
type Cycle @key(fields: "id") {
id: ID!
projectId: ID!
number: Int!
startDate: Date!
endDate: Date!
velocityTarget: Int
issues: [Issue!]!
review: CycleReview
}
type Issue @key(fields: "id") {
id: ID!
code: String!
title: String!
description: String! # rendered from Yjs doc
status: IssueStatus!
priority: IssuePriority!
assignee: Subject
estimateHours: Int
actualHours: Int
cycleId: ID
parent: Issue
children: [Issue!]!
dependencies: [Dependency!]!
comments: [Comment!]!
labels: [String!]!
attachments: [Attachment!]!
brainLinks: [BrainLink!]!
history: [HistoryEvent!]!
}
enum IssueStatus { BACKLOG TODO IN_PROGRESS IN_REVIEW DONE CANCELLED }
enum IssuePriority { URGENT HIGH MEDIUM LOW NONE }
enum ProjectStatus { PLANNED ACTIVE PAUSED COMPLETED }
enum BillingMode { T_AND_M FIXED_FEE RETAINER }
type Mutation {
createIssue(input: CreateIssueInput!): Issue!
@requiresScopes(scopes: [["proj.write"]])
updateIssue(id: ID!, patch: IssuePatch!): Issue!
assignIssue(id: ID!, assigneeId: ID!): Issue!
moveIssueToCycle(id: ID!, cycleId: ID): Issue!
addComment(issueId: ID!, body: String!): Comment!
closeCycle(cycleId: ID!): CycleReview!
@requiresScopes(scopes: [["proj.cycle.close"]])
}
Sync-engine WebSocket protocol
// Client → server: optimistic mutation
{
"op": "issue.update",
"client_seq": 12834,
"tenant_id": "01HZ…",
"issue_id": "01HZ…",
"patch": { "status": "in-progress", "assignee_id": "01HZ…" },
"vector_clock": { "spa-stephen-laptop": 47 }
}
// Server → all room subscribers: canonical state
{
"op": "issue.state",
"server_seq": 982341,
"issue_id": "01HZ…",
"state": { "status": "in-progress", "assignee_id": "01HZ…", "updated_at": "…" },
"vector_clock": { "spa-stephen-laptop": 47, "server": 982341 }
}
// Server → client (conflict, rebase needed)
{
"op": "rebase",
"client_seq": 12834,
"server_state": { … },
"reason": "concurrent_modification"
}
MCP tool catalogue
| Tool name | Inputs | Outputs | Annotations |
|---|---|---|---|
cyberos.proj.list_issues | project_id?, cycle_id?, assignee_id?, status? | Issue[] | readonly · scope=proj.read |
cyberos.proj.create_issue | CreateIssueInput | Issue | scope=proj.write |
cyberos.proj.update_issue | id, patch | Issue | scope=proj.write |
cyberos.proj.assign_issue | id, assignee_id | Issue | scope=proj.write |
cyberos.proj.add_comment | issue_id, body | Comment | scope=proj.write |
cyberos.proj.move_to_cycle | id, cycle_id | Issue | scope=proj.write |
cyberos.proj.close_cycle | cycle_id | CycleReview (draft) | destructive · human-confirm · scope=proj.cycle.close |
cyberos.proj.detect_blockers | project_id? | Issue[] + reasons | readonly |
cyberos.proj.estimate_calibration | member_id, range | Calibration stats | readonly |
Key flows
Flow 1 — Create an issue (sync-engine)
Flow 2 — Concurrent edit + conflict-free merge via Yjs
Yjs handles the description / comment-body fields. Scalar fields (status, priority, assignee) use last-write-wins with the server's vector clock as the tiebreaker.
Flow 3 — AI cycle-review draft at cycle close
Flow 4 — Blocker detection from comments
Flow 5 — Estimate calibration nightly batch
Issue lifecycle
An issue traverses six canonical states (the closed enum). The per-project workflow overlay may rename or re-order the visible states but the underlying category drives velocity, auto-roll, and BRAIN ingestion.
Auto-roll behaviour at cycle close
| Issue status at cycle close | Auto-roll behaviour | Configurable? |
|---|---|---|
todo | Roll to next cycle | yes ((FR pending)) |
in-progress | Roll to next cycle | yes |
in-review | Roll to next cycle | yes |
done | Stay in original cycle (velocity counts) | no |
cancelled | Stay in original cycle | no |
backlog (unscheduled) | Stay in backlog | n/a |
Functional Requirements
The CyberOS FR catalogue is being rebuilt one feature at a time via the open fr-author Agent Skill.
Previous FR enumerations were archived 2026-05-14 and are no longer reflected on this page. PRD/SRS narrative remains authoritative for the spec; specific FRs land here as they are re-authored.
Non-Functional Requirements
NFRs from PRD §11.2 that PROJ must satisfy. Cross-referenced at nfr-catalog.html#proj.
| NFR ID | Concern | Target | Measurement |
|---|---|---|---|
N(FR pending) | Issue update mutation | p95 ≤ 120 ms server-side | histogram via OBS |
N(FR pending) | Issue list view (50 issues) | p95 ≤ 250 ms (network + render) | SPA RUM |
N(FR pending) | WebSocket fan-out latency (mutation → other clients) | p95 ≤ 200 ms within region | NATS lag metric |
N(FR pending) | BRAIN ingestion (issue create → indexed) | p95 ≤ 5 s | BRAIN ingest histogram |
N(FR pending) | Offline-edit merge correctness | ≥ 99.9% | property-based test (10k random workloads) |
N(FR pending) | Vietnamese search recall (50-query corpus) | ≥ 90% | quarterly eval |
N(FR pending) | Cycle-review draft acceptance rate | ≥ 60% by AM | SPA telemetry |
N(FR pending) | Service availability (28-day) | ≥ 99.9% | OBS SLO monitor |
N(FR pending) | Private-engagement isolation | = 0 cross-leak | CI test on every PR |
N(FR pending) | RLS coverage | 100% of tables | migration-CI gate |
N(FR pending) | Mutation durability after WS ack | = 0 dropped under crash | chaos test + BRAIN walk |
N(FR pending) | WS connections per tenant per axum task | ≥ 5k sustained | k6 load test |
Dependencies
PROJ depends on AUTH for every call, BRAIN for ingestion + audit, TIME for time entries, AI for CUO features, MCP for tool surfacing, and NATS for fan-out. It is depended on by INV (billable hours roll-up), CRM (deal → engagement link), KB (project docs), and PORTAL (client-visible Project view at P2+).
billable roll-up"] CRM["🤝 CRM
deal→engagement"] KB["📚 KB
project docs"] EMAIL["✉️ EMAIL
thread→issue"] PORTAL["Portal · P2"] end AUTH --> PROJ BRAIN --> PROJ TIME --> PROJ AI --> PROJ MCP --> PROJ NATS --> PROJ OBS --> PROJ PROJ --> INV PROJ --> CRM PROJ --> KB EMAIL --> PROJ PROJ --> PORTAL classDef shipped fill:#f5ede6,stroke:#45210e classDef planned fill:#fef6e0,stroke:#9c750a class BRAIN shipped class PROJ,AUTH,TIME,AI,MCP,NATS,OBS,INV,CRM,KB,EMAIL,PORTAL planned
Compliance scope
PROJ is not a regulator's first stop, but it sits inside the audit trail for delivery work and must satisfy ACL, audit, and DSAR obligations.
| Regulation / standard | Article / clause | PROJ feature that satisfies it |
|---|---|---|
| Vietnam PDPL (Law 91/2025) | Art. 14 — DSAR | DSAR export includes every issue / comment a subject authored. |
| Vietnam Decree 13/2023 | Art. 17 — Processing log | HISTORY_EVENT table is the processing log; every mutation writes one row. |
| GDPR (EU 2016/679) | Art. 17 — Right to erasure | Soft-tombstone on assignee, then DSAR-driven hard purge via BRAIN. |
| GDPR | Art. 25 — Privacy by design | Private-engagement ACL means non-engaged Members cannot see issue titles. |
| ISO/IEC 27001:2022 | A.8.2 — Privileged access | RBAC + per-engagement ACL gate write operations. |
| ISO/IEC 27001:2022 | A.8.16 — Monitoring | BRAIN audit chain covers create / status / assign / comment events. |
| SOC 2 Type II | CC6.1 — Logical access | RLS + ACL enforcement at every mutation. |
| SOC 2 Type II | CC7.2 — System monitoring | OBS traces + BRAIN audit cross-correlate. |
Risk entries
PROJ-specific risks tracked in the risk register.
| ID | Risk | Likelihood | Impact | Owner | Mitigation |
|---|---|---|---|---|---|
R-PROJ-001 | Sync-engine state divergence between SPA and server | Medium | High | CTO | Property-based tests (10k random workloads); server is canonical; client always rebases on conflict. |
R-PROJ-002 | Yjs CRDT memory leak on long-running document sessions | Medium | Medium | CTO | Snapshot to Postgres every 60 s; evict in-memory doc after 5 min idle; reload on demand. |
R-PROJ-003 | Private-engagement leak via cross-tenant graph query | Low | High | CSO | RLS + ACL CI gates; quarterly red-team review of GraphQL surface. |
R-PROJ-004 | NATS JetStream backlog → WS clients see stale state | Medium | Medium | CTO | NATS depth alerted at > 1k msgs; SPA reconnect triggers full state refetch. |
R-PROJ-005 | Auto-roll inflates next cycle and burns out team | Medium | Medium | COO | Auto-roll opt-in per project; AM sees roll-over count in cycle review draft. |
R-PROJ-006 | Cycle-review draft hallucinates events that did not occur | Medium | Medium | COO | Draft is an editable suggestion, never auto-sent; AM is accountable for content. |
R-PROJ-007 | Blocker detector false-positive spam | Medium | Low | COO | Confidence threshold ≥ 0.85; user "not a blocker" feedback trains down. |
R-PROJ-008 | BRAIN ingestion lag breaks cross-module search | Low | Medium | CDO | p95 ≤ 5 s SLO; backlog alarm pages CDO + CTO. |
R-PROJ-009 | Calibration data weaponised in performance review | Medium | Low | CHRO | Calibration visible only to Member + manager + CHRO; never client-visible; never used as sole performance signal (HR policy). |
R-PROJ-010 | Vietnamese tokenisation regressions on PGroonga upgrade | Low | Low | CTO | 50-query VN test corpus run on every PGroonga upgrade. |
KPIs
PROJ rolls up 9 KPIs covering delivery cadence, sync-engine performance, AI feature efficacy, and Member experience.
| KPI | Formula | Source | Target |
|---|---|---|---|
| Cycle velocity stability | stddev(completed_points) / mean | cycle_review | ≤ 0.25 (steady) |
| Issue update mutation p95 | histogram | OBS | ≤ 120 ms |
| WS fan-out lag p95 | histogram | NATS | ≤ 200 ms |
| Auto-rolled issues per cycle | count | cycle_review | tracked; alert if > 30% |
| AI cycle-review acceptance | sent / drafted | SPA telemetry | ≥ 60% |
| Blocker-detection precision | true_positive / flagged | user feedback | ≥ 80% |
| BRAIN ingestion lag p95 | histogram | BRAIN | ≤ 5 s |
| Estimate calibration drift | actual / estimate − 1 | calibration_snapshot | tracked per Member |
| Offline-merge incidents | conflicts / month | BRAIN audit | tracked; expect < 5 / mo |
RACI matrix
PROJ is owned by the COO seat. Today (COO vacant), CEO is interim accountable; CTO owns engineering; Account Managers own per-engagement workflow configuration.
| Activity | CEO | CTO | COO | CHRO | CDO | AM |
|---|---|---|---|---|---|---|
| Service design + spec | A | R | C | I | C | C |
| Sync-engine implementation | I | A/R | I | I | I | I |
| Engagement / workflow config | I | C | A | I | I | R |
| Cycle review send | I | I | C | I | I | A/R |
| Calibration policy (HR) | C | I | C | A/R | I | I |
| BRAIN ingestion review | I | C | I | I | A/R | I |
| Private-engagement ACL audit | C | R | A | I | I | I |
| VN localisation review | C | C | A/R | I | I | C |
| Incident response | A | R | R | I | C | I |
R Responsible · A Accountable · C Consulted · I Informed.
Planned CLI surface
A single admin CLI cyberos-proj for tenant operators and an SDK for scripted bulk edits.
1. Create an Engagement
$ cyberos-proj engagement create \
--tenant cyberskill \
--client-account acme-vn \
--name "ACME Q3 platform build" \
--billing-mode T_AND_M \
--start 2026-07-01
[engagement created]
id: 01HZK2…
client: acme-vn
billing: T_AND_M
audit: brain seq=15014 chain=1f2e…3d4c
2. Create a Cycle and bulk-create Issues
$ cyberos-proj cycle create --project pj-acme-platform --number 7 --start 2026-08-04 --weeks 2
[cycle created] id=01HZK3… number=7 dates=2026-08-04 / 2026-08-17
$ cyberos-proj issue bulk-create --cycle 01HZK3… --file backlog.yaml
[bulk-create] parsed 12 issues
[bulk-create] PROJ-1247 "Auth integration" → assignee=linh@…
[bulk-create] PROJ-1248 "Migration runbook" → assignee=tu@…
[bulk-create] … 10 more
[bulk-create] 12 created · 0 errors
[audit] brain seq=15018 chain=…
3. Close a Cycle (auto-generate review draft)
$ cyberos-proj cycle close --id 01HZK3…
[cycle close] 12 issues · 8 done · 3 rolled · 1 cancelled
[review draft] generated via CUO/COO-skill
[review draft] saved to ./cycle-7-review.md (124 lines)
[notify] Account Manager pinged in CHAT
[audit] brain seq=15042 chain=…
4. Move all in-progress issues to next cycle
$ cyberos-proj cycle rollover --from 01HZK3… --to 01HZK4… --status in-progress
[rollover] 3 issues moved
[rollover] PROJ-1249 · PROJ-1251 · PROJ-1255
[audit] brain seq=15045 chain=…
5. Estimate calibration report
$ cyberos-proj calibration --member linh@cyberskill.world --range 90d
member: linh@cyberskill.world
task_class estimates actual_avg ratio trend
backend.feature 18 1.18× +18% ▲ improving
infra.config 9 0.96× -4% ▬ stable
qa.test_plan 12 1.42× +42% ▼ widening
overall 39 1.18× +18% ▲ improving
6. Export DSAR bundle
$ cyberos-proj dsar-export --subject linh@cyberskill.world --output linh-proj.zip
[dsar] subject: linh@cyberskill.world
[dsar] issues: 218 (authored) · 612 (assigned)
[dsar] comments: 1,894
[dsar] history: 4,217
[dsar] written: linh-proj.zip (38 MB)
7. Replay sync-engine conflict for debug
$ cyberos-proj sync replay --tenant cyberskill --since 1h --filter "issue.update"
[replay] 47 mutations · 2 rebases · 0 lost
[rebase] PROJ-1247 · client_seq=18 server_seq=98234 reason=concurrent_modification
[rebase] PROJ-1255 · client_seq=22 server_seq=98241 reason=concurrent_modification
Phase status & estimates
cyberos-proj| Capability | Status |
|---|---|
| Four primitives (Issue / Cycle / Project / Engagement) | planned · P1 |
| Sync-engine WS + optimistic apply | planned · P1 |
| Yjs CRDT for description / comments | planned · P1 |
| Per-engagement rate cards | planned · P1 |
| TIME ↔ PROJ ↔ INV chain | planned · P1 |
| Auto-roll at cycle close | planned · P1 |
| AI blocker detection | planned · P1 |
| AI cycle-review draft | planned · P1 |
| Estimate calibration report | planned · P1 |
| BRAIN Layer 3 ingestion | planned · P1 |
| Per-task / per-engagement ACL | planned · P1 |
| Vietnamese localisation | planned · P1 |
| Dependency graph + cycle detection | planned · P1 |
| Custom workflow per project | planned · P1+ |
| Mobile (offline-first) | planned · P3+ |
| Client-visible PORTAL view | planned · P2+ |
References
- PRD §9.5 — PROJ module: three primitives, sync-engine, AI features, FRs.
- PRD §9.10 — TIME module (upstream dependency).
- PRD §11.2 — NFRs that PROJ must satisfy.
- SRS §4.5 — Formal (FR pending) through (FR pending) with verification methods.
- Linear sync-engine — Tuomas Artman, "Scaling the Linear Sync Engine" (2023 talk).
- Yjs CRDT framework —
github.com/yjs/yjs; ywasm Rust binding. - PGroonga — Postgres full-text search with CJK tokenisation.
- NATS JetStream — message-streaming layer for WebSocket fan-out.
- Apollo Federation v2.5 — subgraph composition spec.
- Architecture context: infrastructure.html#proj.