Compare commits
2
Commits
refactor
...
t3/a29151f2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0de04dc263 | ||
|
|
ed00421a46 |
No files matched your search
@@ -0,0 +1,48 @@
|
||||
# Request intake and product delivery — proposed PRD addendum
|
||||
|
||||
Status: **proposed exact implementation text for owner-authorized behavior**. Prepared against `7e849a7b0b635d34950a5c5c2e4b78c4238fe651` for Vikunja #797 / Gitea #1839. Jason authorized the staged request-to-product work and GPT agents; this does not assert that the following exact version text has already received user approval. The approved `docs/prd/mosaic-stack.md` remains unchanged. Assign the next PRD version and record its exact approval only during the owning integration process.
|
||||
|
||||
Source design: `docs/plans/2026-11-03_request-to-product-design.md`. Implementation and acceptance: `docs/plans/2026-11-03_request-lifecycle-implementation.md`. Stage 1 implements existing REQ-WEB-2 and needs no duplicate requirement here. New prose uses “user”; current technical names such as `human.input`, `business.human` and `writeHumanFile` remain compatible until the separately tracked #798 identifier migration.
|
||||
|
||||
## Proposed additive text
|
||||
|
||||
Insert the following subsection after Projects. Requirement IDs below are proposed additions; check for collisions at integration before assigning the approved version. They describe Stack's lifecycle capability. A pomodoro product uses its own requirements and must never cite these as its product specification.
|
||||
|
||||
### Request intake and product delivery
|
||||
|
||||
- **REQ-INTAKE-1.** A user request can enter discovery without an implementation task or an approved product requirement. The stack preserves the original input event, message text, owner, business and conversation context in a durable intake record. If the product context is absent, it offers three choices through the Console: “New project — autonomous,” “New project — guided,” and “Add to existing project.” Each available decision option has a working answer control under REQ-WEB-2 and REQ-DEC-3. Cancellation retains the request and creates no work. A missing or insufficient PRD starts discovery or revision; it never causes the stack to invent a task, requirement ID or product attachment.
|
||||
|
||||
- **REQ-INTAKE-2.** Before a user confirms a new project, the stack displays its proposed name, original intent, mode, code source and revision, local code and records locations, repository and fork arrangement, tracker association and responsible roles. The confirmation binds that exact resource plan and its current organization revision. The first supported route may reuse a declared software-factory repository and an installed tracker board in its configured tree, while creating a distinct product project, separate code checkout, local records repository and local working repository. Sharing an upstream or tracker board never shares requirement authority or grants publication rights. Existing-project selection lists only authorized software projects and confirms the exact association; a chat grouping alone is not a provisioned business project.
|
||||
|
||||
- **REQ-INTAKE-3.** `project.bootstrap` is a protected action that remains a user hard wait under REQ-WAIT-3. An authenticated user selection and confirmation of the displayed plan authorizes only that bootstrap, once. Its typed executor may add exactly the approved project mapping and create the approved local resources within the configured managed data area. Ordinary organization writes remain unable to alter project mappings. The executor rejects stale revisions, collisions, links and overlapping ownership, validates the full business and project configuration, and records each partial effect for recovery. It makes the finished project available to broker validation, tracker association and subsequent role launches before reporting readiness. No reusable project-creation mandate is required or introduced by this increment.
|
||||
|
||||
- **REQ-INTAKE-4.** The user's intent specification remains distinct from the product PRD. The protected bootstrap executor may commit the exact original intent displayed and confirmed by the authenticated user to `spec/north-star.md`, with that confirmation recorded as provenance. Any generated or altered intent must first be displayed and explicitly confirmed by the user. Agents cannot use this executor to author an unconfirmed specification. Agents write assumptions, alternatives, PRDs and requirements as attributed agent-authored project records under REQ-PROJ-1 and REQ-PROJ-2.
|
||||
|
||||
- **REQ-INTAKE-5.** Autonomous mode lets agents make and record product choices within the confirmed intent and current role authority. A PM submits the exact product PRD and requirement set for a separate authorized review, initially by the business's technical arbiter acting as CTO through `prd.approve` with a current confirmed spec citation. The author cannot approve its own submission. Guided mode asks concise questions through the Console and returns the exact draft and requirement set to the user for approval. Free-text answers are attributed inputs, not implicit PRD approval. Both modes preserve the existing decision routing, identity checks and hard waits; product mode never approves spend, account creation, credentials, external messages, protected or remote pushes, deployment or other protected actions.
|
||||
|
||||
- **REQ-INTAKE-6.** Stack code activates a product requirement snapshot only after verifying an approval bound to the business, product project, PRD version, records commit and blobs, requirement contents, current intent spec and mode revision. It records authors, reviewer or user approver, decision and resolution evidence. An agent-written accepted status or document is not activation. Editing approved content requires a new approval. A changed intent, revoked approval or mode change is checked before the next action; superseded and revoked snapshots remain immutable historical evidence. Changing mode or revoking approval is an authenticated user control and does not retroactively rewrite task or run history.
|
||||
|
||||
- **REQ-INTAKE-7.** Requirement discovery and tracker task creation consult the same approved project snapshot. A product task identifies its business, product project, snapshot, requirement ID and original request, and its evidence includes source PRD version and commit. A requirement from a draft, wrong product, unapproved or revoked snapshot, or ambiguous context is refused. The selected tracker project must be installed in the business's authorized tracker tree. The built-in Mosaic Stack catalogue remains available only for the explicitly identified Stack project and compatible existing callers; it is never a fallback for another product. Local code pushes, reviews and delivery remain bound to the task's product project.
|
||||
|
||||
- **REQ-INTAKE-8.** The intake record tracks selection, bootstrap, discovery, PRD review, planning, implementation, verification, review and delivery, with an exact waiting reason and continuation whenever it cannot advance. Pre-task decisions remain nonblocking in the task system; the intake record owns their wait. PM staffing requests may name an intake request before a task exists. The chief launches existing authorized staff through the normal launch, model, processing and limit checks. Decision resolution, completed setup and role progress resume the responsible role automatically. Neither messages nor typed tools grant extra authority, and the assistant's existing messaging boundary remains intact. The user does not act as a messenger between agents or run decision commands to advance the workflow.
|
||||
|
||||
- **REQ-INTAKE-9.** Every lifecycle transition checks the expected request revision. Each effect has a durable operation identity and payload binding. Repeated input, duplicate answers, repeated notifications and process restart must not duplicate projects, PRD activation, tracker tasks or artifact delivery. An uncertain external write is reconciled against recorded operation evidence before further effects. An ambiguous or unprovable outcome remains an explicit wait; absence of a read result alone does not authorize another write. Restart recovery retains prior evidence and resumes incomplete continuations, including a role that died after receiving its message.
|
||||
|
||||
- **REQ-INTAKE-10.** Delivery means a usable artifact produced by real implementation and verification and approved by a separate reviewer for the exact latest work commit. The evidence links original request, product intent, approved PRD and requirements, tracker task, implementation commit, verification record, review request and verdict, and delivered artifact hash. The stack exports committed bytes from its trusted working repository and offers an authorized download. Product HTML does not run inside the privileged Console origin. The first supported artifact is self-contained offline HTML. Reviewed delivery is distinct from protected landing, remote publication and deployment and does not require those actions.
|
||||
|
||||
- **REQ-INTAKE-11.** Missing resources or authority produce one actionable setup wait naming the service, instance, resource or scope, available protected executor and condition for automatic resumption, without exposing secrets. Existing credential and account hard waits remain. Reusing configured factory resources is sufficient for the first supported delivery; creating new external repositories, tracker projects or accounts is not silently implied. An unsupported setup executor is reported explicitly, and the request cannot be called delivered while its required setup is incomplete.
|
||||
|
||||
## Proposed acceptance text
|
||||
|
||||
1. An isolated configured instance accepts the original single-file pomodoro request and an initial autonomous project selection/confirmation. Separate PM, technical approver, coder and reviewer roles produce an approved product PRD, a scoped real tracker task, working offline HTML, verification and independent review, and a downloadable artifact with requirement/PRD/task/commit/review evidence. No user message relay or command execution is required. Proposed 25-minute work, 5-minute break, start/pause/reset and phase-end cue defaults are product decisions recorded and approved in that product PRD, not attributed to the user's original request unless its actual text says them.
|
||||
2. Guided integration exercises questions, attributed text answers, a rejected/revised draft and exact user approval before task creation. Attachment integration covers an existing sufficient snapshot and an existing project that needs discovery/revision, with no duplicate project or borrowed requirement authority.
|
||||
3. Real process termination and restart against persistent stores exercise partial bootstrap, approval-before-activation, tracker-create response loss, review completion and export-before-notification. IDs and effects remain unique; uncertainty is visible and no historical evidence is rewritten.
|
||||
4. Deterministic role fixtures exercise real broker, tracker adapter, project repositories, typed tools, launch checks, commits, review protocol and signed-in Console endpoints. Their results are labeled fixture integration. A separate actual-model run in an authorized isolated instance supplies live role/host evidence; fixture success alone is not claimed as live acceptance. Production deployment and external setup require their own concrete authorization.
|
||||
|
||||
## Integration notes outside the proposed PRD text
|
||||
|
||||
This increment requires a narrow project-map writer and new `project.bootstrap` action, intentionally kept out of `ROUTED` and every role authority list. It does not need a generalized approval mechanism or expanded PM launch rights. Existing `prd.approve`, `record.write`, task, local working-push, review, message and chief launch authority provide the functional route. Duty contracts and typed adapters must expose it consistently; approved role authority files are unchanged by this planning task.
|
||||
|
||||
Existing Gitea `credential.mint` can handle a later concrete product grant/fork need. Existing Vikunja role scopes and `credentials.issue` do not automatically create tracker projects or mint tracker identities; the first route reuses an installed board and configured identities. Missing foundation resources remain protected setup blockers, not an instruction-only substitute for delivery.
|
||||
|
||||
The source design does not contain the verbatim original pomodoro input/event. Final original-request acceptance needs that provenance from the lead's incident evidence. A reconstructed request can be labeled representative for fixture development, but cannot be labeled the original acceptance run.
|
||||
@@ -0,0 +1,255 @@
|
||||
# Request Lifecycle Implementation Plan
|
||||
|
||||
> **For agentic workers:** Use `superpowers:executing-plans` to implement this plan task by task. Steps use checkbox syntax. This planning assignment authorizes no implementation, delegates or review runs; a later implementer follows the lead's execution assignment.
|
||||
|
||||
**Goal:** Carry an unattached user request through project selection, discovery, approved product requirements, real implementation, independent review and an openable artifact without user message relay.
|
||||
|
||||
**Architecture:** Extend the existing broker's append-only SQLite evidence and project records, with a small fixed lifecycle reducer and durable effect receipts. Reuse the configured software factory's repository and installed tracker board, existing role sessions, local working repositories and review protocol. There is no new workflow service, reusable creation mandate or general authorization framework.
|
||||
|
||||
**Tech Stack:** Existing Node.js ESM, `node:sqlite`, local Git, Vikunja adapter, typed harness tools and signed-in Console. Preserve the pinned harness and existing sandbox/processing/launch controls.
|
||||
|
||||
**Spec:** `docs/plans/2026-11-03_request-to-product-design.md`, stages 2–4; owner continuation and this assignment narrow the first supported route. Base: `7e849a7b0b635d34950a5c5c2e4b78c4238fe651`. Tracking context: Vikunja #797 / Gitea #1839. The separate `2026-11-03_request-intake-prd-addendum.md` is proposed exact implementation text, not an assertion that a new PRD version was approved.
|
||||
|
||||
## Purpose and boundary
|
||||
|
||||
This is a builder check and executable implementation plan, not evidence of delivered product behavior. Stage 1 is independently owned: consume `decision.preview.console`, `decision.resolve.console` and `/api/decisions/:id/confirmation|resolve` after integration. Do not redesign its option transport, grant summaries or confirmation. Intake-specific forms and reads belong here; generic decision buttons do not.
|
||||
|
||||
The first supported new product reuses a user-selected, already declared factory code source and an already installed tracker board in that business's configured tracker tree. It creates a distinct business project key, separate local code checkout, separate local records repository, chat-project association and local working repository. Sharing a tracker board or upstream does **not** share product requirement authority. Product tasks explicitly name their product and approved snapshot. This uses the design's authorized-resource reuse route and avoids requiring new external repositories, accounts, tracker projects or broad service credentials for an offline HTML result.
|
||||
|
||||
A resource plan displays the source project/commit, upstream and existing fork state, tracker root/selected board, paths, roles, mode and exact original intent before confirmation. Choosing autonomous or guided and confirming that displayed plan authorizes that one bootstrap. Reusing an existing project has a picker and confirmation bound to its current mapping. Unsupported resources produce a precise setup wait; silently substituting Stack requirements or a different board is forbidden.
|
||||
|
||||
## Global invariants
|
||||
|
||||
- Discovery, PRD drafting and their decisions have no fabricated task or requirement. Pre-task decisions use existing `blocking: false`; the intake journal owns the wait.
|
||||
- Preserve the original `human.input` event and message bytes. That is a current technical identifier; new prose uses “user.” Identifier migration belongs to #798 / Gitea #1840.
|
||||
- Only authenticated owner controls can select a mode, approve bootstrap, confirm generated intent or change mode. First support is the existing business owner Console identity; delegated-user creation is not implied.
|
||||
- Original intent becomes `spec/north-star.md` only through the protected executor of the exact user-confirmed plan. Agent assumptions stay in agent-authored PRD records. Existing `writeHumanFile`/`business.human`/`confirmed` identifiers remain compatible.
|
||||
- Broker reads and tracker creation use **one** project-scoped approved snapshot. Draft records, a JSON `status: accepted`, a bare requirement ID or a chat project alone confer no authority.
|
||||
- Autonomous PRD approval uses a distinct configured technical arbiter, initially CTO; guided approval uses the user. Bind the decision to exact PRD/requirement content, current spec and mode revision. No PM self-approval.
|
||||
- Existing role grants, messaging graph, processing state, launch revocation, quotas, tool limits, credential scopes and all hard waits remain enforced. A new `project.bootstrap` action stays user-gated; do not add it to `ROUTED` or any role authority list.
|
||||
- No protected push, remote publication, merge, deployment, external message or spend is needed to deliver the reviewed local HTML. Such later actions keep their existing gates.
|
||||
- Effects reserve an operation key before execution; a retry reconciles evidence. Append corrections and supersessions; never rewrite run records, events, decisions, prior snapshots or receipts.
|
||||
- Managed product paths are under the configured `dataRoot`; reject links, overlaps, collisions and unrelated partial contents. Existing projects keep their paths. No new repository-root files.
|
||||
- This assignment changes only its two planning artifacts. No queue movement, tracker writes, session/build-log edits, production setup or authority edits. Those explicit assignment limits supersede the general session protocol for this planning checkout.
|
||||
|
||||
## Review focus
|
||||
|
||||
1. Two requests sharing a tracker board or the same `REQ-*` spelling must never borrow one another's product authority (Task 5).
|
||||
2. A restart after an external task create but before its receipt must recover the existing task, including a subsequently closed task, without a second POST (Tasks 5 and 8).
|
||||
3. A valid selection followed by a changed organization, intent or mode must not execute stale bootstrap/approval work (Tasks 2 and 4).
|
||||
4. A delivered message followed by a dead role session must not strand the continuation; launch refusal must stay visible and resume only through allowed launch paths (Tasks 6 and 8).
|
||||
5. An approved commit followed by a new push, or an artifact containing links/traversal, must never export unreviewed or host-local bytes (Task 7).
|
||||
|
||||
## Builder findings and first-route decisions
|
||||
|
||||
| Existing seam at base | Consequence and chosen integration |
|
||||
| --- | --- |
|
||||
| `broker.mjs` `project.create` only inserts a chat grouping with optional `repo` | Create/associate the business mapping and records/code resources separately; retain `project.create` semantics. |
|
||||
| `organizationWriter().write` checks `organization-projects-protected` before and after serialization | Add a dedicated exact-add operation; do not introduce an escape flag into ordinary organization writes. |
|
||||
| `runtime.mjs` `fixedAtStart`/`sameFixed` rejects changed roots on reload | Admit only completed, receipt-backed managed project additions; retain restart/refusal behavior for arbitrary roots/credential/bot changes. |
|
||||
| `cli/src/config.mjs` `trackerFor` refuses two project files with `tracker.project` | Keep the single factory tracker root. Product `.mosaic/project.json` omits `tracker.project`; the approved resource binding selects an installed board from that root's tree. |
|
||||
| `tasks/src/verbs.mjs` and `broker.mjs` separately call `loadRequirements()` | Replace product lookups with a shared resolver. Keep the static loader only for the explicitly bound legacy Stack catalogue. |
|
||||
| `staff.request` requires `task_ref`; PM has no launch authority | Add an intake alternative to that typed request, still PM → chief. Before a PM is running, use assistant → chief and the existing launch tool. |
|
||||
| `typedTools` gates requirements on tracker/task authority and freezes project enums at launch | Expose scoped discovery reads without a fabricated task; new code/review sessions must be built after project activation. |
|
||||
| `task.create` documents that a lost create answer cannot currently be reread | Add durable operation markers and reconciliation before claiming lifecycle idempotency. |
|
||||
| `checkPush`/`recordPush` do not bind a task's product requirement scope to `push.project` | Add that binding for scoped tasks before accepting bundle bytes and at record time. |
|
||||
| `project` records accept direct `docs/NAME.md`, not `docs/prd/NAME.md` | Product PRDs use `docs/prd-VERSION.md`; do not reuse the static catalogue's path schema. |
|
||||
| Gitea grants can provision identities/forks, but role Vikunja scopes cannot create projects | Reuse the installed tracker board and existing roles for v1. Do not invent a Vikunja provisioning capability. |
|
||||
|
||||
The configured factory is a selected declared project, not a hard-coded `stack` key. For new products clone its local code source at the displayed commit into `<dataRoot>/products/<business>/<project>/code`, preserve history, and write a local bootstrap commit changing only `.mosaic/project.json` to the new ID and explicitly displayed permitted project vars. Do not copy role overrides or broaden limits from the template. The artifact lives at `products/<project>/pomodoro.html` in the product clone; the factory checkout is never edited. Records default to `<dataRoot>/projects/<business>/<project>` and have no remote. Working storage remains `workingRepo(dataRoot,business,project)`.
|
||||
|
||||
Reuse the factory's validated upstream URL in the new mapping. Existing actor forks may be reused only after the existing identity/grant checks; a new product key does not inherit `publish` rights. Local `push_working` and `fetch_review` need no new remote grant. If remote publication is later requested, the chief uses the existing Gitea `credential.mint` path for the product scope and a separate `git.push.remote` approval for the exact commit. No remote provisioning is a hidden dependency of the first offline delivery.
|
||||
|
||||
## Producer/consumer contract
|
||||
|
||||
All shapes below are proposed strict, versioned interfaces. Reject extra keys at public boundaries. IDs use existing repository validators; hashes are SHA-256, Git commits use the existing full-OID validator. Broker-derived identity is never an agent argument. `request` is the original `human.input` event ID, not the chat message ID.
|
||||
|
||||
```text
|
||||
ResourcePlan = {
|
||||
version:1, business, request, project, name, chat_project:null|id,
|
||||
mode:"autonomous"|"guided", organization_revision,
|
||||
source:{project, commit, remote:null|httpsURL,
|
||||
forks:[{instance,url,grant:null|id,state:"verified"|"not-granted"}]},
|
||||
code_root, records_root,
|
||||
tracker:{root:number, project:number},
|
||||
staff:{pm, technical_reviewer, coder, reviewer, chief},
|
||||
intent:{text, sha256, source_message, generated:boolean},
|
||||
project_vars:{...validated project-layer vars, no tracker.project},
|
||||
existing:boolean
|
||||
}
|
||||
PlanBinding = {plan:ResourcePlan, digest, decision, choice}
|
||||
RequestState = {
|
||||
version:1, request, business, revision:number, source_message,
|
||||
thread:null|id, session:null|id, owner, pm,
|
||||
phase:"selection"|"bootstrap"|"discovery"|"prd-review"|"planning"|
|
||||
"implementation"|"review"|"delivery"|"delivered"|"cancelled",
|
||||
project:null|key, chat_project:null|id, mode:null|"autonomous"|"guided",
|
||||
mode_revision:number, plan_digest:null|hash, spec_commit:null|oid,
|
||||
snapshot:null|id, tasks:[task_ref], delivery:null|id,
|
||||
question:null|{id,text,options:[{key,text}],answer:null|event_id},
|
||||
candidate:null|PrdCandidate, selection:null|{decision,bindings:[PlanBinding]},
|
||||
wait:null|{kind:"decision"|"setup"|"launch"|"effect",
|
||||
code, subject, resume_phase, observed_revision}
|
||||
}
|
||||
PrdCandidate = {
|
||||
version:1, request, project, prd_version:"1.0", records_commit,
|
||||
prd_path:"docs/prd-1.0.md", prd_blob,
|
||||
requirements:[{id,title,path,blob}], spec_commit, mode_revision
|
||||
}
|
||||
ApprovedSnapshot = {
|
||||
version:1, id, business, project, prd_version, records_commit,
|
||||
prd_path, prd_blob, spec_commit, requirements:[{id,title,text,path,blob}],
|
||||
authors:[{definition,instance,commit}],
|
||||
approval:{decision, resolution_seq, by, via}, mode_revision,
|
||||
origin:"product"
|
||||
}
|
||||
BuiltinSnapshot = {
|
||||
origin:"builtin", id, business, project, prd, version,
|
||||
requirements:[{id,title}], catalog_sha256
|
||||
}
|
||||
CatalogSnapshot = ApprovedSnapshot | BuiltinSnapshot
|
||||
TaskScope = {project_key, requirement_snapshot, requirement}
|
||||
EffectReceipt = {
|
||||
version:1, business, request, op, kind, digest,
|
||||
stage:"prepared"|"committed"|"uncertain"|"refused",
|
||||
result:null|object, code:null|string
|
||||
}
|
||||
Delivery = {
|
||||
version:1, id, business, request, project, snapshot,
|
||||
task_ref, commit, review_request, verdict,
|
||||
artifact:{path,blob,sha256,bytes,mime:"text/html"},
|
||||
verification:{record_path,record_commit}, message
|
||||
}
|
||||
```
|
||||
|
||||
`request_events` stores `{seq,business,request,revision,kind,actor_role,actor_run,at,body}` with unique `(business,request,revision)` and append-only triggers. `body` is a validated transition payload; `readRequest` reduces it into `RequestState`. Creation is unique per source event. `request_effects` stores the `EffectReceipt` fields plus sequence/time, unique `(business,request,op,stage)`; an operation's digest/kind cannot change. `request_snapshots` stores immutable `ApprovedSnapshot` JSON keyed by ID, and `request_snapshot_events` appends activation/revocation with project, revision, snapshot and cause. `request_project_events` stores `{seq,business,project,revision,kind,at,body}` with unique `(business,project,revision)` and append-only triggers. It holds shared project mode changes and attachment evidence. Mode writes compare the displayed project mode revision as well as the request revision in one transaction; another attached request cannot race a stale mode write through. These are operational records, not system configuration. All indexes/projections are rebuildable. Never repurpose mutable `status` files as authority.
|
||||
|
||||
Only fixed effect kinds are supported: `bootstrap`, `prd-submit`, `prd-activate`, `task-create`, `continuation`, `delivery`. Intermediate bootstrap steps have deterministic keys under their parent's op. No agent-facing “execute arbitrary effect” API.
|
||||
|
||||
## Task 1: Durable pre-task intake and selection boundary (stage 2)
|
||||
|
||||
**Files:** Create `packages/bus/src/request-lifecycle.mjs`, `packages/bus/src/request-store.mjs`, `packages/bus/src/migrations/3n-3o.sql`, `packages/bus/tests/request-intake.test.mjs`. Modify `packages/bus/schema.sql`, `packages/bus/src/store.mjs`, `packages/bus/src/broker.mjs`, `packages/bus/src/runtime.mjs`, `packages/business/src/vocabulary.mjs`.
|
||||
|
||||
**Interfaces:** `createRequestStore(store)` returns `readRequest(business,request)`, `appendRequest({business,request,expectedRevision,kind,body,actor})`, `prepareEffect(receipt)` and `finishEffect(receipt)`. These are host-only. `createRequestLifecycle({journal,services})` returns `open(identity,args)`, `get(identity,args)`, `resume(business,request)` and `recover()`. Broker verbs: `request.open({request})`, `request.get({request})`, `request.projects({request})`, and PM-only `request.propose({request,revision,op,source_project,project,name,tracker_project})`. Opening captures intake; proposing validates a concrete resource plan and creates the mode decision. The PM chooses a sensible source/name from declared resources; the user sees and confirms them before any bootstrap effect. PM may open a reachable user-origin request through existing `message.send` authority; owner may read its own request. Opening twice returns the same state.
|
||||
|
||||
- [ ] **Red:** Add `opens_without_task_or_requirement`, `duplicate_open_is_same_request`, `rejects_foreign_input`, `non_owner_cannot_select` and `reopen_store_reduces_same_state`. Assert no `task.created` and null `task_ref`/`requirement_ref` on intake decisions.
|
||||
- [ ] **Red verification:** Run `node --test packages/bus/tests/request-intake.test.mjs`; new exports/verbs must fail before implementation.
|
||||
- [ ] **Green:** Add append-only tables, offline migration and schema digest/version updates using existing migration checks. Keep earlier migrations immutable; if another integrated change takes `3o`, rebase this single new migration rather than editing its predecessor.
|
||||
- [ ] **Green:** Add `project.bootstrap` to both closed `ACTIONS` lists (`business/src/vocabulary.mjs` and `bus/src/broker.mjs`) only; update their equality/closed-vocabulary tests, never either `ROUTED` list. `request.propose` builds the three exact keys `autonomous`, `guided`, `existing` in a user-routed nonblocking decision, with `approvalChoice: "autonomous"`. This decision is an enumerated selection: guided/existing are valid selections, not denials inferred from `approvalChoice`. Its lifecycle executor uses the immutable choice-to-plan bindings, never generic action consumption. Before opening it, prepare and validate the displayed resource proposals; if prerequisites are missing, open one setup wait instead. Cancellation uses existing withdrawal, creates no resources, and retains the source request.
|
||||
- [ ] **Green:** For `existing`, return only accessible software project mappings; exclude library projects, unknown tracker associations and another business. A picker stages a candidate binding; a subsequent ordinary decision confirms that exact association. Existing matching requirements still require an explicit scope choice by PM; no text matching silently establishes authorization.
|
||||
- [ ] **Verification:** Run `node --test packages/bus/tests/request-intake.test.mjs packages/bus/tests/schema.test.mjs packages/bus/tests/store.test.mjs packages/business/tests/hard-waits.test.mjs`. Expect zero failures; the hard-wait test intentionally gains only `project.bootstrap`.
|
||||
- [ ] **Commit:** Commit this task's named implementation/tests only after green checks, when the execution assignment authorizes local commits.
|
||||
|
||||
## Task 2: Protected project bootstrap that becomes usable at runtime (stage 2)
|
||||
|
||||
**Files:** Create `packages/business/src/project-bootstrap.mjs`, `packages/bus/src/request-bootstrap.mjs`, `packages/business/tests/project-bootstrap.test.mjs`, `packages/bus/tests/request-bootstrap.test.mjs`. Modify `packages/business/src/organization.mjs`, `packages/project/src/index.mjs`, `packages/bus/src/runtime.mjs`, `packages/bus/src/broker.mjs`, `packages/cli/src/config.mjs`, `packages/cli/src/launcher.mjs`, `packages/bus/src/process.mjs`, `packages/seat/src/working.mjs`. Test existing `packages/business/tests/library-projects-protected.test.mjs`, `packages/project/tests/init-failure.test.mjs`, `packages/cli/tests/launcher.test.mjs`.
|
||||
|
||||
**Interfaces:** `prepareBootstrap({business,request,sourceProject,project,name,mode,dataRoot,organizationRevision,tracker,staff,intent}) -> Promise<ResourcePlan>` in `request-bootstrap.mjs`; `project-bootstrap.mjs` validates the exact mapping/path addition for the organization writer. `executeBootstrap({binding,journal,services}) -> Promise<{project,chat_project,spec_commit,organization_revision}>`. `organizationWriter().addProject(id,{revision,project,entry,receipt},actor)` is a new narrow host method; `entry` is only `{root,repo,remote?}`. `activateManagedProject({business,project,receipt,organization_revision}) -> Promise<void>` is a runtime-only operation. Host IPC `request.admission({business,project}) -> {ready,revision,code}` exposes readiness to the launcher through `process.mjs`; scope it to the host business and fail closed if unavailable. `initializeWorking({dataRoot,business,project,root,env?}) -> Promise<{repo,commit}>` is a new host-only export in `seat/src/working.mjs`, using its existing repository lock and private safe `seed` helper, with no work ref or push authority. Bootstrap calls it after the code seed commit and journals the returned root commit. Existing `initProject`, `writeHumanFile` and `project.create` remain compatible.
|
||||
|
||||
- [ ] **Red:** Test `bootstrap_connects_all_resources`: inspect the actual organization file, code `.mosaic/project.json`, records HEAD/spec author, chat association, tracker tree/board, working-repo seed and next launch's project list. Test stale organization/plan, changed source commit, symlink ancestor, path overlap, preexisting unrelated data and partial initialization. Assert every ordinary organization writer still rejects project changes.
|
||||
- [ ] **Red verification:** Run `node --test packages/business/tests/project-bootstrap.test.mjs packages/bus/tests/request-bootstrap.test.mjs`.
|
||||
- [ ] **Green:** Under the existing organization lock/receipt discipline, factor a private exact-add writer used only by `addProject`; reject replacement/removal, library entries, unrelated key changes and a mismatched plan receipt. Compare both input and serialized document. A plan with a stale revision requires a new preview/confirmation, never silent rebasing.
|
||||
- [ ] **Green:** Journal path reservations, clone/seed, mapping addition, records init, exact-intent save, chat association and runtime activation separately. `initProject` currently requires a declared project: prepare the code seed, publish the reserved mapping, then initialize records under that mapping. Mark it pending in broker admission until every step passes. For interrupted local Git effects compare deterministic paths, stored before/after commits and exact bytes; retain ambiguous contents and return `bootstrap-uncertain`. Do not remove unrelated paths or rewind commits.
|
||||
- [ ] **Green:** Save original displayed intent through `writeHumanFile` as the authenticated owner recorded by the decision; generated wording requires its own exact preview/confirmation. Record confirmation event and resulting spec commit. Keep `writeRecord` unable to write `spec/`.
|
||||
- [ ] **Green:** Preserve the single tracker root: the product file omits `tracker.project`; persist its selected board in the immutable plan and admission projection. `trackerFor` must ignore reserved managed additions until committed and verify product IDs after completion, including after a fresh boot. Never create a second tracker adapter per product or fall back to the root board on failure.
|
||||
- [ ] **Green:** Extend runtime reload only for receipt-backed additive roots within `<dataRoot>/products`, already excluded from secret locations by the Credentials data-root fence. Revalidate the full business, unchanged credentials/bots/libraries/roles, prior mappings and completed plan. Admit the mapping to broker only after readiness; rebuild readiness from receipts on restart. Launcher already rereads business in `check`; additionally refuse a reserved/unready product from cloning until admitted. Existing arbitrary reload changes still answer `restart: true` or refuse. Existing sessions receive no new project tool enum; Task 6 schedules a fresh suitable coder/reviewer session.
|
||||
- [ ] **Verification:** Run the new tests plus `node --test packages/business/tests/library-projects-protected.test.mjs packages/project/tests/init-failure.test.mjs packages/cli/tests/launcher.test.mjs`. Kill/reopen the fixture after mapping write and after spec commit; recovery must reach the same mapping/spec exactly once, without changing factory files.
|
||||
- [ ] **Commit:** Commit this bounded bootstrap path after green checks. Do not execute bootstrap on any running instance.
|
||||
|
||||
## Task 3: Intake Console controls and guided answers (stage 2)
|
||||
|
||||
**Files:** Create `packages/webui/src/request-http.mjs`, `packages/webui/src/public/requests.js`, `packages/webui/tests/request-http.test.mjs`, `packages/webui/tests/request-browser.test.mjs`. Modify `packages/webui/src/serve.mjs`, `packages/webui/src/console-bus.mjs`, `packages/webui/src/bus.mjs`, `packages/webui/src/public/index.html`, `packages/webui/src/public/chat.js`, `packages/webui/tests/browser.test.mjs`, `packages/bus/src/request-lifecycle.mjs`, `packages/bus/src/broker.mjs`.
|
||||
|
||||
**Interfaces:** `requestHTTP(req,res,{path,requestRead,requestWrite,session,origin})` handles `GET /api/requests/:request`, `GET /api/requests/:request/projects`, and `POST /api/requests/:request/answer|attach|mode`. The reads call `request.get.console` and `request.projects.console`; the writes call owner-only broker verbs `request.answer.console({request,revision,question,op,text})`, `request.attach.console({request,revision,project,op})`, `request.mode.console({request,revision,mode_revision,mode,op})`. All return `RequestState`; authenticated owner reads also support `GET /api/requests/:request/draft` calling `request.draft.console({request})` and returning the candidate PRD text and full requirement records at its bound commit. That read is produced by Task 4 and is not a generic file-read endpoint. Attachment stages a confirmation decision, not a mapping write. `request.question({request,revision,op,text,options?})` is PM-only and records an outstanding question ID; text answers are not PRD approvals.
|
||||
|
||||
- [ ] **Red:** Test signed-in owner selection, authorized picker, guided free-text answer and stale revision. Assert denied origins, expired sessions, readers/testers/granted nonowners cannot mutate intake. No generic decision endpoint/schema changes are part of this task.
|
||||
- [ ] **Red verification:** Run `node --test packages/webui/tests/request-http.test.mjs packages/webui/tests/request-browser.test.mjs`.
|
||||
- [ ] **Green:** Mount the intake panel from the source chat request. Render server-selected plans and waiting reason as escaped data; use Stage 1's authoritative decision options and existing confirmation endpoints for decisions. New text/attach/mode writes enforce the same signed-in owner, same-origin, writable-Console and bounded-body rules. Extend `CONSOLE_VERBS` with only these new `.console` verbs, using `consoleCall` and its existing verified `(provider,iss,sub)` transport, never an owner CLI proxy selected by client input. Check `s.console` and the configured owner explicitly; the existing `#human` CLI guard rejects Console capabilities and must not be weakened. Agent intake reads keep their unsuffixed names. Mode change is an explicit user control with expected revision; it invalidates pending autonomous approval/dispatch admissions at the next action.
|
||||
- [ ] **Green:** Guided answers become attributed `human.input` events linked to question and request, with duplicate op protection. They do not silently rewrite the original spec. Persist answers; enqueue PM continuation after commit. “Cancel” withdraws the selection or appends cancellation; an already-created project remains evidence, never auto-deleted.
|
||||
- [ ] **Verification:** Run the two new suites and `node --test packages/webui/tests/browser.test.mjs`. Update its exact script-list expectation for `requests.js`. Test reload after lost answer response: read the stored answer/op first, no blind repost. Existing grant summaries and confirmation regressions remain green after Stage 1 integration.
|
||||
- [ ] **Commit:** Commit intake-specific UI and tests; do not fold generic Console decision work into this commit.
|
||||
|
||||
## Task 4: Exact-version product PRD approval and activation (stage 3)
|
||||
|
||||
**Files:** Create `packages/project/src/prd.mjs`, `packages/bus/src/requirement-catalog.mjs`, `packages/project/tests/prd.test.mjs`, `packages/bus/tests/prd-activation.test.mjs`. Modify `packages/bus/src/request-lifecycle.mjs`, `packages/bus/src/broker.mjs`, `packages/bus/src/runtime.mjs`, `packages/project/src/index.mjs`, `packages/project/src/read.mjs`, `packages/webui/src/request-http.mjs`, `packages/webui/src/public/requests.js`.
|
||||
|
||||
**Interfaces:** `readPrdCandidate({business,project,dataRoot,request,prd_version,records_commit,prd_path,requirement_ids,mode_revision}) -> Promise<PrdCandidate>` reads bounded committed regular blobs using existing Git safety rules. `prd.submit({request,revision,op,prd_version,records_commit,prd_path,requirement_ids}) -> {candidate,decision}` is PM-only, requires `record.write`, and internally raises the existing `prd.approve` action. `createRequirementCatalog({journal,readSpec,builtinBinding})` returns `resolve({business,project,snapshot?}) -> Promise<CatalogSnapshot>` and `activate({request,decision}) -> Promise<ApprovedSnapshot>`; the latter is host-only. `Broker.requirementsFor(cap,{project_key,requirement_snapshot?,requirement?}) -> Promise<CatalogSnapshot>` is the shared, authenticated consumer used in Task 5.
|
||||
|
||||
- [ ] **Red:** Test autonomous PM → configured CTO approval, PM/self-role denial, guided user approval, changed draft, changed requirement blob, stale spec, changed mode, revoked snapshot, wrong business and forged `status: accepted`. Assert no task exists before activation.
|
||||
- [ ] **Red verification:** Run `node --test packages/project/tests/prd.test.mjs packages/bus/tests/prd-activation.test.mjs`.
|
||||
- [ ] **Green:** Bound this first route to 64 requirements, 32 KiB PRD text, 16 KiB per requirement text and 256 KiB aggregate candidate content; reject oversized candidates before decision creation. PM writes `docs/prd-1.0.md` and `requirements/REQ-POMO-1.json` etc. with existing `record.write`; validate strict requirement records, IDs/titles, unique paths and exact content at one reachable records commit. Candidate hashes are server-read, never trusted agent assertions. At submission and activation, compare each selected path at current HEAD with its candidate blob; unrelated record commits do not invalidate it, but an edited selected draft requires a new submission. Read requirement JSON via a private committed-blob helper; do not broaden the public spec editor's file access.
|
||||
- [ ] **Green:** In autonomous mode raise `prd.approve` with `domain: "technical"`, current confirmed spec citation and target bound to the candidate; require a distinct authorized arbiter instance/definition. Missing or self-routing technical arbiter becomes a setup wait, not self-approval. Guided mode deliberately raises the same gated action without a routing spec citation so it goes to the user; its separate candidate binding still includes and revalidates the current spec. Display exact draft, requirements and version through the request panel before approval.
|
||||
- [ ] **Green:** After resolution, activation rereads the immutable candidate, current intent, mode and role authority (not whether the approving run is still alive) and checks matching approving choice/resolution. Append the snapshot and activation receipt atomically with the continuation. A changed candidate requires a new decision. Repeated activation returns the same ID. A mode/spec change revokes outstanding admissions; prior task evidence remains immutable. Owner `request.mode.console` and existing spec-save notices trigger this invalidation. Support owner-only `prd.revoke.console({project,snapshot,revision,reason,op})` for explicit revocation through `POST /api/requests/:request/revoke`, with the same Console controls and whitelist integration as Task 3; pending work waits for replacement authority.
|
||||
- [ ] **Verification:** Run both new suites and `node --test packages/project/tests/read.test.mjs packages/project/tests/human-file.test.mjs packages/business/tests/spec-review-contracts.test.mjs`. Fresh runtime must resolve the same approved snapshot solely from committed records and journal evidence. Preserve existing decision closure/notification behavior.
|
||||
- [ ] **Commit:** Commit activation/catalogue code and tests after green checks. Do not claim the Stack PRD amendment itself has already been approved.
|
||||
|
||||
## Task 5: One scoped requirement validator and recoverable tracker creates (stage 3)
|
||||
|
||||
**Files:** Create `packages/tasks/src/create-recovery.mjs`, `packages/tasks/tests/scoped-requirements.test.mjs`, `packages/tasks/tests/create-recovery.test.mjs`, `packages/bus/tests/scoped-push.test.mjs`. Modify `packages/tasks/src/verbs.mjs`, `packages/tasks/src/adapter.mjs`, `packages/tasks/src/startup.mjs`, `packages/tasks/src/sync.mjs`, `packages/bus/src/broker.mjs`, `packages/cli/src/config.mjs`, `packages/cli/src/git-socket.mjs`, `packages/bus/src/process.mjs`, `packages/bus/src/runtime.mjs`.
|
||||
|
||||
**Interfaces:** Broker `requirements({project_key?,requirement_snapshot?})` and host method `requirementsFor` both use Task 4's catalog. Add optional `{project_key,requirement_snapshot,op}` to existing `task.create`; product callers require all three plus existing `request` and `requirement`. Existing numeric `project` remains the tracker board ID, distinct from `project_key`. `reconcileCreate({ctx,receipt}) -> Promise<{state:"committed",task_ref}|{state:"uncertain",code}>` reads through sync authority, never writes as sync. Adapter exposes host-only `reconcileCreates(business)` and `inspectProject(business,project)` for startup/recovery/admission. Add host-only `Broker.recordRecoveredCreate({receipt,task_ref,snapshot})`: verify the prepared identity/body/target and write the missing task event once, with original attribution. Never expose this method as a socket verb.
|
||||
|
||||
- [ ] **Red:** Test two products on one board with the same requirement ID but different snapshots; draft/unapproved/revoked/wrong-project/wrong-board/ambiguous requests; omission by product callers; and explicitly bound legacy Stack compatibility. Assert broker and task creation return/accept the same exact snapshot, including its version and content commit.
|
||||
- [ ] **Red:** Test lost response after tracker create, restart before receipt, duplicate PM calls, failure during label/assignment follow-up, a closed matching task, edited marker, duplicate marker and complete scan failure. Assert at most one create POST after an uncertain result; a negative/partial scan alone never authorizes another POST.
|
||||
- [ ] **Red verification:** Run `node --test packages/tasks/tests/scoped-requirements.test.mjs packages/tasks/tests/create-recovery.test.mjs packages/bus/tests/scoped-push.test.mjs`.
|
||||
- [ ] **Green:** Remove the private product ID set from `verbs`; call `Broker.requirementsFor` both when planning and immediately before create admission. Resolve tracker board from the request's confirmed binding, recheck installed tree membership and role/session authority, and append a prepared op before network I/O. Record `TaskScope`, source PRD version/commit, spec commit and op in `task.created` evidence. Task filtering/trail must distinguish product keys when IDs collide.
|
||||
- [ ] **Green:** Bind the built-in catalogue only to a startup-validated Stack project, passed explicitly by `bootConfig` as `{business,project,tracker_project}`. Confirm its code project identity and repository-owned Stack PRD/catalogue relationship; do not infer it from the first project, any `REQ-*` prefix or the board number. Unscoped legacy calls preserve the existing `{prd,version,requirements}` response and may use that binding only when their source request has no intake record or conflicting product binding. Any intake request, including selection/discovery, requires an approved product snapshot before task creation. The internal builtin wrapper records the baked catalogue version/hash and never fabricates a product approval decision. New product calls never fall back. Keep `packages/tasks/requirements.json` and its existing approved-PRD consistency test unchanged in this task.
|
||||
- [ ] **Green:** Use a stable visible description suffix `Mosaic operation: <op>; request: <request>; scope: <project_key>; snapshot: <snapshot>` added by the adapter. Journal the complete create-body digest and target board. On uncertainty, scan all pages including completed tasks with the sync reader; adopt exactly one matching marker only after validating board, creator bot and original create fields. A changed/ambiguous/missing marker stays `task-create-uncertain` with a reconciliation wait. Resume labels/relations through existing read-before-write checks. Record recovered create attribution from the original prepared identity, never from a fabricated live capability.
|
||||
- [ ] **Green:** Add product binding to git admission: extend `checkPush(cap,task_ref,project)` and pass `project` from the git socket through `process.mjs`/runtime before reading bundle bytes; repeat in `recordPush`. A scoped task can push/review/export only from its bound project. Preserve legacy recorded task handling without inventing product scope for old evidence.
|
||||
- [ ] **Verification:** Run new tests plus `node --test packages/tasks/tests/requirements.test.mjs packages/tasks/tests/verbs.test.mjs packages/tasks/tests/tree.test.mjs packages/tasks/tests/adapter.test.mjs packages/cli/tests/git-socket.test.mjs`. Exercise an actual file-backed Store close/reopen and persistent fake tracker; an in-memory reducer replay is not a restart test.
|
||||
- [ ] **Commit:** Commit scoped validation and create recovery only after all listed checks pass.
|
||||
|
||||
## Task 6: Typed role continuations through implementation and review (stage 3)
|
||||
|
||||
**Files:** Create `packages/bus/tests/request-continuation.test.mjs`, `packages/harness/tests/request-tools.test.mjs`, `packages/cli/tests/request-launch.test.mjs`. Modify `packages/bus/src/request-lifecycle.mjs`, `packages/bus/src/broker.mjs`, `packages/bus/src/runtime.mjs`, `packages/cli/src/launcher.mjs`, `packages/bus/src/process.mjs`, `packages/harness/src/tools.mjs`, `packages/harness/src/runner.mjs`, `packages/seat/src/sandbox.mjs`, and duty contracts `roles/pm.md`, `roles/chief-of-staff.md`, `roles/cto.md`, `roles/coder.md`, `roles/reviewer.md`, `roles/assistant.md` in the later implementation only.
|
||||
|
||||
**Interfaces:** Extend `staff.request`/`request_staff` to exactly one of `{task_ref,...}` or `{request,...}`, keeping `{roles,note?,decision?}` and PM-only `message.send` checks. Add typed tools `intake_open`, `intake_status`, `intake_projects`, `intake_propose`, `intake_question`, `submit_prd`, `advance_request` mapping to the already specified verbs. Add `request.advance({request,revision,op}) -> RequestState` as PM-only: it verifies evidence for the next fixed transition, never accepts a claimed success state. Lifecycle `resume` records one durable continuation intent per `(request,revision,target,step)`; runtime `recover` sweeps unfinished intents on startup and after relevant events, plus a bounded 30-second runtime reconciliation pass for missed notifications. It processes only these fixed request stages, deduplicates by durable continuation key and does not add another scheduler service.
|
||||
|
||||
- [ ] **Red:** Test pre-task staff request, correct chief launch, wrong-role refusal, actual PM/CTO/coder/reviewer tool manifests, absent tracker during discovery, a running role with an old project enum, revoked launch, full limits and a dead role after message delivery. Existing assistant message restrictions must still reject direct PM/reviewer coordination.
|
||||
- [ ] **Red verification:** Run `node --test packages/bus/tests/request-continuation.test.mjs packages/harness/tests/request-tools.test.mjs packages/cli/tests/request-launch.test.mjs`.
|
||||
- [ ] **Green:** Preserve assistant → chief → PM intake and chief → assistant delivery. A PM uses discovery records and scoped catalog tools without creating a task; after activation it creates/assigns the task using Task 5 and requests coder/reviewer staff. Chief launches existing configured roles under the normal `launch` tool. Do not hire a PM/CTO/reviewer through the empty chief `hireable` list or add PM `role.launch` authority.
|
||||
- [ ] **Green:** Continuations name source request/revision, current phase, evidence IDs and exact next typed operation. Decision closure, approved snapshot, task/create/review evidence, session end, successful launch and cleared prerequisites trigger reconciliation. Append continuation intent and outgoing message atomically; link acknowledgement to a validated transition/effect, not `message.read`. On a dead run with no progress, deliver the same continuation key to its successor and recheck existing effect receipts. Persist attempt/refusal state; avoid message floods and busy retry loops.
|
||||
- [ ] **Green:** If the chief or worker is unavailable, store the exact existing launch refusal and surface it in the intake panel. A new relevant prerequisite revision/session event retries through the same chief path. No synthetic unlimited capability, direct privileged worker spawn or user command relay. A role that lacks the new product in its session manifest waits for its current turn to drain; chief uses its existing permitted end/relaunch path for that role, never interrupting unrelated active work. The next launch uses admitted mappings and real `ensureCheckouts`. Use Task 2's host-only `request.admission` read for readiness.
|
||||
- [ ] **Green:** Update typed schemas with product snapshot fields and intake alternatives; expose reads for eligible PM/CTO before task existence and writes only to existing authorized roles. Ensure runner/MCP dispatch and sandbox module mounts include the new imported modules without mounting credentials/configuration. Update role duty prose to describe discovery, exact approval, resume and artifact completion; no `.json` authority grants are needed on this first route.
|
||||
- [ ] **Verification:** Run new tests plus `node --test packages/harness/tests/tools.test.mjs packages/harness/tests/mcp-server.test.mjs packages/harness/tests/pi-session.test.mjs packages/business/tests/workflow-roles.test.mjs packages/business/tests/chief-of-staff.test.mjs`. Inspect manifests for both configured supported harnesses; no generic broker escape tool.
|
||||
- [ ] **Commit:** Commit continuation/tool/contract updates after green checks and the normal execution review gate. This planning task makes none of those edits.
|
||||
|
||||
## Task 7: Export a reviewed artifact and deliver its evidence (stage 4)
|
||||
|
||||
**Files:** Create `packages/seat/src/artifact.mjs`, `packages/seat/tests/artifact.test.mjs`, `packages/bus/tests/request-delivery.test.mjs`, `packages/webui/tests/artifact-http.test.mjs`. Modify `packages/bus/src/request-lifecycle.mjs`, `packages/bus/src/runtime.mjs`, `packages/bus/src/broker.mjs`, `packages/webui/src/request-http.mjs`, `packages/webui/src/public/requests.js`, `packages/webui/src/bus.mjs`, `packages/harness/src/tools.mjs`.
|
||||
|
||||
**Interfaces:** `readReviewedArtifact({repo,commit,path,maxBytes}) -> Promise<{bytes,blob,sha256,mime}>` accepts a trusted working-repo path and a regular committed blob, max 1 MiB for this route. PM typed `deliver_request` → `request.deliver({request,revision,op,task_ref,verdict,path,verification_record}) -> Delivery`; `verification_record` is `{path,commit}` in the records repo. Host resolves all other evidence. `GET /api/requests/:request/artifact/:delivery` returns a protected attachment from broker-authorized delivery evidence. Broker read `request.artifact.console({request,delivery}) -> {mime,filename,base64,sha256}` is owner-only and bounded to 1 MiB decoded. Add it to `CONSOLE_VERBS`; set `consoleCall`'s output cap to 2 MiB for this verb only (its current 1 MiB cap cannot hold the base64 payload), below the existing bus Client 4 MiB response cap; the HTTP layer decodes bytes and enforces request ownership again. It is not a harness tool.
|
||||
|
||||
- [ ] **Red:** Test approved artifact bytes, stale verdict after newer push, changes verdict, wrong-project task, path traversal/symlink/submodule/oversize, forged verification record and duplicate export/notification. Assert exact blob/hash, task scope, review request and commit equality.
|
||||
- [ ] **Red verification:** Run `node --test packages/seat/tests/artifact.test.mjs packages/bus/tests/request-delivery.test.mjs packages/webui/tests/artifact-http.test.mjs`.
|
||||
- [ ] **Green:** Coder builds/tests the actual file, commits locally in its sandbox clone and calls `push_working`. A distinct reviewer fetches the exact work commit with `fetch_review`, runs the acceptance checks, writes an attributed verification record through `record.write` and emits `review_verdict`. PM closes with that verdict through existing `task.close`; `request.deliver` requires both closed-task evidence and latest approving review, and confirms the verification record cites the same commit/results and was committed through `record.write` by the reviewing role, proven by the broker action receipt rather than text claiming a reviewer identity.
|
||||
- [ ] **Green:** Export only the committed working-repo blob through bounded safe Git operations, never a workspace path. Append delivery evidence and chief notification intent atomically. Link it to the original thread/session; chief and assistant relay automatically through existing messaging rules. Delivery read remains available even if the assistant is temporarily unavailable, but the outstanding notification stays visible and recoverable. Exactly one delivery ID/message intent per op.
|
||||
- [ ] **Green:** Serve HTML as a download (`Content-Disposition: attachment`, `nosniff`, private/no-store); never execute product HTML inside the privileged Console origin or relax its CSP. The downloaded file runs locally offline. The evidence panel links PRD/snapshot, task, code commit, review and verification records. It labels reviewed delivery separately from landing/deployment.
|
||||
- [ ] **Verification:** Run the three suites; open the downloaded file in the isolated acceptance browser with networking disabled, then confirm its bytes match the reviewed Git blob. Existing `task.close` refuses stale/changes verdicts as before.
|
||||
- [ ] **Commit:** Commit artifact delivery only after green checks.
|
||||
|
||||
## Task 8: Three-path integration, crash recovery and honest acceptance (stage 4)
|
||||
|
||||
**Files:** Create `packages/cli/tests/request-lifecycle.test.mjs`, `packages/cli/tests/fixtures/request-agent.mjs`, `packages/cli/tests/fixtures/pomodoro-request.json`, `packages/webui/tests/request-lifecycle-browser.test.mjs`, `packages/cli/live/request-lifecycle.mjs`. Reuse `packages/tasks/src/fake.mjs`, the file-backed broker runtime, real project Git helpers, launcher/session fixtures and `packages/webui/tests/browser.mjs`. Do not reuse `tasks/tests/world.mjs`'s permissive PM launch grant as shipped authority.
|
||||
|
||||
**Interfaces:** Fixture request file is `{source_event,source_message,text,source_sha256,provenance}`. The integration fixture exposes `start()`, `kill(point)`, `restart()` and `evidence()` over the same on-disk instance and persistent fake service. Scripted role adapters invoke the real typed tools and create real commits; they do not insert successful lifecycle records directly. Live runner takes an explicitly named isolated instance and evidence output directory, validates resources/owner authorization first, and never defaults to .53/.54 or production.
|
||||
|
||||
- [ ] **Red:** `autonomous_original_request_delivers_offline_html`: submit the original request, select/confirm autonomous once, then let role adapters run through PRD approval, real tracker task, code/test/commit, independent role review and export. Assert zero user message relays, shell commands and task creation before snapshot activation.
|
||||
- [ ] **Red:** `guided_answers_and_exact_approval`: answer a short question via Console, reject a draft, revise, approve exact content and deliver. `attach_existing_and_revise_missing_requirement`: attach to an authorized existing product; test both matching approved snapshot and discovery/revision when none fits; create no extra project. Also test cancellation and mode change during approval.
|
||||
- [ ] **Red verification:** Run `node --test packages/cli/tests/request-lifecycle.test.mjs packages/webui/tests/request-lifecycle-browser.test.mjs`.
|
||||
- [ ] **Green:** Build the fixture with actual shipped role definitions and valid isolated organization/tracker credentials; fake only external services and model responses. Use real task field validation, local repositories, git socket/bundles, typed manifests, launcher admission, separate role/run identities and signed-in HTTP/browser actions. The coder fixture writes working HTML, not a README describing how the user should build it.
|
||||
- [ ] **Green:** Crash a separate process after selection resolution, mapping write, spec commit, PRD resolution, tracker POST, working push, review verdict and export-before-notification. Restart the actual broker/runtime against the same Store/repositories/fake-service data. Assert identical IDs/commits, one project/task/artifact, unchanged historical rows and automatic continuation. Include uncertainty where the remote outcome cannot be proven: a visible wait is correct; a duplicate write or success claim is not.
|
||||
- [ ] **Green:** Check proposed product defaults only after their product PRD approval: 25-minute work, 5-minute break, start/pause/reset, phase-end cue, no network/external assets. Browser tests control time to verify transitions, pause/resume/reset and cue after a user gesture. Assert downloaded HTML is self-contained and usable offline. Those defaults are agent proposals, not invented prior owner requirements.
|
||||
- [ ] **Verification:** Run `node --test packages/bus/tests/*.test.mjs packages/tasks/tests/*.test.mjs packages/project/tests/*.test.mjs packages/business/tests/*.test.mjs packages/cli/tests/*.test.mjs packages/harness/tests/*.test.mjs packages/seat/tests/*.test.mjs packages/webui/tests/*.test.mjs` in the repository's supported Node/browser environment. Record failures, skips and environment limitations explicitly; isolate a flaky/preexisting failure before claiming an unaffected suite green. Document/reference/whitespace checks also run before each final integration commit.
|
||||
- [ ] **Verification:** Run the separate live runner only in a later explicitly authorized isolated configured instance with actual model credentials/role routes. It must use the same production code and real independent role sessions. Retain request, activation, task, commit, test, review and artifact receipts. Fixture success demonstrates integration/recovery, not live model quality or deployment readiness. No production setup or external resource creation is authorized by this planning assignment.
|
||||
- [ ] **Commit:** Commit the acceptance harness and evidence references after applicable checks. Report fixture and live results separately; if live prerequisites are absent, report the exact remaining setup gate instead of marking stage 4 fully accepted.
|
||||
|
||||
## Protected setup, policy deltas and handoff
|
||||
|
||||
No `.json` role expansion is necessary for the selected first route: PM already writes records/tasks; CTO resolves technical decisions; coder pushes local working refs; reviewer issues verdicts; chief launches; assistant relays. The unavoidable implementation boundary is a new user-gated `project.bootstrap` action plus its narrow executor and protected project-map writer. The PRD addendum explicitly states that routing and scope. Other new verbs are bounded implementations of existing record/message/task/PRD authority or authenticated owner controls, not new permission grants. Reviewed duty-contract edits and corresponding schema/tool tests are still necessary.
|
||||
|
||||
Missing model account/route, PM/CTO/reviewer role, tracker sync credential or installed board is a real foundation setup refusal. The supported route reuses those declared resources; it must not create new service accounts by pretending a project-mode answer granted `account.create` or `credential.mint`. Show `{service,instance,missing_scope_or_resource,decision,can_execute,resume_condition}` without secrets. For existing Gitea grant needs, use the chief's established `credential.mint` request and concrete Console confirmation; existing bounded grant scope may apply only where already configured. For missing Vikunja token issuance, existing `credentials.issue` accepts a user-provided token through the protected credentials control; it is **not** an automatic project/token provisioner. If no installed board exists, state `tracker-install` and that the current executor cannot provision it. That is a protected foundation setup blocker, not delivery completion. Do not ask the user to edit files, forward role messages or run decision commands as the normal lifecycle.
|
||||
|
||||
Implement in Task order except that Task 3 may follow Task 4 while waiting for Stage 1 integration. Tasks 4/5 share the catalog contract; integrate together before enabling product task creation. Keep the feature unavailable until bootstrap admission, scoped validation and typed continuations all exist; no prompt-only partial release. The shortest end-to-end milestone is one product, one scoped task, one code commit/review and one downloaded HTML artifact. Multiple products share the same machinery; reusable mandates, automatic external project provisioning and broader artifact types are deferred.
|
||||
|
||||
The checked-in design names the original pomodoro request but does not preserve its verbatim text/source event. The lead must supply a read-only export of that source for the final acceptance fixture; do not relabel a reconstructed prompt as the original. Fixture development can use an explicitly labeled representative request meanwhile. No other builder choice requires a fresh owner decision: source project and board are selected from actual configured resources in the displayed initial plan. Exact PRD amendment adoption remains a separate versioned approval record; this document is not that record.
|
||||
Reference in new issue
Block a user