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, inspection, task browsing/claim/start, governing context, project creation/declaration and original upload delivered through WS-CLI-001-10; PILOT-13 assigned-guide listing/download is delivered; setup inspection/approval/activation, further public journeys and binary distribution remain; hidden submission is not exposed |
| [WS-CLI-001](initiatives/WS-CLI-001/OVERVIEW.md) | Planned | Public Go CLI self-service, inspection, task browsing/claim/start, governing context, project creation/declaration, original upload and setup diagnostic inspection delivered through WS-CLI-001-11; PILOT-13 assigned-guide listing/download is delivered; approval/activation, further public journeys and binary distribution remain; hidden submission is not exposed |
| [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; 04E1B-B3 retains inspected ZIP metadata and B4 binds Submission text to checked packet custody and B5 validates bounded evaluation content before durable admission; B6 commits initial Submission/dispatch and exact replay; B7 adds hidden request delivery; completion routing is next under the [first-layer sequence](initiatives/WS-ARCH-001/planning/PLAN.md#first-complete-contributor-milestone), ending in a public contributor drill before live human review/revision. 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 @@ -15,6 +15,7 @@
[WS-CLI-001-08](WS-CLI-001-08.md), draft project shell creation with explicit caller-owned replay;
[WS-CLI-001-09](WS-CLI-001-09.md), guide declaration, illustrative tasks and document upload selectors;
[WS-CLI-001-10](WS-CLI-001-10.md), declared-original upload with hash/size-bound storage receipts;
[WS-CLI-001-11](WS-CLI-001-11.md), latest exact-guide setup diagnostics and compilation lineage;
[PILOT-13](../../changes/pilot13-assigned-task-guide-documents.md), assigned-task locked-guide listing/download.

## Current boundary
Expand Down Expand Up @@ -53,6 +54,9 @@ before success. Its exact-byte receipt establishes storage only, not setup readi
approval or activation; unconfirmed outcomes require deliberate unchanged-input
replay. `task guide TASK_ID [--download DIR]` lists or downloads the assigned
task's locked originals with verified byte identity; setup examples stay private.
`project guide setup PROJECT_ID GUIDE_ID` reads the latest exact-guide setup
and compilation lineage through one public GET. It does not poll, execute setup,
approve policies or activate the guide; successful reading is not readiness.
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 @@ -111,12 +115,15 @@ CLIs. Keep the package independent of backend and MCP runtime dependencies.
Setup awaits actual original upload.
10. **WS-CLI-001-10:** Upload one declared PDF/DOCX/PPTX original through public
binary POST; validate storage receipt against local bytes and preserve manual
replay custody. Setup inspection, approval and activation remain.
11. **Later governed-work commands:** Add further project setup, submission,
replay custody. Approval and activation remain.
11. **WS-CLI-001-11:** Inspect latest exact-guide setup and compilation lineage
through the public diagnostic read. No polling, local readiness rules,
execution, approval or activation.
12. **Later governed-work commands:** Add further 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.
12. **Optional TUI:** Add a focused public queue/evidence view after its API
13. **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
88 changes: 88 additions & 0 deletions .commitrail/initiatives/WS-CLI-001/WS-CLI-001-11.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# WS-CLI-001-11 — Inspect the latest guide setup

- Initiative: `WS-CLI-001`
- Durable disposition: `Complete`
- Intended merge outcome: Inspect one guide's latest server-owned setup and compilation lineage through its existing public read.

## Intent

Guide declaration returns an initial receipt and original upload establishes
storage, neither current setup readiness. Add `workstream project guide setup
PROJECT_ID GUIDE_ID`, calling only public `GET
/api/v1/projects/{project_id}/guides/{guide_id}/setup-runs/latest` once, without
preflight, polling, local readiness rules, or follow-up reads. Return the exact
validated API object for JSON and safely escaped complete fields for text.
An inspected blocked, pending, or failed setup is a successful read, not a
successful compilation, approved policy, or activated guide.

Reuse the hardened JSON client, UUID-identity comparison, closed response
decoder and complete escaped-object renderer. Validate required versus
nullable fields against `ProjectSetupRunResponse`; the three nullable lineage
UUIDs with default null may be omitted. Bind project/guide identity, validate
record UUIDs and timestamps, and retain nullable diagnostics. Setup generation
is a backend integer, so preserve its range without an int64 ceiling. Status,
step, Celery selector and diagnostic strings are backend-owned strings, not
new client enums or decisions. Reject unknown/duplicate fields, required nulls,
malformed identities/times and substituted project/guide identities with empty
stdout. No new transport, schema owner, dependencies or credential mechanism.

## Bounded change

Allowed: new `cli/internal/api/guide_setup.go`, command registration in
`cli/internal/command/guide_create.go`, new
`cli/tests/integration/test_guide_setup_http.py`, the existing real bootstrap
journey in `cli/tests/integration/guide_create_journey.py`, CLI/root README,
affected roadmap claims, this record, initiative overview and index.

Prohibited: backend/MCP/workflow/dependency changes, hidden routes, setup
execution/retry, report/proposal fetching, approval/activation, local policy or
authorization decisions, file storage, additional broad test fixtures and TUI.
The existing setup diagnostic authority owns exact project/guide membership
and fresh actor/grant checks; no cached authorization or management inference.

## Acceptance criteria

- Built-process HTTP proof captures the unchanged escaped UUID selectors and
bearer, one GET per invocation, no body/key or follow-up. Supported alternate
UUID spellings compare by identity. JSON retains the exact response; text
escapes diagnostic controls and includes nullable lineage without claiming
readiness. Pending, provider-uncertain, failed and finalized projections remain
observations. Omitted default-null lineage UUIDs and integers beyond int64
work; malformed/substituted/null/duplicate/unknown replies do not.
- Exercise bounded replies, canonical denial, reflected credential error
metadata and redirects using existing process fixtures. Existing shared
transport tests retain timeout/proxy/HTTP2 custody; no duplicate transport suite.
- Extend the existing real Flow-token/bootstrap/PostgreSQL public journey:
verify the read is in OpenAPI; compare CLI and direct API setup objects after
declaration; exact scoped manager succeeds, outsider/foreign project fail,
and revocation/suspension after a valid control deny the same setup read.
This proves current diagnostic reads, not live provider execution.
- Run all CLI process/API tests through `run_isolated_tests.py` and confirm
database cleanup, Go build/vet/module verification/tidy-diff, Ruff/format,
links/stale-wording/Commitrail, and full required hosted Backend. No test
removal, skips, coverage quotas or CI weakening.
- Mutate the response identity guard in an out-of-tree copy and demonstrate
the named substitution test fails at the intended assertion.

## Evidence

```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 .venv/bin/python scripts/run_isolated_tests.py --metadata-json /tmp/workstream-cli-isolation.json --timeout-seconds 900 -- .venv/bin/python -m pytest -q ../cli/tests/integration
```

## Risk and review routing

L1, bounded protected public diagnostic response; no invented urgency or human
decision beyond approval of this PR. Focused plan feasibility review first.
After shared proof and a clean candidate, route architecture/documentation/reuse,
security and QA/test-delta in three bounded assignments, not all nine reviewers.
Human focus: this command observes latest setup, not stored creation state;
statuses and lineage do not establish approval, activation or permission for
another operation. Runtime deployment and binary distribution remain separate.
Roadmap impact is the CLI's newly usable read, not backend lifecycle completion.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,9 @@ upload documents or approve the guide; returned setup waits for those documents.
--media-type MIME --idempotency-key UUID` uploads a declared original. The CLI
streams its bytes and validates the storage receipt against their hash and size.
An upload receipt is not setup completion, policy approval or guide activation.
`workstream project guide setup PROJECT_ID GUIDE_ID` reads the latest public
setup status and compilation lineage. A successful diagnostic read is not
approval or activation; there is no polling or setup execution in the CLI.
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
23 changes: 23 additions & 0 deletions cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ context/intake requirements:
| `workstream project create --name TEXT --slug TEXT --idempotency-key UUID` | `POST /api/v1/projects` |
| `workstream project guide create PROJECT_ID --input FILE --idempotency-key UUID` | `POST /api/v1/projects/PROJECT_ID/guides` |
| `workstream project guide upload PROJECT_ID GUIDE_ID DOCUMENT_ID --file FILE --media-type MIME --idempotency-key UUID` | `POST /api/v1/projects/PROJECT_ID/guides/GUIDE_ID/documents/DOCUMENT_ID/content` |
| `workstream project guide setup PROJECT_ID GUIDE_ID` | `GET /api/v1/projects/PROJECT_ID/guides/GUIDE_ID/setup-runs/latest` |
| `workstream project tasks PROJECT_ID` | `GET /api/v1/projects/PROJECT_ID/tasks` |
| `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` |
Expand Down Expand Up @@ -188,6 +189,28 @@ unknown outcomes. An otherwise valid unconfirmed-storage status also exits 1,
sets `outcome_unknown` and leaves stdout empty rather than reporting success.
Diagnostics never include file paths, contents or raw provider/transport errors.

## Inspect current guide setup

```sh
workstream project guide setup PROJECT_ID GUIDE_ID --output json
```

This reads the latest setup for that exact guide, rather than replaying its
initial creation receipt. The API owns current scoped diagnostic authority,
actor lifecycle, project/guide membership and compilation lineage. The CLI
makes one public GET with the caller's bearer; no polling, role preflight,
follow-up calls, setup execution or retry is added.

JSON output preserves the complete validated API object. Text renders all
fields with terminal escaping, including nullable diagnostic and compilation
selectors. UUID identities and timestamps are checked; the generation integer
retains the backend response range. A pending, blocked, failed or finalized
setup can be read successfully (exit 0); this is not a successful compilation,
policy approval, guide activation or authority for another operation.
Denials, malformed/substituted replies, oversized JSON and network failures
leave stdout empty and exit 1. The normal 12-second/64KiB JSON bounds apply.
Approval and activation commands remain separate future work.

## Create a draft project shell

```sh
Expand Down
83 changes: 83 additions & 0 deletions cli/internal/api/guide_setup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package api

import (
"context"
"errors"
"math/big"
"net/http"
"net/url"
)

// GuideSetup is a current diagnostic projection, not an approval or activation.
type GuideSetup struct {
ID string `json:"id"`
ProjectID string `json:"project_id"`
GuideID string `json:"guide_id"`
GuideVersion string `json:"guide_version"`
SourceSnapshotID string `json:"source_snapshot_id"`
SetupGeneration *big.Int `json:"setup_generation"`
FinalizedCompilationID *string `json:"finalized_compilation_id"`
CorrectionOperationID *string `json:"correction_operation_id"`
PredecessorCompilationID *string `json:"predecessor_compilation_id"`
CeleryTaskID *string `json:"celery_task_id"`
DocumentsReadyAt *string `json:"documents_ready_at"`
Status string `json:"status"`
CurrentStep string `json:"current_step"`
OutputSufficiencyReportID *string `json:"output_sufficiency_report_id"`
OutputSubmissionArtifactPolicyID *string `json:"output_submission_artifact_policy_id"`
ErrorCode *string `json:"error_code"`
ErrorArtifactIncidentID *string `json:"error_artifact_incident_id"`
ErrorSummary *string `json:"error_summary"`
CreatedBy string `json:"created_by"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
StartedAt *string `json:"started_at"`
FinishedAt *string `json:"finished_at"`
}

func (c *Client) GuideSetup(ctx context.Context, project, guide string) (Result[GuideSetup], error) {
var result Result[GuideSetup]
if !validUUID(project) || len(project) > 100 || !validUUID(guide) || len(guide) > 100 {
return result, errors.New("PROJECT_ID and GUIDE_ID must be UUIDs")
}
raw, err := c.request(ctx, http.MethodGet,
"/api/v1/projects/"+url.PathEscape(project)+"/guides/"+url.PathEscape(guide)+"/setup-runs/latest", "", nil)
if err != nil {
return result, err
}
var value GuideSetup
fields, err := contextObject(raw, &value, []string{
"id", "project_id", "guide_id", "guide_version", "source_snapshot_id", "setup_generation",
"status", "current_step", "created_by", "created_at", "updated_at",
}, nil)
if err != nil || !sameUUID(value.ProjectID, project) || !sameUUID(value.GuideID, guide) ||
!validUUID(value.ID) || !validUUID(value.SourceSnapshotID) || !validUUID(value.CreatedBy) ||
!validTime(value.CreatedAt) || !validTime(value.UpdatedAt) {
return result, &Failure{Code: "invalid_api_response"}
}
// These public nullable fields are required; only the three lineage UUIDs
// default to null when omitted. Do not infer a state machine from diagnostics.
for _, name := range []string{
"celery_task_id", "documents_ready_at", "output_sufficiency_report_id",
"output_submission_artifact_policy_id", "error_code", "error_artifact_incident_id",
"error_summary", "started_at", "finished_at",
} {
if _, present := fields[name]; !present {
return result, &Failure{Code: "invalid_api_response"}
}
}
for _, identity := range []*string{
value.FinalizedCompilationID, value.CorrectionOperationID, value.PredecessorCompilationID,
value.OutputSufficiencyReportID, value.OutputSubmissionArtifactPolicyID, value.ErrorArtifactIncidentID,
} {
if identity != nil && !validUUID(*identity) {
return result, &Failure{Code: "invalid_api_response"}
}
}
for _, timestamp := range []*string{value.DocumentsReadyAt, value.StartedAt, value.FinishedAt} {
if timestamp != nil && !validTime(*timestamp) {
return result, &Failure{Code: "invalid_api_response"}
}
}
return Result[GuideSetup]{Raw: raw, Value: value}, nil
}
17 changes: 17 additions & 0 deletions cli/internal/command/guide_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,23 @@ func addGuideCreate(project *cobra.Command, client func() (*api.Client, error),
create.Flags().StringVar(&key, "idempotency-key", "", "Required caller-owned UUID; retain with unchanged input for manual replay")
guide.AddCommand(create)
addGuideUpload(guide, client, output, stdout)
guide.AddCommand(&cobra.Command{
Use: "setup PROJECT_ID GUIDE_ID", Short: "Inspect latest guide setup (does not approve or activate)", Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
apiClient, err := client()
if err != nil {
return err
}
result, err := apiClient.GuideSetup(cmd.Context(), args[0], args[1])
if err != nil {
return err
}
if *output == "json" {
return writeJSON(stdout, result.Raw)
}
return writeTaskContextFields(stdout, []contextField{{"Latest setup (not approval or activation)", result.Value}})
},
})
project.AddCommand(guide)
}

Expand Down
Loading
Loading