diff --git a/Makefile b/Makefile index cd7630024..df8746230 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ LDFLAGS = -X $(GIT_IMPORT).BuildDate=$(BUILD_DATE) -X $(GIT_IMPORT).GitCommit=$( # GORELEASER_DOCKER_IMAGE = ghcr.io/goreleaser/goreleaser-cross:v1.25.7 GORELEASER_DOCKER_IMAGE = ghcr.io/goreleaser/goreleaser:latest -.PHONY: test test-race test-coverage harness inner-loop cli-wayfinding docs-wayfinding install-smoke provider-conformance-mock provider-conformance lint fmt install-tools proto clean help gorelease-dry-run gorelease-dry-run-docker +.PHONY: test test-race test-coverage harness zero-to-hero-transcript inner-loop cli-wayfinding docs-wayfinding install-smoke provider-conformance-mock provider-conformance lint fmt install-tools proto clean help gorelease-dry-run gorelease-dry-run-docker # Default target help: @@ -19,6 +19,7 @@ help: @echo " make test-coverage - Run tests with coverage" @echo " make lint - Run linter" @echo " make harness - Run deterministic getting-started and end-to-end harnesses" + @echo " make zero-to-hero-transcript - Verify the ordered 0→hero lifecycle transcript" @echo " make inner-loop - Verify scaffold → run/chat/inspect → deploy dry-run contract" @echo " make cli-wayfinding - Verify installed first-agent CLI wayfinding commands" @echo " make docs-wayfinding - Verify first-agent docs/CLI wayfinding stays in sync" @@ -54,10 +55,16 @@ test-coverage: harness: $(MAKE) cli-wayfinding $(MAKE) inner-loop - ./internal/harness/zero-to-hero-ci/run.sh + $(MAKE) zero-to-hero-transcript go run ./internal/harness/agent-flow $(MAKE) provider-conformance-mock +# Verify the maintained 0→hero transcript in the same order documented for new +# developers: scaffold → run/chat/inspect → support-agent chat → flow history → +# deploy dry-run. This is the focused CI contract for the full lifecycle path. +zero-to-hero-transcript: + ./internal/harness/zero-to-hero-ci/run.sh + # Focused provider-free CLI inner-loop contract: scaffold a service, keep the # run/chat/inspect commands discoverable, and prove deploy dry-run reaches the # documented boundary without remote side effects. Use this when README/docs/CLI diff --git a/README.md b/README.md index 7b128431f..ee0bc14c1 100644 --- a/README.md +++ b/README.md @@ -84,8 +84,13 @@ To verify the focused CLI inner-loop contract — scaffold → run/chat/inspect make inner-loop ``` -To run the broader local contract (including the [0→hero services → agents → workflows path](internal/website/docs/guides/zero-to-hero.md), -chat/inspect CLI boundaries, and deploy dry-run), use: +To run only the ordered [0→hero services → agents → workflows transcript](internal/website/docs/guides/zero-to-hero.md) that CI guards, use: + +```bash +make zero-to-hero-transcript +``` + +To run the broader local contract (including that transcript, chat/inspect CLI boundaries, and deploy dry-run), use: ```bash make harness diff --git a/internal/harness/zero-to-hero-ci/docs_test.go b/internal/harness/zero-to-hero-ci/docs_test.go index 4ed58cf4b..6105d2dc2 100644 --- a/internal/harness/zero-to-hero-ci/docs_test.go +++ b/internal/harness/zero-to-hero-ci/docs_test.go @@ -21,6 +21,7 @@ func TestZeroToHeroReferenceDocs(t *testing.T) { guide := readFile(t, filepath.Join(root, "internal", "website", "docs", "guides", "zero-to-hero.md")) for _, want := range []string{ "make harness", + "make zero-to-hero-transcript", "make inner-loop", "go test ./cmd/micro/cli/new -run TestZeroToOne -count=1", "go test ./cmd/micro -run TestFirstAgentWalkthroughCLIBoundaries -count=1", @@ -70,6 +71,9 @@ func TestZeroToHeroReferenceDocs(t *testing.T) { if !strings.Contains(readme, "internal/website/docs/guides/zero-to-hero.md") { t.Fatal("README does not point to the canonical 0→hero guide") } + if !strings.Contains(readme, "make zero-to-hero-transcript") { + t.Fatal("README does not expose the focused ordered 0→hero transcript contract") + } if !strings.Contains(readme, "make inner-loop") { t.Fatal("README does not expose the focused CLI inner-loop contract") } @@ -80,6 +84,33 @@ func TestZeroToHeroReferenceDocs(t *testing.T) { } } +func TestZeroToHeroTranscriptTargetStaysOrdered(t *testing.T) { + root := filepath.Clean(filepath.Join("..", "..", "..")) + makefile := readFile(t, filepath.Join(root, "Makefile")) + if !strings.Contains(makefile, "zero-to-hero-transcript:") { + t.Fatal("Makefile missing focused zero-to-hero-transcript target") + } + if !strings.Contains(makefile, "./internal/harness/zero-to-hero-ci/run.sh") { + t.Fatal("zero-to-hero-transcript target must run the maintained CI transcript") + } + + runScript := readFile(t, filepath.Join(root, "internal", "harness", "zero-to-hero-ci", "run.sh")) + assertOrderedMarkers(t, "0→hero CI transcript", runScript, []string{ + `run_step "scaffold: 0→1 service contract"`, + `run_step "run/chat/inspect: first-agent CLI boundaries"`, + `run_step "chat/inspect: no-secret first-agent transcript and docs"`, + `run_step "first-agent app: runnable provider-free example"`, + `run_step "0→hero app: support lifecycle smoke"`, + `run_step "flow history: deterministic services → agents → workflows harnesses"`, + `run_step "deploy dry-run: configured target plan"`, + }) + + guide := readFile(t, filepath.Join(root, "internal", "website", "docs", "guides", "zero-to-hero.md")) + if !strings.Contains(guide, "make zero-to-hero-transcript") { + t.Fatal("0→hero guide must point developers at the focused ordered transcript target") + } +} + func TestZeroToHeroDeployDryRunCommandSmoke(t *testing.T) { root := filepath.Clean(filepath.Join("..", "..", "..")) absRoot, err := filepath.Abs(root) diff --git a/internal/harness/zero-to-hero-ci/run.sh b/internal/harness/zero-to-hero-ci/run.sh index ceb66e875..3481799f6 100755 --- a/internal/harness/zero-to-hero-ci/run.sh +++ b/internal/harness/zero-to-hero-ci/run.sh @@ -22,8 +22,6 @@ run_step "scaffold: 0→1 service contract" \ go test ./cmd/micro/cli/new -run TestZeroToOne -count=1 run_step "run/chat/inspect: first-agent CLI boundaries" \ go test ./cmd/micro -run 'TestFirstAgentWalkthroughCLIBoundaries|TestExamplesWayfindingIndexStaysLinked|TestExamplesCommandPointsAtWayfindingIndex|TestZeroToHeroCLIBoundaries|TestZeroToHeroCommandPrintsMaintainedNoSecretPath' -count=1 -run_step "deploy dry-run: configured target plan" \ - go test ./cmd/micro/cli/deploy -run TestDeployDryRun -count=1 run_step "chat/inspect: no-secret first-agent transcript and docs" \ go test ./internal/harness/zero-to-hero-ci -run 'TestNoSecretFirstAgentTranscript|TestFirstAgentCLIChatInspectFixture|TestNoSecretFirstAgentDebuggingSmoke|TestZeroToHeroReferenceDocs|TestZeroToHeroDeployDryRunCommandSmoke|TestYourFirstAgentTutorialSmoke' -count=1 @@ -37,3 +35,5 @@ run_step "0→hero app: support lifecycle smoke" \ go test ./examples/support -run 'TestRunSupportMockSmoke|TestZeroToHeroReadmeDocumentsLifecycle|TestZeroToHeroInspectTranscript' -count=1 run_step "flow history: deterministic services → agents → workflows harnesses" \ go test ./internal/harness/universe ./internal/harness/plan-delegate -run 'Test.*Harness|TestPlanDelegateEndToEnd|TestPlanDelegateFlowHandoff' -count=1 +run_step "deploy dry-run: configured target plan" \ + go test ./cmd/micro/cli/deploy -run TestDeployDryRun -count=1 diff --git a/internal/website/docs/guides/zero-to-hero.md b/internal/website/docs/guides/zero-to-hero.md index 501080147..bb9999805 100644 --- a/internal/website/docs/guides/zero-to-hero.md +++ b/internal/website/docs/guides/zero-to-hero.md @@ -26,6 +26,7 @@ cloud credentials?" | Deploy | `micro deploy --dry-run prod` resolves the documented deploy target without touching remote infrastructure. | `go test ./internal/harness/zero-to-hero-ci -run TestZeroToHeroDeployDryRunCommandSmoke -count=1` | | Smallest first agent | `examples/first-agent` runs one service-backed agent with a deterministic mock model and no provider key. | `go test ./examples/first-agent -run TestRunFirstAgent -count=1` | | Runtime reference app | `examples/support` runs typed services, an agent using those services as tools, an event-driven flow handoff, and an approval gate with only the model mocked. | `go test ./examples/support -run 'TestRunSupportMockSmoke|TestZeroToHeroReadmeDocumentsLifecycle|TestZeroToHeroInspectTranscript' -count=1` | +| Ordered 0→hero transcript | The maintained CI transcript walks scaffold → run/chat/inspect → support-agent chat → flow history → deploy dry-run without provider keys. | `make zero-to-hero-transcript` | | Runtime harnesses | Real services, agents, durable flows, store-backed history, delegation, and A2A run with only the model mocked. | `./internal/harness/zero-to-hero-ci/run.sh` and `make provider-conformance-mock` | ## Find the one-command entrypoint @@ -62,6 +63,12 @@ From the repository root: make harness ``` +For the focused ordered transcript only, run: + +```sh +make zero-to-hero-transcript +``` + That target runs the scaffold contract, the CLI boundary smoke tests, the 0→hero runtime harnesses, the event-driven agent-flow harness, and mock provider conformance. It is intentionally deterministic: no provider key, cloud account,