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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .commitrail/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ for current product capability.
|---|---|---|
| [WS-DB-002](initiatives/WS-DB-002/OVERVIEW.md) | Complete | Shared UUIDv7 record generation, native-UUID relationships and fresh v0.1 baseline; natural-owner retry custody and aligned CI/local setup |
| [WS-MCP-002](initiatives/WS-MCP-002/OVERVIEW.md) | Planned | Nine tools through WS-MCP-002-03: self-service and administrative reads; 18 tools remain and WS-MCP-002-04 administrative grant mutations are next |
| [WS-CLI-001](initiatives/WS-CLI-001/OVERVIEW.md) | Planned | Public Go CLI self-service, project inspection, manager browsing and contributor discovery delivered through WS-CLI-001-05; further public journeys and binary distribution remain |
| [WS-CLI-001](initiatives/WS-CLI-001/OVERVIEW.md) | Planned | Public Go CLI self-service, project inspection, manager browsing, contributor discovery and claim/start delivered through WS-CLI-001-06; further public journeys and binary distribution remain |
| [WS-ARCH-001](initiatives/WS-ARCH-001/OVERVIEW.md) | Planned | Source storage, inert AUTH contracts, TASK request reservation, hidden exact AUTH preparation and the REV-04C hidden FinalAcceptance/TASK/CON participant are delivered; TASK-before-CHECKERS reservation/current-read custody and ordered admission INSERTs are delivered by 04E1B-B1; 04E1B-B2 adds exact source preparation without publication; remaining hidden routing handlers are next. True admission remains independent of shared acceptance; false activation still requires exact AUTH receipt custody, database complete-set enforcement, currentness race proof and atomic routing activation. |
| [WS-ART-001](initiatives/WS-ART-001/OVERVIEW.md) | Planned | Exact checker input/output custody and packet foundations are delivered; routing integration, remediation and public intake remain. |
| [WS-AUTH-001](initiatives/WS-AUTH-001/OVERVIEW.md) | Planned | AUTH-19A commitments, TASK request reservation, ARCH-04E2-A hidden strict PREP matching and the REV-04C hidden FinalAcceptance/TASK/CON participant are delivered; the action remains unavailable, with mandatory exact AUTH receipt input, database closure, audit/outbox and scoped activation still required for the automated path. |
Expand Down
13 changes: 10 additions & 3 deletions .commitrail/initiatives/WS-CLI-001/OVERVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
self-profile editing through the public REST API; [WS-CLI-001-03](WS-CLI-001-03.md),
exact-project inspection with server-owned full/minimal disclosure;
[WS-CLI-001-04](WS-CLI-001-04.md), public manager task pagination and detail;
[WS-CLI-001-05](WS-CLI-001-05.md), contributor ready-task discovery and instructions.
[WS-CLI-001-05](WS-CLI-001-05.md), contributor ready-task discovery and instructions;
[WS-CLI-001-06](WS-CLI-001-06.md), public contributor claim/start with explicit retry keys.

## Current boundary

Expand All @@ -27,6 +28,9 @@ reads only the existing public project's server-selected disclosure shape.
manager queue/detail journey with server-owned authority on each page.
`task ready PROJECT_ID` and `task show TASK_ID` add the contributor projection
with exact Submitter authority and server-owned assignment visibility.
`task claim TASK_ID --idempotency-key UUID` and `task start` add the public
contributor writes, with server-owned fresh authority, assignment and lineage.
Exact caller keys support manual replay; uncertainty never triggers automatic retries.
All have text/JSON
output and built-binary integration proof. Mutations preserve omitted/null
semantics and explicitly report uncertain outcomes without automatic retries.
Expand Down Expand Up @@ -71,11 +75,14 @@ CLIs. Keep the package independent of backend and MCP runtime dependencies.
detail, passing opaque continuation unchanged without automatic pagination.
5. **WS-CLI-001-05:** Discover one ready-task page and inspect contributor
instructions through public reads, without management metadata or task writes.
6. **Later governed-work commands:** Add project setup, contributor task mutations, submission,
6. **WS-CLI-001-06:** Claim ready work and start the caller's assignment through
public POSTs with caller-supplied keys, exact response validation and explicit
uncertain outcomes. No local authority decisions or operator override.
7. **Later governed-work commands:** Add project setup, submission,
review, revision, and contribution reads/writes only as their actual public
contracts and authority boundaries become available. Split by user journey,
not one PR per endpoint or one giant catalogue PR.
7. **Optional TUI:** Add a focused public queue/evidence view after its API
8. **Optional TUI:** Add a focused public queue/evidence view after its API
workflow is complete. Never require a TUI for agents or scripts.

## Risks and proof
Expand Down
139 changes: 139 additions & 0 deletions .commitrail/initiatives/WS-CLI-001/WS-CLI-001-06.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# WS-CLI-001-06 — Claim and start contributor work

- Initiative: `WS-CLI-001`
- Durable disposition: `Complete`
- Intended merge outcome: Claim a ready task and start the caller's assignment
through the existing public REST operations.

## Intent

Contributor discovery is delivered. It does not reserve work. Add the next
bounded journey without implementing authority or lifecycle in the CLI.
`tasks/router.py` exposes claim and start with a required UUID `Idempotency-Key`
and optional reason of at most 1000 characters. `AuthorizedTaskCommands` owns
fresh AUTH, assignment, locked policy lineage, transaction and transition audit.
`TaskCommandReplay` scopes receipts by actor/action/key and verifies task/reason,
current authority and state. A receipt is not permission and replay may fail
after state changes; neither CLI retries nor local success caching are justified.

## Bounded change

Allowed: cohesive `cli/internal/` client/command code, process/API integration
tests, CLI/root README, affected roadmap claims, this record, overview and index.
Prohibited: backend/product, MCP, workflows, dependencies, operator overrides,
hidden APIs, credential persistence, local role/policy decisions, preflight,
automatic retries, automatic key generation, TUI or distribution work.

`workstream task claim TASK_ID --idempotency-key UUID [--reason TEXT]` sends one
POST to `/api/v1/tasks/{task_id}/claim`; `task start` sends one POST to the public
start route. Require a caller-supplied key so a lost response does not lose the
retry identity. Validate selectors/key and bounded UTF-8 reason locally, preserve
supported UUID spelling on the wire and compare returned identity by value.
Send `{}` when reason is absent and preserve explicit empty reason. No actor or
project override and no arbitrary endpoint. Reuse the existing safe transport.
Mutation bodies must not be rewindable by the HTTP transport: a caller's
idempotency key does not permit silent HTTP/2 GOAWAY/REFUSED_STREAM replay.
After a sent body loses its response, return an unknown outcome for manual retry.

Validate the exact contributor mutation TaskResponse and claim assignment
envelope, including UUID/timestamp/array/null shapes, requested task identity,
assignment task/project/contribution-policy identity, contributor equal to
assigned-by, active assignment, non-null assigned/accepted times, no released
time, required claimed/in-progress result, and absent management-only fields.
Preserve raw successful JSON;
text prints all returned public fields safely. Do not infer the caller's actor
ID from a JWT or add a whoami request. Workstream owns caller binding.

Transport/send/read failures, redirects, unexpected success statuses,
malformed/oversized success, 5xx and noncanonical/intermediary 4xx produce
`outcome_unknown: true`. Only complete strictly decoded canonical API 4xx
envelopes establish known denial. Extend the shared transport deliberately for
these POST writes; retain the profile payload and error contract while honoring
its existing one-request/no-retry promise. Task-specific text directs
inspection with `task show TASK_ID` and
manual replay of the unchanged action/task/reason/key, not `whoami` or a new
key. Inspection is observational, not proof of rollback or global ordering.
No false rollback, automatic retry,
or guarantee that a later state-dependent replay will succeed.

## Acceptance criteria

- Built-process tests in the new `test_contributor_task_mutations.py` prove both
fixed routes, unchanged bearer/key/body, compact UUID parity, no preflight or
retry, local invalid input without network, complete safe text/raw JSON,
malformed/substituted/management replies, and unknown-outcome handling.
- Extend `contributor_task_journey.py` inside the existing one-bootstrap real
FastAPI/PostgreSQL test. Public create/screen/release and canonical approved
guide prerequisites remain; inference/storage fixtures do not certify S3.
CLI claim/start must be OpenAPI-visible. Preserve every existing read control.
- Prove persisted own claim/start and same-key response parity; changed reason
with the same key conflicts; changed task with that key cannot succeed. Active
same-project peer authority cannot start another assignment. Absent, Reviewer-
only, foreign-project, revoked and suspended authority deny writes/replays.
Positive controls reach each relevant guard; restore authority before testing
suspension. Inspect the task/assignment through public reads to prove denied
attempts do not mutate them. For revoke/suspend first observe canonical
post-administration state through public management reads, then baseline
denied attempts against that state, not the previous claimed/in-progress
state. Invalidation is asynchronous: ready/authority_revoked is its completed
effect, not an immediate API guarantee. This fixture has no background
dispatcher; do not add private processing to simulate that completion.
Claim replay after start need not succeed.
- Run Go verify/tidy/vet/build, Ruff, complete process/API suite via isolated
PostgreSQL, existing workflow guards, links, stale scans and Commitrail checks.
Full hosted suite remains blocking; no test/coverage quota or deadline change.

## Evidence

Verification commands; exact execution and reviewer/hosted results belong in the
PR. Process tests prove wire, output, strict response and uncertainty boundaries.
The real public API journey reuses the existing bootstrap and approved-guide
prerequisites; it does not certify deployed Flow or real guide inference/storage.

```sh
cd cli
go mod verify
go mod tidy -diff
go vet ./...
go build -trimpath -o /tmp/workstream-cli ./cmd/workstream
cd ../backend
WORKSTREAM_CLI_EXECUTABLE=/tmp/workstream-cli python scripts/run_isolated_tests.py --metadata-json /tmp/workstream-cli-isolation.json --timeout-seconds 240 -- python -m pytest -q ../cli/tests/integration
```

## Risk and review routing

Risk `L1`: credential transport, caller-isolated mutation and misleading retry
success. Plan review precedes implementation. Focused tracks: security;
architecture/documentation; QA/test delta in three bounded assignments. The
lead runs unchanged CI guards once. No broad product rewrite or nine-reviewer
fanout. Human focus: explicit retry key, fresh server authority, assignment and
lineage identity, uncertain outcome, source availability versus distribution.
The typed mutation projection and process/real-API proof exceed the default
500-line guideline, but remain one assignment journey and one unchanged public
owner boundary. Splitting claim from start would duplicate setup and obscure
their replay/state relationship.

Reject automatic keys/retries because they obscure lost-response recovery;
reject manager/operator routes or local authorization because they change the
contract. No new human design decision is required. Human approval/merge remain
the final GitHub authority. Submission and further public journeys remain later.

Plan corrections `PLAN-SEC-CLI06-001/002` specify deterministic uncertainty and
exact composite claim identity. `PLAN-FIXTURE-CLI06-001` distinguishes legitimate
administrative assignment invalidation from denied-command effects. The
implementation proof must independently exercise these boundaries.
`TEST-CLI-003` adds exact-1000-rune success with the unchanged POST body and
invalid-UTF-8 POSIX argument rejection with no request, distinguishing both
off-by-one and omitted-validation defects in the existing process cases.

External findings `EXT-CLI06-HTTP2-REPLAY` and `EXT-CLI06-NULL-DETAILS` require
real TLS/HTTP2 process proof that graceful GOAWAY after body receipt sends only
one request, plus an otherwise complete canonical 4xx with null `details` that
must remain an unknown outcome. The former removes transport rewind capability;
the latter strengthens proof of the existing strict envelope guard. Neither
changes public API scope, backend retry authority or workflow settings.
Tracing that same shared transport also reproduced `EXT-CLI06-PATCH-REPLAY`:
the existing profile PATCH body was rewindable too. Apply the one-shot body rule
to both existing mutation methods, with a dedicated profile process regression
using the same real TLS/HTTP2 peer. Preserve profile omission/null and error
classification, and leave read transport behavior unchanged.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,9 @@ the caller's current authority, preserving contributor-minimal disclosure.
provide a paginated manager list-to-detail journey through public reads.
`workstream task ready PROJECT_ID` and `task show TASK_ID` provide contributor
discovery and instructions, with live Submitter authority and no task claim.
`workstream task claim TASK_ID --idempotency-key UUID` and `task start` add
contributor writes through existing public APIs, with server-owned authority,
explicit caller retry keys and uncertain-outcome reporting without automatic retries.
All support human-readable and JSON output, using the caller's Flow token.
The first source package is buildable; further workflow commands and published
binaries remain planned.
Expand Down
51 changes: 49 additions & 2 deletions cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
An independent Go client for Workstream's public REST API, for humans and
agents using the terminal. It provides human self-profile reads and editing,
plus exact-project inspection, authority reads, manager task browsing and
contributor work discovery:
contributor work discovery, claim and start:

| Command | Public API |
|---|---|
Expand All @@ -15,6 +15,8 @@ contributor work discovery:
| `workstream project task PROJECT_ID TASK_ID` | `GET /api/v1/projects/PROJECT_ID/tasks/TASK_ID` |
| `workstream task ready PROJECT_ID` | `GET /api/v1/projects/PROJECT_ID/tasks/ready` |
| `workstream task show TASK_ID` | `GET /api/v1/tasks/TASK_ID` |
| `workstream task claim TASK_ID --idempotency-key UUID` | `POST /api/v1/tasks/TASK_ID/claim` |
| `workstream task start TASK_ID --idempotency-key UUID` | `POST /api/v1/tasks/TASK_ID/start` |

Workstream verifies the caller's Flow bearer and owns identity resolution,
authorization and lifecycle decisions. Reading a profile can admit a first-time
Expand Down Expand Up @@ -151,9 +153,47 @@ than silently displayed or ignored.
Discovery is live, not a reservation or a claimability guarantee. A later claim
must revalidate current authority and state. Cursors are action/project/limit
bound and cannot be reused as manager cursors; the CLI never decodes them or
automatically fetches another page. These commands do not claim/start tasks,
automatically fetches another page. These reads do not claim/start tasks,
upload submissions or complete unfinished acceptance integration.

## Claim and start contributor work

```sh
workstream task claim TASK_ID --idempotency-key CLAIM_UUID --reason 'Begin this work' --output json
workstream task start TASK_ID --idempotency-key START_UUID --output json
```

Supply your own UUID key and retain it with the action, task and optional reason.
These commands send exactly one public POST, with no preflight, automatic key,
retry or operator override. Reason is optional (at most 1000 UTF-8 characters);
an omitted flag sends `{}`, while an explicit empty flag sends an empty string.
The caller's Flow bearer and key are forwarded unchanged. Only Workstream
decides whether current identity, lifecycle, exact Submitter grant, task state,
assignment ownership and locked policy permit the write.

Claim returns the contributor-safe task and its assignment; start returns the
contributor-safe task in progress. The CLI validates the requested task identity,
assignment/task/project/policy consistency, claim contributor/assigner identity,
active/unreleased assignment and required timestamps before output. It rejects
management-only fields. JSON preserves the API object; text prints every public
field with escaped terminal controls. This does not expose submission or review
commands, or activate unfinished product lifecycle work.

The API scopes keys by actor and action, and checks current authority before
recovering a committed result. An exact retry can recover the same result only
while the required state remains current. Changed reason/task conflicts;
claim replay after start can be denied. A key never grants permission. Revocation
and suspension deny further writes/replays; assignment invalidation is a separate
asynchronous consequence, not a CLI effect or immediate API guarantee.

If the response is lost, malformed, oversized, redirected, an unexpected success
status, a server error or a noncanonical/intermediary denial, the CLI exits
nonzero with `error.outcome_unknown: true`. Only a complete strictly decoded
canonical Workstream 4xx error envelope establishes a known denial. Inspect with
`workstream task show TASK_ID`; this observes current state, not rollback or
global ordering. If manually retrying, preserve the unchanged action, task,
reason and key. Do not invent a new key or assume recovery will still succeed.

## Edit your profile

```sh
Expand Down Expand Up @@ -213,6 +253,13 @@ same-project non-owner concealment, independent authorized cursor substitution,
exact Submitter grants, Reviewer-only/foreign/revoked denial and suspension after
restored positive authority. The process fixture verifies the separate contributor
shapes, complete field output and refusal of management-only data.
Contributor mutation proof extends the same API/bootstrap journey with CLI
claim/start, persisted assignment and locked lineage, exact replay parity,
reason/task mismatch, same-project non-owner denial, foreign/Reviewer-only
authority, revocation and suspension. Denied writes are compared with the
publicly observed post-administration task baseline, not an assumed pre-revoke
state. Process tests prove the exact POST/key/body, strict claim/start response
identity, safe text, canonical errors and uncertain/no-retry behavior.
Local Flow-compatible tokens are test fixtures, not deployed-provider proof.
No coverage percentage or test-count target is used.

Expand Down
Loading
Loading