Feat/oss port flow#5
Open
fxck wants to merge 11 commits into
Open
Conversation
…e slot
Autonomous OSS "port" workflow, phase 0 (zero-deploy classification only):
- workflow/port_recon.go: ReconClassify(target descriptor, schema) -> PortPlan —
acquisition strategy (source-build/prebuilt-binary/crane-image-lift/bail),
dep->managed-catalog mapping, feasibility band. Image-only is IN-band via
crane-lift; only K8s-runtime-orchestration bails.
- workflow/port_session.go: PortSession sidecar (.zcp/state/port/{pid}.json),
mirrors work_session.go conventions, wraps WorkSession.
- PhasePortActive wired into build_plan.go empty-Plan fall-through (peer to
export/launch-production); tools/workflow_port.go handlePortStart serves
zerops_workflow workflow=port action=start.
TDD: table tests for recon decision tree (image->crane, k8s->bail, dep mapping
incl. clickhouse/kafka managed, band roll-up) + PortSession round-trip + handler.
go build ./... + go test ./internal/workflow ./internal/tools + make lint-local green.
Plan: plans/oss-recipe-port-flow-2026-06-09.md §8 Phase 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ecovery
Agent-driven port loop (handler derives, agent applies, handler records):
- workflow/port_fixclass.go: pure DeriveFixClass(FailureClass, signals) -> guidance.
build+command-not-found→prepareCommands; build+oom-killed→ESCALATE (not a fix —
build resources aren't import-tunable); start+db-refused→wire ${dep_*};
missing-env→EnvSet; migration→run.initCommands + zsc execOnce --retryUntilSuccessful;
config→glue zerops.yaml; credential→git-push-setup; network→retry. Prefers
glue-yaml over import edits; flags the import-override tax (ErrDiagnosisRequired
from iter 2 + state wipe) when an existing-hostname import edit is unavoidable.
- workflow/port_status_recovery.go: BuildPortActiveRecovery — PhasePortActive has an
empty Plan (peer to launch-production), so it gets its own recovery envelope (OQ-5).
- tools/workflow_port_iterate.go: handlePortIterate (reads FailureClassification
FIRST, derives fix-class, records attempt) + handlePortStatus; routed via
routePortAction (single pre-switch dispatcher, keeps handleWorkflowAction under
the maintidx/cyclo lint thresholds).
Low blast radius: failure signals persist on the port-owned PortSession.Attempts
(new PortAttempt type + RecordPortAttempt); shared work_session.go DeployAttempt is
UNTOUCHED (its tests stay green). Phase 2 reads Attempts for stall detection.
TDD: fix-class table, iterate round-trip, status recovery, work-session-untouched
guard. go build + go test ./internal/{workflow,tools} + TestArchitectureLayering +
make lint-local all green.
Plan: plans/oss-recipe-port-flow-2026-06-09.md §8 Phase 1.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pure logic over PortSession.Attempts (no live ops): - workflow/port_progress.go: three terminators — two-counter stall detection (classStallStreak keys on FailureClass CATEGORY so it survives Signals variation; phaseStallStreak on fix-class phase non-advancement, with a progressRose seam for Phase 3 tier-rise), iteration cap per band (EASY 4/MEDIUM 8/HARD 12) closing the wrapped session with the existing CloseReasonIterationCap, wall budget (time injected). EvaluatePortProgress rolls them up; cap measured from RebudgetOrigin. - workflow/port_escalate.go: T0 stay / T1 source-build→prebuilt (classStall>=3 on build or OOM-flag, AND a PrebuiltURL exists, still on source-build) / T2 bail; credential+network never escalate. - iterate handler wires the decision: T1 mutates Plan.Acquisition + re-budgets; any terminator stops (cap → idempotent close guarded on CloseReason, not raw ClosedAt — P5 TestNoRawClosedAtReads); T0 returns the fix guidance. Adds PortPlan.PrebuiltURL + PortSession.RebudgetOrigin. work_session.go untouched. TDD: classStall-survives-signal-variation, phaseStall trip/reset, cap+close, T1-only-with-prebuilt, credential/network-no-escalate, wall budget. build + tests + TestArchitectureLayering + TestNoRawClosedAtReads + make lint-local green. Plan: plans/oss-recipe-port-flow-2026-06-09.md §8 Phase 2 (§4 mechanics). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
docs/spec-oss-port-flow.md — the runtime/architecture reference (distinct from the build plan): two-stage model (port&harden → capture), agent-driven loop, recon + acquisition ladder (incl. crane image-lift), fix-class dispatch, two-counter termination + T0/T1/T2 escalation, rubric→FitCeiling, the curated publish channel (zerops-recipe-apps + zeropsio/recipes, NOT .zerops-recipe/), feasibility bands + the PostHog reality, and implementation status (Phases 0-2 built, 3-5 designed). Pointer added to CLAUDE.md key specs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… plan Design artifacts the feat/oss-port-flow commits reference: the port-flow plan (plan of record), its independent verification verdict, and the superseded software-shape plan (kept for D4/D6 + verified contract facts). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Scores how well the ported software runs; logic unit-tested, live harden deferred: - workflow/port_rubric.go: C1 builds / C2 boots-STABLE (ACTIVE-then-exit→1, stable→2) / C3 serves / C4 core-flow / C5 persists / C6 HA (throughput=1 vs HA-replication=2, MEMORY invariant). Port-local PortTierLevel enum (6 levels) — NO recipe.Tiers() import (depguard-clean; Break #1 resolved); recipe.TierAt re-derived at Phase 4 emit. - workflow/port_fitceiling.go: FitCeiling + pure BuildFitCeiling — highest-honored-tier projection; a tier is honored only if prereqs met (C5=2,C6=1 ⇒ tiers 0-4, tier 5 excluded with reason; C1=C2=C3=0 ⇒ infeasible). Measured ceiling vs recon band both kept. - workflow/port_harden.go: PlanHarden (durable-surface sentinel plan + HA scale probe) + pure GradeHarden(injected results) → C5/C6. No ops calls in workflow. - tools/workflow_port_harden.go: agent-driven "harden" action — emits sentinel/scale guidance, grades agent-reported results, builds + persists FitCeiling on PortSession. - progressRose wired: EvaluatePortProgress(ps, now, progressRose); a rising measured ceiling breaks phaseStall (the Phase 2 seam). iterate attaches FitCeiling at stop/bail. TDD: each C grade, roll-up incl. tier5-not-honored + infeasible, rose-breaks-phaseStall, harden grading from mocks, FitCeiling shape + reasons. build + tests + TestArchitectureLayering (no workflow→recipe) + make lint-local green. work_session untouched. Plan: plans/oss-recipe-port-flow-2026-06-09.md §5 + §8 Phase 3. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Stage B: turn the working ported deployment into a curated recipe. First (additive)
touch of internal/recipe; framework emit path byte-identical (goldens unchanged).
- recipe/yaml_emitter.go: D6 buildFromGit override at BOTH emit sites — runtime
(writeRuntimeBuildFromGit) AND the ServiceKindUtility branch (which emitted none).
Emits Plan.GlueRepoURL verbatim (canonicalized via topology.CanonicalRepoURL) when
set; falls back to the hardcoded RecipeAppRepoBase form when empty. recipe/plan.go:
Plan.GlueRepoURL (omitempty). recipe/assemble.go: exported SubstituteFragmentMarkers.
- tools/workflow_port_capture.go: handlePortCapture (action "capture") — gated on
FitCeiling.Feasible; portSessionToPlan maps the working topology + honored-tier
subset + glue URL into a *recipe.Plan; emits environments/<N — Name>/{import.yaml,
README.md} via EmitDeliverableYAML + recipe.TierAt for honored tiers ONLY; authors
rich content (description/features/takeover-guide/knowledge-base from FitCeiling
evidence + UnresolvedConstraints) via the existing marker machinery; publishes app→
zerops-recipe-apps + envs→zeropsio/recipes via direct sync calls (portPublisher
seam, initialized var). BuildFromGitReady=false → defers publish, never fails (OQ-1).
Grounding: D4 recipe-level fragment SURFACES not needed — curated rich content rides
the existing marker machinery + publish flags + Strapi, same as framework recipes.
TDD: GlueRepoOverride (both sites; empty→hardcoded), PortSessionToPlan honored-subset,
capture feasible/infeasible/not-scored/glue-not-ready. Existing recipe suite
(TestYAMLEmitter_MatchesFixture etc.) stays green = framework path unchanged.
build + recipe/workflow/tools/sync tests + TestArchitectureLayering +
TestNoCrossCallHandlerState + make lint-local green.
Plan: plans/oss-recipe-port-flow-2026-06-09.md §8 Phase 4. Spec status bumped to 0-4.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Finisher, using the CORRECTED PostHog reality (plan §12): PostHog is fully feasible INCLUDING HA — the honest residue is knowledge depth, not infeasibility. - port_recon.go: cross-service-ordering axis (PortTargetDescriptor.CrossServiceOrdering) — forces BandHard and records the IN-BAND fix (zsc execOnce --retryUntilSuccessful + zsc scale ram max), never a bail. Acquisition untouched (image-only stays crane-lift). - workflow_port_capture.go: HARD-band honesty content — hardBandChoreographyNote injects the retry-until-ready choreography into the knowledge-base + takeover-guide fragments for BandHard ports; UnresolvedConstraints (Kafka SASL prefixes, Fernet key, ioredis URL, patched Rust fork) surfaced as the honest residue. - PostHog canonical HARD fixture (server-level recon→harden→FitCeiling→capture, real embedded catalog): crane-lift, all deps managed incl. ClickHouse HA, C5=2 + C6=2 → Tier 5 (ha-prod) HONORED (explicitly asserts NOT infeasible, NOT Tier5-dropped) — the §12 correction pinned. Strapi EASY contrast fixture confirms no HARD-band noise. TDD: cross-service-ordering raises-band-not-bail, image-only-stays-crane, PostHog honest contract, HARD-band choreography in fragments + EASY no-leak. build + recipe/workflow/ tools suites + TestArchitectureLayering + make lint-local green. Framework path unchanged. Note: pre-existing flaky test TestDeployIntoDerivedClosedSession_SucceedsAndRecords (session-deploy timing, unrelated to port) — port tests are deterministic (5x green). Plan: plans/oss-recipe-port-flow-2026-06-09.md §8 Phase 5. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ntegration Two test files were left unstaged in their phase commits (impl + unit tests landed, these did not): - recipe/yaml_emitter_test.go: TestEmitDeliverableYAML_GlueRepoOverride — pins D6 (override at runtime + utility emit sites, canonicalized; framework path byte-identical when GlueRepoURL empty). Without this, Phase 4's D6 was unpinned. - tools/workflow_port_iterate_test.go: Phase 2 handler-level integration — iteration-cap closes+stops, build-stall T1 escalation sets RebudgetOrigin, no-prebuilt bails. Both pass; no impl change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…sentinel Codex-validated fixes to the OSS port-flow feasibility/band model (4 review rounds → SHIP). Each finding traced to a real defect, not just a weak test. - C2 gate requires grade 2 (boots STABLE): a crash-loop / ACTIVE-then-exit (C2=1) honors NO tier and lands in WhatDoesnt, never WhatRuns. Pinned by TestRollUpHonoredTiers_C2CrashLoopFailsGate + TestBuildFitCeiling_C2CrashLoopNotInWhatRuns. - Infeasible FitCeiling reports MeasuredCeiling = PortTierNone (-1), distinct from honored Tier 0, so a consumer ignoring Feasible can't misread it. - Port emits MEASURED HA topology, not capability-table assumptions: the agent reports per-dep haDeps; DeriveAchievableHA filters to planned mode-bearing deps (storage excluded); the C6 grade AND the emitted per-service mode both consume the same ManagedHADeps list, so they cannot diverge. ClickHouse emits HA (mandatory for PostHog ON CLUSTER DDL), Postgres/Valkey NON_HA — matching the real recipe-posthog. Driven by additive recipe.Service.ModeMeasured + the single-owner recipe.ManagedServiceModeForTier; framework emit path is byte-identical (ModeMeasured=false keeps the run-12 §Y3 family-table logic). - managedTypeFor resolves bare types (strip :ha/:single) so the emitter owns mode via the mode: field, not a composite type token. clickhouse added to the HA family table (proven HA on Zerops). - Cleanups: dead constraints counter, stale Phase-5 plan row, doc/logic mismatch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.