Skip to content

feat: phase 1 core (model, link, rules) - #3

Merged
Skeyelab merged 23 commits into
mainfrom
feat/core
Oct 7, 2026
Merged

Skeyelab merged 23 commits into
mainfrom
feat/core

Conversation

@Skeyelab

@Skeyelab Skeyelab commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

Phase 1 of the app-green v1 plan: the pure core, with no network code. Design, spike and plan are in #2.

What's here

  • internal/model: shared types (tickets, PRs, environments, deploys, slots, chains, stages, flags).
  • internal/link: Jira keys in PR titles/branches, ticket-to-PR linking with stacked PRs, and per-environment slots ("is this change running here now?").
  • internal/rules: chain stage, needs-action flags in a fixed order, sorting and fading.
  • internal/e2e: end-to-end tests from linking through rules on realistic synthetic chains.

100 tests, race-clean. Every task went through spec and code-quality review; later work used one-test-at-a-time TDD.

Decisions made during review (they supersede the plan's Phase 1 code)

  • Running now, not ever deployed: a change counts in an environment only if that environment's newest successful deploy contains it. Rollbacks (including batched ones) show a red rolled back flag.
  • In prod only when every applicable prod environment has it. Partial prod past partial_prod_after (4h) gets a yellow flag targeting the missing environment.
  • Repos per environment come from config (Env.Repos). Missing history, or a merged repo no environment deploys, shows yellow deploy unknown and keeps the row out of "in prod".
  • Stacked PRs: pending stacks hold the stage at "merged". PRs merged into a dead branch get a red stranded flag. The phase-2 GitHub adapter must fetch each base branch's PR to avoid false reds.
  • Unhealthy prod stays "in prod" with a red flag. Failure beats unknown. A newer in-flight run supersedes an old failure. "Since" is when the change went live again after a rollback.
  • Approved PRs with no checks count as ready to merge. GitHub's ERROR/EXPECTED check states count as failing.
  • Jira status uses the stable statusCategory.key. To Do or In Progress with merged work is a status mismatch. Done tickets with no PRs are hidden.
  • Missing timestamps fail safe: a deploy with no time never fades; a Done ticket with no status time uses last-updated.

Assisted-by: Claude Code:claude-opus-5-5

Skeyelab and others added 23 commits October 6, 2026 13:00
Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Claude Code:claude-opus-5-5
…in-flight runs

Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Claude Code:claude-opus-5-5
…fallbacks

Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Claude Code:claude-opus-5-5
…flag

Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Claude Code:claude-opus-5-5
- link compares repos ignoring case everywhere (Env.Repos, PR.Repo,
  Deploy.Revisions keys) through one revision lookup.
- A deploy carries a repo only with a non-empty SHA for it.
- rules flags a merged repo that no Env.Repos names: yellow deploy unknown,
  "<repo> not deployed by any configured environment", no slot target. It is
  skipped when no Env sets Repos (history fallback).
- Ticket.StatusCategory is typed and holds Jira's statusCategory.key
  (new, indeterminate, done).
- DoneGrace <= 0 turns the Done check off, like the other thresholds.
- Docs: what a Deploy is, adapter ordering and filtering, Env.Repos required
  in practice.

Assisted-by: Claude Code:claude-opus-5-5
- PR.Stranded: link sets it (with StackPending) on a PR merged into a branch
  whose own PR had already merged, or into a branch with no live PR. Waiting
  on an open base PR is not stranded. rules raises a red FlagStranded,
  "PR #n merged into a dead branch", targeting the PR.
- Batched rollback: when the newest success does not contain a PR and no
  older success carried its exact SHA, link walks older successes newest to
  oldest; the first that contains it makes the slot RolledBack (unless a
  newer run contains it). The walk stops at a compare that cannot answer.
- A Done ticket with no PRs (closed ones ignored) gets no status mismatch
  and Evaluate drops it: nothing to ship.

Assisted-by: Claude Code:claude-opus-5-5
Runs link.Link, link.Slots and rules.Evaluate on synthetic chains across
two accounts (stage-acct, prod-acct), each with Test and Production Envs:
squash merge everywhere, approval wait, missing prod history, rollback,
batched rollback, a landed stack, a stranded stack PR and a repo case
mismatch.

Assisted-by: Claude Code:claude-opus-5-5
A chain with a merged repo that no configured Env deploys no longer reads
"in prod" even when every applicable prod Env has the rest. Same guard as
the unclaimed-repo flag: skipped when no Env sets Repos. PR.Stranded doc
now says callers must pass the PR for each base branch.

Assisted-by: Claude Code:claude-opus-5-5
Same workflow and linters as jira-green, plus a gofmt check.

Assisted-by: Claude Code:claude-opus-5-5
Same change as the other studio repos; the runner image has
build-essential, so go test -race works.

Assisted-by: Claude Code:claude-opus-5-5
The repo is public, and the ger3 runner group is private-repos only.

Assisted-by: Claude Code:claude-opus-5-5
@Skeyelab
Skeyelab merged commit 5f4b77f into main Oct 7, 2026
4 checks passed
@Skeyelab
Skeyelab deleted the feat/core branch October 7, 2026 03:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants