AGENT SKILL

go

Write native Go for cnos. Use when building the runtime/kernel, package tooling, command dispatch, HTTP services, or other low-level infrastructure in Go.

License 许可
Apache-2.0
所属仓库
usurobor/cnos
最近更新
2026-11-07
Stars
★ 9
Forks
0

01 前言 Front Matter

name
go
scope
task-local
triggers
[ "implementing cnos runtime/kernel code in Go", "creating package/command/orchestrator infrastructure in Go", "building HTTP/file/git/process integrations in Go", "reviewing Go code for cnos", "migrating logic from OCaml or shell into Go" ]
description
Write native Go for cnos. Use when building the runtime/kernel, package tooling, command dispatch, HTTP services, or other low-level infrastructure in Go.
kata_surface
embedded
artifact_class
skill
governing_question
How do we write Go that keeps cnos simple, explicit, testable, and easy for any agent to build anywhere?

03 SKILL.md 正文

Go

Core Principle

Write Go that is boring to run, easy to read, and explicit about failure.

Use packages to keep boundaries clear, concrete types to keep intent obvious, and error values to make degraded behavior visible. Prefer simple code paths that any agent can build and reason about on any machine.

Algorithm

  1. Define — name the model, the package boundaries, the failure policy, and the build/test contract.
  2. Unfold — design the package layout, types, interfaces, context flow, error flow, resource lifecycle, and tests.
  3. Rules — keep the code explicit, small-package, low-magic, and hostile to silent fallback.
  4. Verify — build, test, and review the same failure classes across sibling surfaces.

1. Define

1.0. Classify the artifact first

Use this skill for Go code that belongs in the cnos runtime/kernel layer:

  • package management
  • command dispatch
  • orchestrator runtime
  • runtime contract emission
  • HTTP services
  • file/git/process adapters
  • transport and protocol support

Do not use this skill for:

  • product prose
  • package-authored Markdown skills
  • shell one-offs that should stay shell one-offs
  • workflow judgment rules better expressed as package skills

1.1. Identify the parts

A coherent Go subsystem has:

  • Packages — the primary unit of design
  • Types — concrete domain models
  • Interfaces — small consumer-owned seams
  • Errors — explicit outcome channel
  • Context — cancellation / deadline propagation
  • Observability — structured log/slog state emission
  • Adapters — file, git, HTTP, process, archive, env
  • Tests — table-driven and subtest-based
  • Build — go build / go test / go mod tidy, no exotic toolchain
    • ❌ Start with helpers and globals, then invent packages later
    • ✅ Name the packages and types first, then fill in behavior

1.2. Articulate how they fit

Packages own responsibilities. Concrete types carry domain meaning. Interfaces appear where callers need substitution. Context flows from entrypoint downward. Errors make failure explicit. Adapters isolate side effects. Tests prove both success and degraded behavior.

  • ❌ One package owns CLI, HTTP, registry parsing, and git side effects together
  • ✅ cmd/cn wires internal/runtime, which uses internal/deps, internal/contract, and internal/transport

1.3. Name the failure mode

Go code fails through:

  • package sprawl — blurry boundaries, cyclic dependencies, util buckets
  • interface pollution — interfaces declared before there is a real consumer need
  • context leaks — context stored in structs or dropped on the floor
  • resource leaks — failing to defer cleanup for files, network responses, or locks
  • opaque exhaust — unstructured fmt.Printf or log.Printf that hides system reality
  • panic-driven control flow — expected failure treated as exceptional collapse
  • silent fallback — error ignored, empty value fabricated, caller never told
  • global state drift — mutable package globals controlling behavior invisibly
  • library fatalism — log.Fatal / os.Exit deep in reusable code
    • ❌ if err != nil { return nil }
    • ✅ if err != nil { return fmt.Errorf("read package index: %w", err) }

2. Unfold

2.1. Package design

Design packages around responsibilities, not layers of convenience.

Use short, lower-case package names. Avoid names that steal good local variable names or say nothing.

  • ❌ common, utils, helpers, misc
  • ✅ deps, contract, transport, command, workflow, activation

For cnos, prefer a shape like:

cmd/cn/                # CLI entrypoint only
internal/deps/         # package index, lockfile, restore/install logic
internal/contract/     # runtime contract types + rendering
internal/command/      # command registry + dispatch
internal/workflow/     # orchestrator IR + runner
internal/activation/   # skill activation index + evaluator
internal/transport/    # peer/mail/A2A support
internal/host/         # fs/git/http/process/archive/env adapters
  • ❌ Import side-effecting adapters directly from every package
  • ✅ Keep impure adapters at the edge and pass them inward through concrete types or narrow interfaces

2.2. Type design

Prefer concrete types. Make the zero value useful when practical. Use structs and typed constants to model the domain directly.

// ✅ concrete domain model
type SourceKind string

const (
    SourceReleaseHTTP SourceKind = "release-http"
    SourceLocal       SourceKind = "local"
)

type PackageLock struct {
    Name    string
    Version string
    SHA256  string
}

Make the zero value useful when it does not violate invariants.

  • ❌ Constructor required for a plain data holder with no invariants
  • ✅ Plain struct with zero-value-safe fields

Use constructors only when you must enforce:

  • invariants
  • normalization
  • hidden/internal fields

2.3. Interfaces

Define interfaces where they are consumed, not where they are produced. Use interfaces to express what a caller needs from a dependency.

  • ❌ Producer package exports type Store interface { ... } before any consumer needs it
  • ✅ Consumer package defines the minimal interface it needs

Prefer:

  • concrete return types
  • narrow interfaces as inputs
// ✅ consumer-owned interface
type ReleaseFetcher interface {
    FetchLatest(ctx context.Context) (Release, error)
}

Avoid any / map[string]any as a domain model except at true JSON boundaries.

2.4. Context

context.Context is a parameter, not a field.

Rules:

  • first parameter
  • never nil
  • do not store in structs
  • pass it through long-running or blocking operations
  • check ctx.Done() in loops and retries
func (r *Registry) Resolve(ctx context.Context, name, version string) (Artifact, error) {
    // ...
}
  • ❌ type Client struct { ctx context.Context }
  • ❌ func Resolve(name string) (...)
  • ✅ func Resolve(ctx context.Context, name string) (...)

2.5. Errors and fallback

Errors are values. Fallback is policy.

Return errors for expected failures. Reserve panic for impossible states or invariants broken by programmer error.

Rules:

  • wrap with %w
  • error strings start lower-case
  • no trailing punctuation
  • never log.Fatal or os.Exit inside reusable packages
  • never silently fabricate success from failure
  • explicitly use errors.Is and errors.As to inspect wrapped errors for fallback logic
if err != nil {
    return fmt.Errorf("read package index: %w", err)
}

// ✅ Explicit inspection for fallback
if errors.Is(err, fs.ErrNotExist) {
    // apply intentional policy ...
}

Fallbacks must be explicit and visible:

  • ❌ "if missing, just return empty registry"
  • ✅ "if missing and local override is allowed, log/annotate the degraded path and continue by policy"

If a fallback exists, document:

  • why it exists
  • when it applies
  • what it returns
  • what signal tells the caller it happened

2.6. Side-effect boundaries

Keep side effects at the edge. The core logic should decide:

  • what to load
  • what to validate
  • what to write
  • what to execute

Adapters should only do:

  • filesystem
  • git
  • HTTP
  • archive
  • env
  • subprocess

Rules for adapters:

  • Inject adapters into domain structs at initialization.
  • Strictly ban package-level mutable state or init() wiring.
    • ❌ Parse a package manifest inside the HTTP client
    • ✅ HTTP client returns bytes; parser validates in the domain package

2.7. Resource lifecycles

Resources must explicitly articulate their cleanup immediately after acquisition.

Rules:

  • use defer for Close(), Unlock(), or cleanup functions immediately after checking the acquisition error
  • never assume the garbage collector handles OS-level resources
resp, err := client.Do(req)
if err != nil {
    return err
}
// ✅ Teardown bonded to acquisition
defer resp.Body.Close()
  • ❌ Acquire a file handle, then close it 50 lines later in a conditional branch
  • ✅ defer f.Close() on the line after the nil-error check

2.8. Observability

State must be structured and queryable, not opaque text.

Rules:

  • use log/slog for all runtime logging
  • attach key-value attributes (e.g., slog.String("pkg", name)) rather than concatenating strings
  • log degraded paths explicitly when a fallback policy is triggered
// ✅ Structured state articulation
slog.WarnContext(ctx, "local override allowed, bypassing missing index",
    slog.String("package", pkgName),
    slog.String("fallback_path", localPath),
)
  • ❌ fmt.Printf("warning: package %s missing, using fallback\n", name)
  • ✅ slog.WarnContext(ctx, "package index missing, applying local override policy", slog.String("package", name))

2.9. Concurrency

Do not add goroutines because Go makes them cheap. Add them when they simplify the model or materially improve throughput.

Rules:

  • own cancellation with context
  • keep fan-out/fan-in explicit
  • prefer sequential correctness first
  • use channels when communication is the model, not as decoration
    • ❌ Spawn goroutines for every restore step with no backpressure or cancellation
    • ✅ Keep restore sequential until parallelism is justified by real latency/throughput data

2.10. Testing

Use go test as the contract.

For deterministic logic:

  • table-driven tests
  • subtests with t.Run
  • golden/text fixtures under testdata/ where useful

For adapters:

  • fake servers / temp dirs / test repos
  • explicit degraded-path tests

Typical commands:

go test ./...
go test -race ./...
go build ./...

Test both:

  • success
  • degraded/malformed/missing/unsupported cases
    • ❌ Only test the happy path
    • ✅ Test both the nominal path and the policy path

2.11. Build and shipping

Any agent on any machine should be able to build the runtime with the standard Go toolchain.

Keep the build boring:

  • standard module layout
  • strict module hygiene (go mod tidy)
  • no custom code generation unless justified
  • minimal external dependencies
  • cross-compile only when needed, not as a daily burden

Prefer stdlib first:

  • encoding/json
  • net/http
  • log/slog
  • archive/tar
  • compress/gzip
  • crypto/sha256
  • os/exec
  • path/filepath

Do not reimplement stdlib functions. Before writing any helper, check whether the standard library already provides it. This is a recurring review finding:

  • ❌ Hand-rolled contains(s, sub string) bool → ✅ strings.Contains
  • ❌ Hand-rolled joinArgs(args []string) string → ✅ strings.Join
  • ❌ Hand-rolled envMap() copying os.Environ() → ✅ os.Getenv at point of use

If you write a utility function, verify it doesn't exist in strings, slices, maps, path/filepath, sort, bytes, fmt, or os first.

2.12. Schema and compatibility

Treat manifests, contracts, and IRs as public contracts.

When handling:

  • package manifests
  • runtime contract data
  • command/orchestrator registries
  • lockfiles
  • indexes
  • workflow IR

prefer:

  • additive evolution
  • explicit version fields
  • strict validation of required fields
  • tolerant handling of unknown fields when forward compatibility matters
    • ❌ Silently coerce malformed config into defaults
    • ✅ Reject malformed input with an explicit error and enough context to repair it

If a compatibility path exists, test it explicitly.

Sibling harnesses are contract surfaces too. When a Go type defines a JSON schema (e.g. pkg.Manifest for .cn/deps.json), every non-Go producer of that JSON — shell test harnesses, CI workflow steps, template-emitted defaults — is a contract surface on the same schema. The schema audit must extend to those producers. Mechanical check: for each Parse*([]byte) added or changed, grep the repo for non-Go writers of the same JSON shape and verify they still produce the declared schema. Derives from: 3.56.2 (#250) — cnos.kata/lib.sh write_deps_json was emitting object-syntax packages while the Go parser expected an array; the bug masked the mismatch until the bug itself was fixed.

  • ❌ Audit only the Go parser when changing a schema-bearing type
  • ✅ grep -rn '"packages"' src/ and inspect every writer (Go, shell, workflow YAML)

2.13. Determinism and reproducibility

Deterministic output matters. For artifacts that are:

  • hashed
  • compared in tests
  • used in reports
  • stored for later diffing
  • emitted as runtime contracts

ensure:

  • stable ordering
  • canonical serialization
  • no dependence on map iteration order
  • no hidden timestamps unless intentionally included
  • no dependence on Go toolchain version for output bytes — compress/gzip flate output is not stable across minor Go versions. Pin the toolchain in go.mod and all CI setup-go calls. If cross-version byte-identity is required, use gzip.NoCompression or generate deterministic artifacts on CI rather than at author-time.
    • ❌ Range over a map and render the result directly
    • ❌ Assume gzip.NewWriter produces identical bytes on Go 1.22 and Go 1.24
    • ✅ Sort keys/items before rendering
    • ✅ Pin Go version in go.mod + CI workflows when artifacts are hashed

2.14. Idempotence and retry safety

For state-changing operations, define:

  • what happens on interruption
  • whether the operation is idempotent
  • what partial state is left behind
  • how cleanup works
    • ❌ Write directly to the final target and hope the process completes
    • ✅ Write to temp, validate, then atomically move into place

2.15. Traceability and receipts

For operations like:

  • package restore
  • update
  • command registry rebuild
  • orchestrator execution
  • sync / transport handling

decide explicitly:

  • what is returned
  • what is logged
  • what is written to status/doctor/runtime contract
  • what receipt or trace event exists
    • ❌ Degraded path only visible in transient stderr
    • ✅ Degraded path visible in logs and/or structured runtime state

2.16. Preserve cnos runtime boundaries

Keep these boundaries explicit in Go code:

  • skills choose
  • commands dispatch
  • orchestrators execute
  • extensions provide capability

Do not let core/runtime packages smear these concepts together.

  • ❌ A command registry that also decides skill activation logic
  • ✅ Separate registries and clear ownership

The kernel stays minimal. Package-driven commands are preferred over built-ins. Core should not accrete convenience commands casually. Mechanical first, semantic second — the kernel resolves, validates, registers, dispatches, and enforces policy. It does not do hidden interpretation or "smart" inference when explicit metadata should exist.

2.17. Purity boundary: Parse vs Read

Derives from: INVARIANTS.md T-004 (source/artifact/installed explicit)

Pure functions operate on bytes/data. IO functions operate on paths/network. Keep them separate.

// Pure — no os imports, no IO
func ParseManifestData(data []byte) (*PackageManifest, error)

// IO wrapper — calls pure function
func ReadManifest(path string) (*PackageManifest, error) {
    data, err := os.ReadFile(path)
    if err != nil { return nil, err }
    return ParseManifestData(data)
}

This mirrors the OCaml src/lib/ (pure) vs src/cmd/ (IO) discipline.

  • ❌ func ParseManifest(path string) — mixes file IO with parsing
  • ✅ func ParseManifestData(data []byte) pure + func ReadManifest(path string) IO wrapper
  • ❌ internal/pkg/ importing os
  • ✅ internal/pkg/ has zero os imports; all IO enters through explicit wrappers elsewhere

Rule: Parse* takes []byte, returns typed data. Read* takes a path, calls Parse*. No mixing.

Diff-local generalization: do not introduce a parallel parser when a new pure parser is added in the same PR. When a diff introduces a new canonical pure parser for a fact (pkg.ParseInstalledManifestData([]byte) → *PackageManifest), every other consumer of the same fact in the same diff is structurally bound to the new canonical. Hand-rolling an inline anonymous-struct unmarshal of the same JSON shape elsewhere in the diff is a parallel-parser violation even if every individual call-site obeys the parse/read split — eng/go §2.17 is also a "one parser per fact" rule, not only a "no IO in pure code" rule. Verification at authoring time: for every new Parse* introduced, grep the diff for sibling json.Unmarshal / anonymous-struct decodes against the same JSON shape; replace each with a call to the new canonical parser. Derives from: #274 F1 (severity C judgment) — the same diff that introduced pkg.ParseInstalledManifestData and the IO wrapper restore.ReadInstalledManifest (correctly applied to restore.restoreOne) also landed an inline anonymous-struct unmarshal in doctor.checkPackages. β caught it via cdd/review §2.2.8 (authority-surface conflict); α fixed cleanly in round 2 by importing pkg into doctor.go and replacing the inline block with pkg.ParseInstalledManifestData(manifestData) (~5 lines net).

2.18. Dispatch boundary: cli/ owns dispatch only

Derives from: INVARIANTS.md T-002 (kernel remains minimal and trusted)

cli/ contains: types (CommandSpec, Invocation, Command, Registry) and thin command wrappers. Domain logic lives in domain packages.

internal/cli/         # dispatch only — types, registry, thin cmd_*.go wrappers
internal/doctor/      # doctor check logic
internal/pkgbuild/    # build pipeline logic
internal/restore/     # deps restore logic
internal/hubinit/     # hub creation logic
internal/hubstatus/   # status display logic
  • ❌ cmd_doctor.go with 238 lines of check logic inline in cli/
  • ✅ cmd_doctor.go as a 20-line wrapper calling doctor.Run()
  • ❌ Any cmd_*.go in cli/ with more than ~30 lines of domain logic
  • ✅ Domain logic extracted to its own package, cmd_*.go delegates

Rule: If a command's logic exceeds a thin wrapper, extract it to a domain package. cli/ owns dispatch. Domain packages own logic.


3. Rules

3.1. Package rule

Use small packages with short, specific names.

  • ❌ common, helpers, shared
  • ✅ deps, contract, workflow, activation

No cyclic imports. No package whose only meaning is "miscellaneous."

3.2. Interface rule

Define interfaces in the consumer package. Return concrete types by default.

  • ❌ "everything behind an interface"
  • ✅ interfaces only where substitution/test seams are real

3.3. Context rule

Pass context.Context explicitly as the first parameter. Do not store it in structs. Do not drop it on the floor.

3.4. Error and observability rule

Expected failure returns error. Do not panic for policy-level failure. Wrap errors with context (%w). Inspect errors carefully with errors.Is/errors.As before falling back. Do not swallow them. Use log/slog to articulate fallback state structurally.

3.5. Fallback rule

Every fallback is a policy decision. Allowed only when:

  • the degraded behavior is intentional
  • the caller can still reason about the result
  • the fallback is visible through logs, return values, or explicit state
    • ❌ return nil on malformed config and continue
    • ✅ return fmt.Errorf("parse activation index: %w", err)

3.6. Resource rule

defer must immediately follow the successful acquisition of files, network bodies, and locks. Never defer before the error check.

3.7. Boundary rule

Parsing, validation, and planning belong in domain packages. Filesystem, git, HTTP, process, and env access belong in adapters. Dependency injection is required for adapters.

3.8. Build rule

Run before push:

go mod tidy
go test ./...
go build ./...

If the change adds concurrency or shared mutable state, also run:

go test -race ./...

3.9. Smell list

Treat these as review smells:

  • panic for expected errors
  • log.Fatal / os.Exit in libraries
  • context.Context stored in a struct
  • producer-owned interfaces with one implementation
  • package-level globals or init() used for runtime state
  • map[string]any as core domain model
  • package util / common
  • hidden package globals controlling behavior
  • silent empty fallback on parse or IO error
  • goroutines with no cancellation path
  • unwrapped external errors
  • string-matching error messages instead of errors.Is
  • missing defer for Close() or Unlock()
  • unstructured fmt.Printf or log.Printf for system state
  • unstable map iteration in rendered/hashed output
  • non-atomic writes to final targets (no temp → validate → rename)
  • archive extraction without path-traversal validation
  • shell command built by string concatenation
  • precedence logic undocumented or untested
  • command/orchestrator/extension boundaries smeared in one package
  • degraded path invisible outside transient stderr

3.10. Shell and archive safety

When using subprocesses or archives:

  • do not shell-escape by string concatenation
  • prefer argv-based execution (exec.Command with separate args)
  • validate destination paths before extraction
  • reject archive entries that escape the target directory
  • never log secrets
    • ❌ sh -c "curl ... $USER_INPUT ..."
    • ✅ exec.CommandContext(ctx, "curl", "-fsSL", url)

3.11. Override precedence must be explicit

If behavior may come from:

  • flags
  • environment
  • config
  • runtime discovery
  • defaults

define the precedence clearly and test it.

  • ❌ Precedence inferred from code order
  • ✅ Documented and table-tested precedence

4. Verify

4.1. File-level check

  • Is the package boundary clear?
  • Is the type model concrete?
  • Is the failure policy explicit?

4.2. Boundary check

  • Is IO at the edge?
  • Are adapters injected rather than globally accessed?
  • Are adapters separated from parsing/validation/planning?

4.3. Error, resource, and observability check

  • Are all expected failures returned as error?
  • Are fallbacks explicit, inspected via errors.Is, and justified?
  • Are resources reliably released via defer?
  • Is state emitted via log/slog (not fmt.Printf)?

4.4. Context/concurrency check

  • Does context flow correctly?
  • Are goroutines owned, bounded, and cancellable?

4.5. Schema/compatibility check

  • Are manifests and contracts validated strictly on required fields?
  • Are unknown fields tolerated where forward compatibility matters?
  • Is schema version checked explicitly?

4.6. Determinism check

  • Is output ordering stable (sorted, not map-iteration-dependent)?
  • Are hashes computed over canonical content?

4.7. Safety check

  • Are subprocesses argv-based (no string concatenation)?
  • Are archive extractions path-validated?
  • Are secrets excluded from logs?
  • Is override precedence documented and tested?

4.8. cnos boundary check

  • Are command/orchestrator/extension/skill boundaries preserved?
  • Is the kernel minimal (no casual built-in accretion)?
  • Are degraded paths visible in structured state, not just stderr?

4.9. Build/test check

  • go mod tidy
  • go test ./...
  • go build ./...
  • go test -race ./... where warranted

5. Kata

5.1. Kata A — package restore over HTTP

Scenario: Implement first-party package restore from an artifact index and tarball.

Task: Write Go code that:

  • resolves name + version
  • downloads artifact + checksum
  • verifies SHA-256
  • extracts into vendor
  • returns explicit errors for all malformed/missing cases

Governing skills: go, design, test

Inputs:

  • package index fixture
  • checksum fixture
  • tarball fixture
  • malformed checksum/index cases

Expected artifacts:

  • concrete package types
  • no producer-owned interfaces
  • explicit adapter boundaries (struct injection)
  • tests for happy path and malformed checksum/index cases

Verification:

  • go test ./...
  • no silent fallback from malformed index or checksum mismatch
  • no panic on network/IO/parse failure

Common failures:

  • hidden global HTTP client
  • parse logic inside transport layer
  • panic on malformed metadata
  • missing degraded-path tests

Reflection:

  • Did the restore path stay mechanical and deterministic?
  • Did every fallback remain explicit and visible?

5.2. Kata B — runtime contract builder

Scenario: Extract runtime contract model/rendering out of a large command handler.

Task: Move:

  • types
  • validation
  • rendering helpers

into a reusable Go package, leaving command wiring in cmd/cn.

Governing skills: go, design, write

Inputs:

  • one existing command handler with mixed model/render/wiring logic
  • one expected JSON output
  • one expected text output

Expected artifacts:

  • clear package boundary
  • concrete types
  • explicit command wiring
  • tests for JSON and text rendering

Verification:

  • no system-truth logic left stranded in the CLI entry package
  • no cyclic imports
  • output stays stable under tests

Common failures:

  • moving IO into the model package
  • inventing interfaces where concrete types suffice
  • leaving rendering behavior untested

Reflection:

  • Did the extraction reduce command-layer ownership of system truth?
  • Did the new package keep IO at the edge?

04 同仓库更多 Skills

usurobor
usurobor/cnos

issues/triage

Issue triage doctrine pointer. Use when classifying a new issue, deciding dispatch eligibility, or deciding whether to close/supersede/defer.

★ 9
usurobor
usurobor/cnos

issues/taxonomy

Issue label taxonomy pointer. Use when classifying an issue's kind/area/priority/effort/status/protocol/dispatch labels, or when the board needs to interpret them.

★ 9
usurobor
usurobor/cnos

issues/map

Issue-board (Issue Pivot) generation domain. Use when reasoning about `cn issues map`'s fetch, taxonomy-parse, effort-computation, and render pipeline, or about the board's JSON/HTML output contract.

律师与法务前端开发
★ 9
usurobor
usurobor/cnos

issues

cnos.issues package entrypoint. Use when reasoning about issue taxonomy, the Issue Pivot / issue-board (`cn issues map`), the read-only CDS issue-state evaluator (`cn issues fsm evaluate`), or the current command-dispatch disposition of issue tooling.

★ 9
usurobor
usurobor/cnos

receipt-stream

Cross-cycle receipt-stream doctrine for protocol-iteration. Use when γ closes a cycle and writes the per-cycle iteration artifact (`cdd-iteration.md`), when γ updates the cross-cycle aggregator at `.cdd/iterations/INDEX.md`, when ε reads the receipt stream across cycles to surface protocol-gap patterns, when a finding's disposition lands a cross-repo patch and the cross-repo trace bundle attaches, or when a courtesy empty-findings stub is written for a `protocol_gap_count == 0` cycle.

★ 9
usurobor
usurobor/cnos

mid-flight

Mid-flight γ→in-flight-α rescue channel. Use when γ needs to change a load-bearing fact (pinned axis, scope, AC, blocker) after α has begun coding, when γ edits the cycle's GitHub issue body mid-cycle, or when a spec change lands on origin/main while α/β polling sessions are in-flight.

★ 9