Skip to content

Shipshape spine v1: design contract + schema migration#13

Merged
SYMBaiEX merged 12 commits into
SYMBaiEX:mainfrom
Dexploarer:feat/shipshape-spine-v1
Apr 29, 2026
Merged

Shipshape spine v1: design contract + schema migration#13
SYMBaiEX merged 12 commits into
SYMBaiEX:mainfrom
Dexploarer:feat/shipshape-spine-v1

Conversation

@Dexploarer

@Dexploarer Dexploarer commented Apr 29, 2026

Copy link
Copy Markdown
Collaborator

Re-targeted from a closed PR on the fork. Same content; aimed at upstream now.

Summary

Lays the design contract and DB foundation for the contribution-economy spine described in docs/shipshape-design.md. Implementation lands incrementally on this branch per docs/shipshape-implementation-plan.md.

What's in this PR (10 commits, foundation only):

  • Agent infrastructure carry-over: SPEC.md invariants, CLAUDE.md product-model constraints, /audit and /spike skills, typecheck Stop hook.
  • Full design doc capturing every product decision (~1100 lines): scoring v1 formula, alignment v1 with asymmetric multiplier, pacing + draft queue, penalty system + CI events, community verification, install kit + README badge, organizations as namespace, no-grace-window cut-over.
  • Atomic implementation plan: 33 commits in 6 phases with v0-protection invariant, dependency graph, reviewable batching.
  • Drizzle schema migration 0018_awesome_boom_boom.sql: extends contributors and projects, adds organizations, contributor_penalties, pending_draft_reviews tables. Hand-trimmed from auto-gen drift; uses DO $$ EXCEPTION for ENUM safety.
  • Includes the gemini-code-assist / codereviewbot review-comment fixes (bun-PATH guard on the typecheck hook + Drizzle check() declaration of the CI-evidence-required CHECK constraint).

What's NOT in this PR yet (held for follow-up commits on this same branch per the implementation plan): all phases of implementation work — pure-function libs, public routes, ingest endpoints, workflow wiring, dogfood, etc.

Architecture highlights

  • v0 protection: every commit before Phase 4.5 keeps existing v0 projects scoring/indexing/paying out exactly as today. v1 turns on via dispatch on scoringConfig.formulaVersion.
  • Single cut-over (no grace windows): existing projects auto-promote v0 → v1 in one SQL backfill (commit 44) after wiring is verified. Consistent with SPEC.md's no-grace-windows rule.
  • Penalty system catches gaming at the PR: /gitshipt flag/ban/clear/... slash commands; CI workflows can issue yellow/red but never black; black auto-escalates from repeat reds.
  • Community verification advised, not enforced: per-project communityLinks (Discord/Telegram/X), optional payoutConfig.communityVerifiedThresholdLamports gate. GitShipt does not run or attest to community channels — it surfaces the link and the gate.
  • Organizations as namespace: org defaults snapshotted into projects at creation. No auto-sync (predictable, no surprise mutations to live payouts). Org-level tokens / org-wide bans / org-level shipshape deferred to v2.

Test plan

  • bun run typecheck clean across @repo/lib, @repo/shared, @repo/ui, apps/web
  • bun run db:generate returns "No schema changes, nothing to migrate" — confirms 0018_snapshot.json matches schema files
  • Migration body verified by hand to contain only spine work (auto-gen drift from missing 0003–0017 snapshots removed)
  • ENUMs wrapped in DO $$ EXCEPTION duplicate_object for rerun safety
  • All ADD COLUMN / CREATE INDEX / CREATE TABLE use IF NOT EXISTS
  • Backfill for existing live/paused/killed/simulated_live projects: launch_state = 'launched' so they aren't trapped behind PR 2's launch state machine
  • Future commits on this branch will add unit + e2e tests for each phase per the implementation plan

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Contributor penalty tracking with severity levels and evidence documentation
    • Community contributor verification system
    • Organization-wide configuration management
    • Automated draft pull request review workflow
    • Enhanced contributor attribution and scoring capabilities
  • Documentation

    • Added product specifications and operational guidelines

@vercel

vercel Bot commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

@Dexploarer is attempting to deploy a commit to the SYMBiEX's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Apr 29, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@SYMBaiEX has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 23 minutes and 7 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 70c68be2-d06d-4c25-bc6d-e44a7ca3c802

📥 Commits

Reviewing files that changed from the base of the PR and between 6f08ad9 and 2eba62c.

📒 Files selected for processing (13)
  • .claude/hooks/typecheck-on-stop.sh
  • .claude/skills/audit/SKILL.md
  • .claude/skills/spike/SKILL.md
  • CLAUDE.md
  • apps/web/db/migrations/0020_shipshape_spine_v1.sql
  • apps/web/db/migrations/meta/0020_snapshot.json
  • apps/web/db/migrations/meta/_journal.json
  • apps/web/db/schema/contributor-penalties.ts
  • apps/web/db/schema/index.ts
  • apps/web/db/schema/pending-draft-reviews.ts
  • apps/web/db/schema/projects.ts
  • docs/shipshape-design.md
  • docs/shipshape-implementation-plan.md
📝 Walkthrough

Walkthrough

Introduces Shipshape v1 infrastructure comprising a type-checking Git hook, Claude configuration (settings and skills for audits/spikes), comprehensive PostgreSQL schema additions (organizations, contributor penalties, draft reviews, enhanced contributors/projects), migration SQL, and architectural documentation spanning specifications, design, and implementation planning.

Changes

Cohort / File(s) Summary
Claude Integration
.claude/hooks/typecheck-on-stop.sh, .claude/settings.json, .claude/skills/audit/SKILL.md, .claude/skills/spike/SKILL.md
New stop-hook for conditional TypeScript type-checking via bun run typecheck with graceful fallback when bun is unavailable. Configuration enables hook execution and defines audit/spike skill workflows for production-readiness reviews and architecture spike gating.
Git Configuration
.gitignore
Restructures .claude/ directory tracking to selectively allow .claude/settings.json, .claude/skills/, and .claude/hooks/ while ignoring others. Adds /spikes/ exclusion for architecture spike prototypes.
Documentation & Specifications
CLAUDE.md, SPEC.md, docs/shipshape-design.md, docs/shipshape-implementation-plan.md
Updates operational guidance in CLAUDE.md (SOL-only constraints, auth revalidation, caching profiles, new commands). Introduces SPEC.md as authoritative invariants contract. Adds comprehensive Shipshape v1 design spec (scoring formula, penalty system, community verification, draft auto-review pipeline, install kit) and phased implementation plan with commit sequencing and verification steps.
Database Migrations
apps/web/db/migrations/meta/_journal.json, apps/web/db/migrations/0019_awesome_boom_boom.sql
Migration journal entry and SQL schema migration introducing four new PostgreSQL enums (contributor_attribution_type, contributor_penalty_level, contributor_penalty_issued_by, draft_review_state, project_launch_state), three new tables (organizations, contributor_penalties, pending_draft_reviews), and updates to contributors/projects tables with new columns (attribution routing, community verification, launch state, scoring/alignment configs, install metadata) and indexes.
Database Schema - TypeScript
apps/web/db/schema/organizations.ts, apps/web/db/schema/contributor-penalties.ts, apps/web/db/schema/pending-draft-reviews.ts, apps/web/db/schema/contributors.ts, apps/web/db/schema/projects.ts, apps/web/db/schema/index.ts
Defines Drizzle ORM schemas and TypeScript types for new tables and enhanced existing tables. Introduces ContributorCiInputs, expanded ContributorScoreInputs, scoring/alignment/routing configuration interfaces (ScoringConfigWeights, AlignmentConfig, AgentRoutingPolicy, CommunityLinks, InstallPreferences), penalty and draft-review state enums, and organization schema with installation metadata. Updates barrel export in index.ts.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Poem

🐰 Shipshape sails on Solana's shore,
With penalties and verification lore,
Org tables bloom and drafts take flight,
Type-checked at stops—the code burns bright!
A v1 spine, from spike to spec,
Now that's a ship we won't shipwreck! 🚀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and concisely summarizes the main changes: introducing the design contract (SPEC.md, docs) and schema migration for Shipshape spine v1.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 23 minutes and 7 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the 'Shipshape' contribution-economy spine, adding necessary database schema migrations, organization-level configuration inheritance, and new project-level state management. It also includes utility hooks for typechecking and architecture spikes. My feedback focuses on improving the robustness of the typecheck hook and optimizing the SQL migration backfill to avoid redundant updates.

# This hook never blocks (never exits 1) — typecheck failures are surfaced as
# warnings so the user can decide whether to act, not as hard stops.

set -uo pipefail

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of set -uo pipefail is good practice, but for a hook that should be robust, consider explicitly handling the case where git rev-parse fails inside the subshell to avoid potential issues if the hook is run outside a git repository.

Comment on lines +218 to +220
UPDATE "projects"
SET "launch_state" = 'launched'
WHERE "status" IN ('live', 'paused', 'killed', 'simulated_live');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The UPDATE statement lacks a WHERE clause that limits the scope to only those rows that actually need the update. While it is likely safe here, adding a condition like WHERE launch_state != 'launched' would be more efficient and prevent unnecessary row updates.

UPDATE "projects"
   SET "launch_state" = 'launched'
 WHERE "status" IN ('live', 'paused', 'killed', 'simulated_live')
   AND "launch_state" != 'launched';

Dexploarer added a commit to Dexploarer/GitShipt that referenced this pull request Apr 29, 2026
Two MEDIUM-priority polish items from gemini-code-assist:

1. .claude/hooks/typecheck-on-stop.sh: the previous
   `cd "$(git rev-parse --show-toplevel 2>/dev/null)" || exit 0`
   silently swallowed the not-in-a-git-repo case — `cd ""` is a no-op
   in bash, so the `|| exit 0` never fired and the rest of the hook
   ran in whatever directory the user was sitting in. Now resolves
   the repo root into a variable, exits 0 when empty, then cd's.

2. 0018_awesome_boom_boom.sql backfill: added
   `AND launch_state <> 'launched'` to the UPDATE so it only touches
   rows that still need promotion. No-op on a clean run (column was
   just added with default 'pending_install'), but scopes
   partial-retry / re-applied migrations to the actual delta —
   cheaper, idempotent, self-documenting.

Smoke: hook exits 0 with no .ts changes; bun run typecheck clean
across all 4 packages.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Dexploarer Dexploarer marked this pull request as ready for review April 29, 2026 17:51

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (2)
apps/web/db/schema/pending-draft-reviews.ts (1)

47-48: Enforce terminal-state close metadata invariants in the table schema.

Right now, Line 47–48 allows closed states without closedAt/closeReason (and vice versa). Add a DB check so state and close metadata stay consistent.

Suggested schema-level guard
 import {
   pgEnum,
   pgTable,
   text,
   integer,
   timestamp,
   index,
   uniqueIndex,
+  check,
 } from "drizzle-orm/pg-core";
+import { sql } from "drizzle-orm";
 ...
   (t) => ({
 ...
     stateAgeIdx: index("pending_draft_reviews_state_age_idx").on(
       t.state,
       t.firstReviewedAt,
     ),
+    closeStateConsistency: check(
+      "pending_draft_reviews_close_state_consistency",
+      sql`(
+        ${t.state} IN ('stale_closed', 'no_penalty_closed', 'merged_via_maintainer')
+        AND ${t.closedAt} IS NOT NULL
+        AND ${t.closeReason} IS NOT NULL
+      ) OR (
+        ${t.state} NOT IN ('stale_closed', 'no_penalty_closed', 'merged_via_maintainer')
+        AND ${t.closedAt} IS NULL
+        AND ${t.closeReason} IS NULL
+      )`,
+    ),
   }),
 );

Also applies to: 58-62

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/db/schema/pending-draft-reviews.ts` around lines 47 - 48, Add a DB
CHECK constraint to ensure terminal-state/close metadata consistency: for the
table definition containing columns state, closedAt, and closeReason, add a
constraint (e.g. chk_close_metadata_consistency) that enforces "if state is a
terminal/closed value then closedAt IS NOT NULL AND closeReason IS NOT NULL, and
if state is not terminal then closedAt IS NULL AND closeReason IS NULL";
implement the same check on the other similar table/block referenced (lines
58–62). Name the constraints clearly and use the table's state enum/values to
detect terminal states when building the boolean expression.
apps/web/db/schema/projects.ts (1)

76-99: Constrain AlignmentConfig.mode to currently shipped modes.

Line 78 currently allows "multiplicative" and "gate" in persisted config even though this phase documents asymmetric alignment as the shipped v1 behavior. Limiting persisted modes now avoids unsupported runtime states.

Suggested diff
 export interface AlignmentConfig {
   enabled: boolean;
-  mode: "informational" | "asymmetric" | "multiplicative" | "gate";
+  mode: "informational" | "asymmetric";
   floor: number;
   ceiling: number;
Based on learnings: `SPEC.md` is the frozen list of invariants and explicit non-goals.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/db/schema/projects.ts` around lines 76 - 99, The
AlignmentConfig.type union currently allows unsupported persisted values
("multiplicative" and "gate"); update the AlignmentConfig interface
(specifically the mode field on AlignmentConfig) to restrict the union to only
shipped runtimes (e.g., "informational" | "asymmetric") so persisted configs
cannot contain unsupported modes, and run/describe any needed migration or
validation to handle existing records using the old values (modify the
AlignmentConfig.mode type and add a conversion/validation path in any
deserialization/DB read logic).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/hooks/typecheck-on-stop.sh:
- Around line 24-27: The current git diff used to populate changed_ts (the git
diff --name-only --diff-filter=ACMR HEAD ...) excludes deletions, so removed
.ts/.tsx files won't trigger the typecheck; update the diff-filter to include
deleted files (e.g., change ACMR to ACMRD) in the command that assigns
changed_ts so deletions are considered when deciding to run the typecheck hook.

In `@apps/web/db/schema/contributor-penalties.ts`:
- Around line 53-56: Add a DB CHECK constraint to enforce consistency between
issuedBy (contributorPenaltyIssuedByEnum "issued_by") and issuedByUserId
("issued_by_user_id"): when issuedBy indicates a human issuer require
issuedByUserId IS NOT NULL, and when it indicates a CI workflow require
issuedByUserId IS NULL; implement this as a table-level CHECK combining both
cases (e.g. (issued_by = '<human-value>' AND issued_by_user_id IS NOT NULL) OR
(issued_by = '<ci_value>' AND issued_by_user_id IS NULL)), and add the same
constraint where the second occurrence of issuedBy/issuedByUserId is defined
(lines ~81-84) so both schema objects enforce the rule.

In `@CLAUDE.md`:
- Line 103: Update the documentation line about proxy.ts to match repo
guidelines: remove any claim that `proxy.ts` mints per-request CSP nonces (the
`x-nonce` behavior) and instead state that `proxy.ts` (Next 16 renamed
middleware) is for redirects only; clarify that CSP/nonce generation belongs to
the app layouts or request handlers and that auth must be revalidated inside
every protected Server Component, Server Action, and route handler (referenced
symbols: proxy.ts, x-nonce, next.config.ts, script-src, protected Server
Component, Server Action, route handler).

In `@docs/shipshape-design.md`:
- Around line 143-145: The design doc uses two different pacing config keys
(perWindowPrCap and perDayMergedPrCap) which will cause divergence; pick one
canonical key (e.g., perDayMergedPrCap) and replace all occurrences of the
alternate (perWindowPrCap) throughout the document so the contract and follow-up
implementation reference the same identifier; ensure related keys
(perPrCommitCap, draftQueueEnabled) remain unchanged and update any
cross-references or sections (§6.5 and lines ~749-751) to use the chosen
canonical symbol.
- Around line 986-987: Remove the stale "14-day window" phrasing in the table
row that currently reads "Existing project owners caught off-guard by 14-day
window" and replace it with language that reflects the frozen invariants in
SPEC.md and §11 (e.g., state there is no grace/claim/migration window and owners
must explicitly unpause to resume), ensuring the table entry and any nearby text
do not imply a migration or grace period and instead reference the explicit
non-goal of claim/grace windows from SPEC.md to keep documentation consistent.

In `@docs/shipshape-implementation-plan.md`:
- Line 37: The fenced dependency-graph block is missing a language tag; update
the opening code fence for that dependency-graph block (the triple-backtick
block that renders the dependency graph) to include a language specifier such as
"text" (i.e., change the opening ``` to ```text) so markdown-lint and docs
checks pass, leaving the closing ``` unchanged.
- Around line 143-145: The documentation defines a mismatched config key —
perWindowPrCap is introduced but later backfilled as perDayMergedPrCap — causing
ambiguous wiring and broken defaults; update the docs and any wiring notes so
the same identifier is used consistently (choose either perWindowPrCap or
perDayMergedPrCap), update all references in Phase 4 (wiring) and the backfill
section to that single chosen symbol, and ensure the described default value and
merging behavior are documented under that unified key so implementation code
(where wiring reads e.g. perWindowPrCap) and any backfill scripts (which
currently reference perDayMergedPrCap) align.

---

Nitpick comments:
In `@apps/web/db/schema/pending-draft-reviews.ts`:
- Around line 47-48: Add a DB CHECK constraint to ensure terminal-state/close
metadata consistency: for the table definition containing columns state,
closedAt, and closeReason, add a constraint (e.g.
chk_close_metadata_consistency) that enforces "if state is a terminal/closed
value then closedAt IS NOT NULL AND closeReason IS NOT NULL, and if state is not
terminal then closedAt IS NULL AND closeReason IS NULL"; implement the same
check on the other similar table/block referenced (lines 58–62). Name the
constraints clearly and use the table's state enum/values to detect terminal
states when building the boolean expression.

In `@apps/web/db/schema/projects.ts`:
- Around line 76-99: The AlignmentConfig.type union currently allows unsupported
persisted values ("multiplicative" and "gate"); update the AlignmentConfig
interface (specifically the mode field on AlignmentConfig) to restrict the union
to only shipped runtimes (e.g., "informational" | "asymmetric") so persisted
configs cannot contain unsupported modes, and run/describe any needed migration
or validation to handle existing records using the old values (modify the
AlignmentConfig.mode type and add a conversion/validation path in any
deserialization/DB read logic).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8e76cc82-403e-4ade-b984-b36a5067c843

📥 Commits

Reviewing files that changed from the base of the PR and between 262ccc6 and 67e241e.

📒 Files selected for processing (18)
  • .claude/hooks/typecheck-on-stop.sh
  • .claude/settings.json
  • .claude/skills/audit/SKILL.md
  • .claude/skills/spike/SKILL.md
  • .gitignore
  • CLAUDE.md
  • SPEC.md
  • apps/web/db/migrations/0018_awesome_boom_boom.sql
  • apps/web/db/migrations/meta/0018_snapshot.json
  • apps/web/db/migrations/meta/_journal.json
  • apps/web/db/schema/contributor-penalties.ts
  • apps/web/db/schema/contributors.ts
  • apps/web/db/schema/index.ts
  • apps/web/db/schema/organizations.ts
  • apps/web/db/schema/pending-draft-reviews.ts
  • apps/web/db/schema/projects.ts
  • docs/shipshape-design.md
  • docs/shipshape-implementation-plan.md

Comment thread .claude/hooks/typecheck-on-stop.sh
Comment thread apps/web/db/schema/contributor-penalties.ts
Comment thread CLAUDE.md Outdated
Comment thread docs/shipshape-design.md
Comment on lines +143 to +145
perPrCommitCap: number; // NEW; default 5
perWindowPrCap: number; // NEW; default 10 — see §6.5
draftQueueEnabled: boolean; // NEW; default true — see §6.5

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Unify pacing config key naming across the design contract.

Line 144 uses perWindowPrCap, while Line 750 switches to perDayMergedPrCap. Keep one canonical key or the follow-up implementation will diverge.

Suggested correction
-  - `perDayMergedPrCap = 10`
+  - `perWindowPrCap = 10`

Also applies to: 749-751

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/shipshape-design.md` around lines 143 - 145, The design doc uses two
different pacing config keys (perWindowPrCap and perDayMergedPrCap) which will
cause divergence; pick one canonical key (e.g., perDayMergedPrCap) and replace
all occurrences of the alternate (perWindowPrCap) throughout the document so the
contract and follow-up implementation reference the same identifier; ensure
related keys (perPrCommitCap, draftQueueEnabled) remain unchanged and update any
cross-references or sections (§6.5 and lines ~749-751) to use the chosen
canonical symbol.

Comment thread docs/shipshape-design.md Outdated
Comment thread docs/shipshape-implementation-plan.md Outdated
Comment thread docs/shipshape-implementation-plan.md
Dexploarer and others added 11 commits April 29, 2026 14:29
Adds the cross-cutting agent + scope-discipline files that the shipshape
spine work depends on:

- SPEC.md — frozen invariants and explicit non-goals (SOL-only,
  community-only, Bags handles Incorporation, no grace windows). Scaled
  from past sessions where invented-adjacent scope caused full reverts.
- CLAUDE.md — adds Product Model Constraints, Debugging Priority, and
  Scope Discipline sections; documents cacheComponents / cacheLife
  profiles, two-super-admin cosign gate, embed/ route realm.
- .claude/skills/audit — production-readiness audit skill that
  reports against SPEC.md invariants without editing.
- .claude/skills/spike — pre-flight architecture validator that
  prototypes risky assumptions before feature work.
- .claude/settings.json + .claude/hooks/typecheck-on-stop.sh — Stop
  hook that runs typecheck only when uncommitted .ts/.tsx files exist.
- .gitignore — share project-level .claude config, keep settings.local
  per-developer; ignore /spikes/ scratch dir.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Single source of truth for the v1 contribution-economy product spine.
Captures every decision from the design conversation:

- Three-PR plan (spine + dogfood / launch gate + install kit / dashboard
  configurator) with scope and rough sizing.
- Scoring v1 formula — adds populated reviews, merges, substantive review
  score, co-authored credit; wires applyTimeDecay; per-PR commit cap;
  fixed self-merge dampener; squash-merge attribution fix.
- Alignment v1 — asymmetric multiplier (×0.5 / ×1.0 / ×1.2) with the
  full signal hierarchy (issue links, label matches, file area matches,
  CI signals, closed-without-merge penalty).
- Shipshape generator (static rules) + logbook generator (live state),
  with public routes at /r/[org]/[repo]/{shipshape,logbook}.md.
- CI ingest endpoint with GitHub Actions OIDC primary auth and HMAC
  fallback, four event types (test_result, coverage_delta, bundle_delta,
  perf_delta).
- Schema additions: extended ScoreInputs with ci sub-object,
  alignmentConfig, agentRoutingPolicy, attributionType,
  routesToContributorId.
- Existing-project policy: 14-day migration window with notifications
  then auto-pause if shipshape not installed.
- Launch gate (PR 2 preview): pending_install → awaiting_pr_merge →
  ready_to_launch → launched, with admin permission re-verification at
  every transition.
- Risks + mitigations + test plan + commit-by-commit landing order.

Implementation does not start until this doc is approved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds §6.5 capturing the pacing mechanism: honest contributors can ship
unlimited PRs, but score earns are capped per period with carry-forward,
and over-cap or deferred drafts auto-route through a no-penalty review.

Mechanism in two parts:

1. Per-window scoring cap (default 10 merged PRs). Excess merged PRs
   score 0 this period but their counts persist; if those PRs merge in
   future periods, they earn full credit then. This is the burnout-safe
   property — a contributor who shipped 15 PRs and rested for 30 days
   still earns from the over-cap PRs in whatever period they merged.

2. Draft auto-review (cron every 6h). Drafts older than
   draftAutoReviewDelayHours (default 24h) run cheap heuristics:
   mergeable + no-conflict + substantive + aligned + author-active.
   All five → elevate (un-draft, request maintainer review).
   Any failure → no-penalty close (gitshipt:no-penalty-close label,
   excluded from closedWithoutMerge alignment penalty).

Non-intrusive: no PR is auto-converted to draft. gitshipt-bot posts a
single guidance comment when a contributor exceeds cap, explaining their
options. A gitshipt/score-status check shows cap state but never blocks.

Edge case decisions made:

- Stale auto-elevated PR: 14d auto-close with 7d reminder ping. Same
  no-penalty alignment treatment.
- Re-elevation abuse: a PR closed-low-value cannot be re-elevated unless
  the head commit is materially different (passes trivial filter +
  touches priority area or ≥10 substantive lines + content-hash differs
  from prior reject). Rate-limited to 1 reattempt per PR per period.
- Maintainer manual review beats auto-review. Approve → un-draft and
  score normally. Request-changes → pause auto-review timer until next
  push.
- gitshipt:wip opt-out label pauses the timer for max 30d (or one full
  window). Re-applying after expiry requires a material commit.

Schema additions (§5.3 ScoringConfig):
- perWindowPrCap: number (default 10)
- draftQueueEnabled: boolean (default true)
- draftAutoReviewDelayHours: number (default 24)

Alignment v1 amendments (§8.1):
- closedWithoutMerge denominator/sum excludes no-penalty closures
- auto_elevated_merged: +0.05 alignment bonus when an elevated PR
  later merges

New workflow: processDraftQueue (apps/web/workflows/processDraftQueue.ts).
Updated implementation order to land it after CI ingest and before docs
honesty fix.

Shipshape output gains §9 "Pacing and the draft queue" so contributors
read the rules from the runbook itself.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…sory

Pivots from elaborate algorithmic prevention to maintainer-driven
catch-at-the-PR enforcement, plus opt-in community verification for
the human-element layer algorithm cannot reach.

§6.5 simplification:
- Drops re-elevation material-commit rules, content-hash normalization,
  gitshipt:wip cap, self-opened-issue/self-applied-label preflight
  hardening. These are arms races we will lose.
- Keeps three 1-liners that have no exploitable surface: head-SHA delta
  on review-iteration bonus, linkedOpenIssue author rule, co-author
  noreply email verification.

§6.6 NEW — Penalty system:
- Maintainer slash commands parsed from PR comments via webhook handler:
  /gitshipt flag (yellow, ×0.5 alignment for 30d), /gitshipt ban (red,
  no earnings 90d + alignment forced to 0), /gitshipt clear,
  /gitshipt no-penalty-close, /gitshipt confirm-quality,
  /gitshipt verify-community.
- Repeat-red within 12 months auto-escalates to black (permaban,
  two-super-admin cosign to lift).
- Schema: contributor_penalties table with issued_by enum
  (human_maintainer | ci_workflow), evidence_url required on CI-issued.
- Enforcement at compute/dispatch time, never stored on score.
- PR check gitshipt/penalty-status (informational, never blocks CI).
- Idempotency on (project, contributor, pr, action) within 5min window.

§6.7 NEW — Community verification (advised, not enforced):
- projects.communityLinks (discord/telegram/x/custom) declared by owner.
- contributors.communityVerified flag with audit trail.
- Optional payoutConfig.communityVerifiedThresholdLamports gates payouts
  above threshold on community verification. Below threshold: paid
  normally. Unverified above threshold: held in escrow until verified
  or threshold waived.
- shipshape.md publishes community section so contributors know the
  rules. GitShipt does not run, host, or attest to community verification.

§10 CI ingest extension:
- Two new event types: penalty_issue (level: yellow|red, evidenceUrl
  required) and penalty_clear. CI cannot issue black.
- Rate limit: > 10% of active contributors flagged in window pauses
  CI penalty events and notifies project owner. Defends against
  runaway CI rules.

§17.2 NEW — Acknowledged "oh well" limitations:
- Maintainer-author collusion via alt accounts.
- Cross-repo single-human arbitrage.
- Owners writing biased CI rules.
- Community channels GitShipt does not run.
- Substance-checking AI reviews (v2).

These attacks exist, are not solvable algorithmically, and are explicitly
documented in SPEC.md non-goals. v1 mitigates via the social layer but
does not pretend to defeat the human element. The 80/15/5 rule: algorithm
80%, maintainers 15%, accept 5%.

SPEC.md updated with the same five acknowledged limitations under a new
"Acknowledged limitations — accepted, not defended" section.

Implementation order updated to land penalty system after alignment v1
and community verification after penalties.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fleshes out §13 from a thin "format adapters" placeholder into the full
install-kit specification. When an owner installs the GitShipt App on a
repo, the App opens a single PR (chore: install GitShipt) containing
everything the spine needs:

Required (locked, can't opt out):
- shipshape.md at repo root
- .github/workflows/gitshipt-report.yml (CI ingest source)

Strongly advised (default on, opt-out at install time):
- README.md badge insertion
- CLAUDE.md adapter (additive — append, don't overwrite)
- .cursor/rules/gitshipt.md (single new file)
- .github/copilot-instructions.md adapter (additive)
- AGENTS.md pointer (additive)

Additive merge logic uses gitshipt:start/gitshipt:end marker comments so
re-running install (or auto-update PRs as rules change) replaces just
the managed section, never overwriting unrelated content. Idempotent.

README badge:
[![GitShipt — tracked](https://gitshipt.com/badge/r/{org}/{repo}.svg)]
   (https://gitshipt.com/r/{org}/{repo})
Served from app/badge/r/[org]/[repo].svg/route.ts. v1 is static
"tracked"; v2 can render live KPIs. Insertion places after first H1,
appending to existing badges block if present. Searching GitHub for
"gitshipt.com/badge" surfaces all tracked repos — analytics + social
proof.

Owner install-time checklist UI; choices stored on
projects.installPreferences so re-runs honor them.

GitHub App permissions documented (Contents r/w, Pull Requests r/w,
Metadata r, Issues w for the penalty label management from §6.6).

Implementation order updated: badge SVG route lands in PR 1 (needed
before any badge resolves); README badge insertion + install kit
mechanics in PR 2 as already planned.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ritance

Adds §14.5 Organizations capturing the v1 org model. Two decisions made:

1. v1 scope: org-as-namespace + default-config inheritance + read-only
   org dashboard + cross-repo contributor visibility. Org-level tokens,
   org-level shipshape, org-wide slash commands, and auto-sync defer to
   v2 (each needs its own design pass).

2. Inheritance behavior: snapshot at project creation. When org defaults
   change, existing projects keep their snapshotted config. No
   auto-sync, no surprise mutations to live payouts. Owner can
   re-apply explicitly via the dashboard.

New schema:
- organizations table (gh_org_id, gh_login, default_*_config columns,
  installed_at/by, primary_wallet_address, audit timestamps)
- projects.gh_org_id soft FK

Permissions:
- Editing org defaults: GitHub-org admin role + wallet-linked
- Org dashboard: any contributor with project-level access
- Cosign reserved for future irreversible org-level actions

§17.1 deferred capabilities updated with the four org-level v2 items.
SPEC.md acknowledged-limitations updated with explicit org-coordination
non-goals so the system is honest about what's per-repo.

Implementation order grows by one item: org dashboard + settings page
in PR 1 (cheap once schema is in).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lands the data spine for the contribution-economy upgrade. Reflects
every decision in docs/shipshape-design.md across §5, §6.5–6.7, §8,
§10, §12, and §14.5.

New tables:
- organizations — per-org default config templates (§14.5). Snapshotted
  into projects at creation; no auto-sync, predictable behavior.
- contributor_penalties — yellow/red/black flags issued by maintainers
  via slash commands or CI workflows (§6.6). CHECK constraint enforces
  evidence_url for ci_workflow-issued rows.
- pending_draft_reviews — state for the §6.5 auto-review pipeline:
  pending_review → elevated_awaiting_maintainer → elevated_reminded
  (7d) → stale_closed (14d). Or no_penalty_closed if heuristics fail,
  or merged_via_maintainer if a human approves.

contributors gains:
- inputs default rewritten with v1 zeros (merges, reviewSubstantiveScore,
  coAuthored, ci.*) so old code that omits them resolves cleanly. v1
  fields are TS-optional during transition.
- attribution_type enum (human / agent_routed / bot_treasury /
  agent_unrouted) for §6.1 operator routing.
- routes_to_contributor_id soft FK to operator's row.
- community_verified flag + audit trail (verified_by, verified_at) for
  §6.7 optional payout-threshold gate.
- gh_user_id index for §14.5 cross-repo aggregation.

projects gains:
- gh_org_id soft FK for org namespace (§14.5).
- alignment_config jsonb (§8) — asymmetric-multiplier defaults.
- agent_routing_policy jsonb (§6.1) — operator bindings + share cap.
- community_links jsonb (§6.7) — Discord/Telegram/X/custom.
- install_preferences jsonb (§13.4) — per-file install opt-in/out.
- launch_state enum (§12) — pending_install / awaiting_pr_merge /
  ready_to_launch / launched / failed.
- install_runbook_pr_url / _number / installer_gh_user_id for the
  install-PR webhook flow.

Backfill:
- Existing projects with status in ('live','paused','killed',
  'simulated_live') get launch_state = 'launched' so they are not
  gated by the §12 state machine when PR 2 ships. Draft and
  launch_configured projects keep launch_state = 'pending_install'
  so they go through the new flow.

Migration safety:
- ENUMs in DO blocks (matches 0011 pattern) — rerun-safe on partial
  failure.
- All ADD COLUMN, CREATE TABLE, CREATE INDEX guarded with IF NOT
  EXISTS — idempotent.
- FK constraints inline in CREATE TABLE so they only run when the
  table is being created.

Verification:
- bun run typecheck across @repo/lib, @repo/shared, @repo/ui, apps/web
  — clean.
- bun run db:generate after edits — "No schema changes, nothing to
  migrate" confirms 0018_snapshot.json matches schema files.
- Migration body manually scoped to spine work only; auto-generated
  drift from missing 0003-0017 snapshots removed by hand.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Companion to docs/shipshape-design.md. Lays out a commit-by-commit
landing strategy where each commit is self-contained, independently
testable, and preserves v0 behavior until the explicit wiring commit
lands.

Six phases, 32 commits on top of the schema migration already shipped:

- Phase 1 (12 commits): pure foundations. lib/scoring/v1, alignment,
  penalty, pacing; lib/github/indexer/{reviews,squash,coauthor,trivial};
  lib/agents/{shipshape,logbook}; lib/badge/svg; lib/orgs/inheritance.
  No behavior change; each export is independently testable.
- Phase 2 (5 commits): public routes + dashboards. Badge SVG route,
  shipshape/logbook/runbook.json public routes, contributor cross-repo
  view, org dashboard read-only, org settings display. Renders DB data;
  v0 projects unaffected.
- Phase 3 (3 commits): ingest. Slash-command parser + webhook handler,
  CI ingest endpoint with OIDC + HMAC. Writes to DB; scoring still
  ignores until Phase 4.
- Phase 4 (5 commits): wiring. computeLeaderboard dispatches v0/v1 by
  formulaVersion; indexProjectDeltas calls new helpers when v1;
  alignment + pacing in computeLeaderboard; penalty enforcement in
  computeLeaderboard + executePayout; community-verified payout gate.
  v1 behavior turns on for projects flagged v1; v0 unchanged.
- Phase 5 (3 commits): async + UX. processDraftQueue cron workflow,
  gh-bot over-cap comment + score-status check, gh-bot penalty-status
  check.
- Phase 6 (4 commits): dogfood + docs honesty. GitShipt own shipshape.md,
  gitshipt-report.yml, README badge, /docs/page.tsx update to publish v1
  truth.

Includes a dependency graph, reviewable batching suggestions (4 review
chunks), out-of-scope items deferred to PR 2/3, per-phase verification
commands, and pinned answers to five open implementation questions so
they don't keep reappearing per-commit.

This plan supersedes the loose order at the bottom of shipshape-design.md
section 18 and adds the v0-protection invariant + atomicity discipline
that earlier sessions repeatedly violated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The earlier draft had a 14-day grace period for existing v0 projects to
install shipshape before payouts paused. That's a grace window, which
SPEC.md already forbids ("A 7-day or N-day grace/claim window..." was
already an explicit non-goal). This was inconsistent with our own rules.

Replaced with a single SQL backfill (0019_promote_v0_to_v1.sql, lands as
commit 44 after all Phase 4 wiring is verified) that flips every existing
project from v0 to v1 in one cut-over:

- formulaVersion: "v0" → "v1" on all rows
- v1 config defaults populated: perPrCommitCap, perDayMergedPrCap,
  draftQueueEnabled, draftAutoReviewDelayHours, trivialCommitFilter,
  substantiveReviewFloor, plus v1 weights for merges,
  reviewSubstantiveScore, coAuthored
- alignmentConfig / agentRoutingPolicy / communityLinks remain NULL.
  v1 code paths short-circuit when null (alignment forced to
  informational mode, routing defaults to treasury, no community
  surface). Owners populate at their pace via PR 3 configurator.

The v0 dispatch path stays in code as a per-project kill-switch — admin
can flip a single project back to v0 by editing scoringConfig directly
if a critical v1 bug surfaces. Nothing auto-sets it.

Implementation plan updated:
- Phase 4.5 added as a single-commit phase (commit 44) for the backfill,
  between wiring (Phase 4) and async/UX (Phase 5).
- Phase 5 commits renumbered 45–47, Phase 6 commits 48–51 (was 47–50).
- "Migration window enforcement" removed from PR 2 out-of-scope list.
- Review chunk C grows by one commit (9 instead of 8) to include the
  cut-over.

SPEC.md gets the 14-day window listed as a previously-considered-and-
rejected mechanism alongside the contributor grace window, so future
sessions can't accidentally re-introduce the same shape.

Design doc §2 (non-goals) updated to be explicit: existing-project
grace windows of any kind are forbidden.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two changes from review feedback on the design + schema PR:

1. .claude/hooks/typecheck-on-stop.sh — graceful bun-not-in-PATH guard
   (gemini-code-assist and codereviewbot-ai). When `bun` is missing the
   hook now prints a clear "bun not in PATH; skipping typecheck" message
   listing the changed TS files, then exits 0 instead of producing a
   tangled error mixed with shell plumbing.

2. apps/web/db/schema/contributor-penalties.ts — declare the
   contributor_penalties_ci_evidence_required CHECK constraint via the
   Drizzle `check()` helper (gemini-code-assist medium-priority finding).
   The constraint was hand-written into 0018_awesome_boom_boom.sql but
   absent from the schema, so the next db:generate would have flagged
   it as drift and tried to drop it. Mirrored declaration prevents that.

   The `check()` helper from drizzle-orm/pg-core is supported in
   drizzle-orm@0.45.2 (already pinned). Patched 0018_snapshot.json to
   include the constraint so the schema-snapshot pair stays consistent
   and `bun run db:generate` reports "No schema changes, nothing to
   migrate".

Other review comments triaged but not actioned in this commit:

- Backfill of launch_state to 'launched' for live/paused/killed/
  simulated_live: matches design intent in shipshape-design.md §11
  (existing projects past install go directly to launched, regardless
  of operational status). Will respond inline on the PR.
- text-bool 'excluded' column on contributors: pre-existing schema
  decision, not introduced by this PR.
- JSONB query-perf concern on organizations defaults: acceptable
  tradeoff for the per-org-template inheritance pattern.
- pending_draft_reviews state-transition enforcement at DB level: app
  enforces (workflow updates row only along defined transitions);
  DB-level state machine would be over-engineering for v1.
- tierWeights sum-to-1.0 invariant: pre-existing PayoutConfig type,
  enforced in the launch-config Server Action, not at the schema layer.

bun run typecheck clean, bun run db:generate confirms snapshot matches
schema (no migration produced).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two MEDIUM-priority polish items from gemini-code-assist:

1. .claude/hooks/typecheck-on-stop.sh: the previous
   `cd "$(git rev-parse --show-toplevel 2>/dev/null)" || exit 0`
   silently swallowed the not-in-a-git-repo case — `cd ""` is a no-op
   in bash, so the `|| exit 0` never fired and the rest of the hook
   ran in whatever directory the user was sitting in. Now resolves
   the repo root into a variable, exits 0 when empty, then cd's.

2. 0018_awesome_boom_boom.sql backfill: added
   `AND launch_state <> 'launched'` to the UPDATE so it only touches
   rows that still need promotion. No-op on a clean run (column was
   just added with default 'pending_install'), but scopes
   partial-retry / re-applied migrations to the actual delta —
   cheaper, idempotent, self-documenting.

Smoke: hook exits 0 with no .ts changes; bun run typecheck clean
across all 4 packages.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Dexploarer Dexploarer force-pushed the feat/shipshape-spine-v1 branch from 67e241e to 6f08ad9 Compare April 29, 2026 18:50

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

♻️ Duplicate comments (4)
docs/shipshape-design.md (2)

986-987: ⚠️ Potential issue | 🟠 Major

Risk table still reintroduces a forbidden 14-day window.

This conflicts with §11’s immediate cut-over and the frozen no-grace-window rules.

🧩 Suggested fix
-| Existing project owners caught off-guard by 14-day window | Multiple notifications (in-app, email, dashboard banner); explicit unpause is one-click |
+| Existing project owners caught off-guard by immediate v0→v1 cut-over | Pre-deploy comms + in-app notice + rollback via per-project `formulaVersion: "v0"` kill-switch |
As per coding guidelines: "`SPEC.md` is the frozen list of invariants and explicit non-goals."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/shipshape-design.md` around lines 986 - 987, The risk table row
introducing an "Existing project owners caught off-guard by 14-day window"
violates the frozen invariant in SPEC.md and §11's immediate
cut-over/no-grace-window rule; remove or replace the "14-day window" phrasing in
the table (the offending table row text) so it reflects immediate cut-over
behavior and the frozen no-grace-window policy, and update the mitigation column
to list immediate notifications (in-app, email, dashboard banner) and require an
explicit one-click unpause—ensure the docs reference SPEC.md/§11 as the
authoritative invariant.

143-145: ⚠️ Potential issue | 🟠 Major

Unify the pacing config key name across the document.

perWindowPrCap and perDayMergedPrCap are both used; keeping both will create wiring/backfill ambiguity.

🧩 Suggested fix (one canonical key)
-  - `perDayMergedPrCap = 10`
+  - `perWindowPrCap = 10`

Also applies to: 749-751

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/shipshape-design.md` around lines 143 - 145, The document uses two
different pacing keys (perWindowPrCap and perDayMergedPrCap) which will cause
ambiguity; pick one canonical key name and replace all occurrences (including
the instances at lines referenced and the other occurrence around 749-751) so
the config keys are consistent—e.g., choose either perWindowPrCap or
perDayMergedPrCap, update the definition block (where perPrCommitCap,
perWindowPrCap, draftQueueEnabled are declared) and update every reference
across the doc to that single name, and ensure any explanatory notes (like “see
§6.5”) reflect the chosen canonical key.
docs/shipshape-implementation-plan.md (1)

37-83: ⚠️ Potential issue | 🟡 Minor

Add a language tag to the dependency-graph fenced block.

This still triggers markdown lint (MD040).

🧩 Suggested fix
-```
+```text
    (DONE)  18: schema migration  ──┐
@@
                                           └──────────────────────┘
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/shipshape-implementation-plan.md around lines 37 - 83, The fenced
dependency-graph block starting with "(DONE) 18: schema migration ──┐" is
missing a language tag which triggers MD040; update the opening triple-backtick
fence to include a language (e.g., add "text" so the fence reads ```text) so the
block is explicitly tagged and Markdown lint stops flagging it.


</details>

</blockquote></details>
<details>
<summary>.claude/hooks/typecheck-on-stop.sh (1)</summary><blockquote>

`26-26`: _⚠️ Potential issue_ | _🟡 Minor_

**Include deleted `.ts/.tsx` files in the trigger condition.**

A deleted TS file can break imports, but `--diff-filter=ACMR` ignores `D`, so this hook can skip typecheck when it should run.

 
<details>
<summary>🔧 Suggested fix</summary>

```diff
-changed_ts=$(git diff --name-only --diff-filter=ACMR HEAD 2>/dev/null | grep -E '\.(ts|tsx)$' || true)
+changed_ts=$(git diff --name-only --diff-filter=ACMRD HEAD 2>/dev/null | grep -E '\.(ts|tsx)$' || true)
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In @.claude/hooks/typecheck-on-stop.sh at line 26, The hook's changed_ts
detection (variable changed_ts) uses git diff --diff-filter=ACMR which omits
deleted files (D) so deleted .ts/.tsx that break imports won't trigger
typecheck; update the git diff invocation to include deleted files (e.g. change
--diff-filter=ACMR to --diff-filter=ACMRD or remove the filter) so deleted
.ts/.tsx are captured by the grep and cause the hook to run.
```

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🤖 Prompt for all review comments with AI agents</summary>

Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/skills/audit/SKILL.md:

  • Around line 63-80: The markdown audit report template in
    .claude/skills/audit/SKILL.md uses an unlabeled code fence which triggers MD040;
    update the opening triple-backtick fence that wraps the template block (the one
    before "## Audit — ") to include a language label such as "text" (i.e.,
    change totext) so the fence is labeled and the MD040 warning is
    resolved; leave the closing fence as-is and ensure other fences in the file
    follow the same pattern if present.

In @.claude/skills/spike/SKILL.md:

  • Around line 55-70: The markdown fenced code block in the SKILL.md spike report
    template is missing a language tag and triggers MD040; update the fenced block
    that begins with "# Spike report — " to use a language tag (e.g.,
    add text instead of ) so the linter stops flagging it—ensure the opening
    fence for the template is changed and the closing fence remains ``` to keep the
    block intact.

In @apps/web/db/migrations/0019_awesome_boom_boom.sql:

  • Around line 216-217: Edit the backfill comment that currently reads "The
    14-day shipshape migration window (§11)..." in the migration comment block and
    remove or replace the "14-day shipshape migration window" wording so it no
    longer implies a migration window; keep the rest of the comment context but
    ensure it aligns with SPEC.md invariants and the no-grace/no-migration-window
    contract (i.e., delete the phrase or rewrite to state there's no migration
    window).
  • Around line 106-108: The CHECK constraint concedes empty strings; update the
    constraint "contributor_penalties_ci_evidence_required" so that when "issued_by"
    = 'ci_workflow' the "evidence_url" is not only non-null but also not blank (e.g.
    require evidence_url IS NOT NULL AND trim(evidence_url) <> '' or
    length(trim(evidence_url)) > 0) to reject empty/whitespace-only URLs while
    preserving the existing issued_by logic.

In @apps/web/db/schema/projects.ts:

  • Around line 147-150: Add a state-dependent CHECK constraint on the projects
    table to require launch metadata when state advances: update the
    schema/migration in apps/web/db/schema/projects.ts to add a CHECK that when
    state IN ('awaiting_pr_merge','ready_to_launch','launched') then
    installerGhUserId IS NOT NULL AND installPrNumber IS NOT NULL AND
    installPrHeadSha IS NOT NULL (and/or any other PR metadata columns used). Apply
    the same constraint placement where the projects table is defined/altered (also
    for the section referenced around lines 225-230) so the DB rejects rows that
    enter those states without the required metadata.
  • Around line 147-158: The schema is defaulting launchState to "pending_install"
    globally which creates impossible combos for non-install projects (e.g., status
    = "tracked"); remove the global default on launchState in the project schema (do
    not set pending_install in pgEnum creation alone), and instead either make
    launchState nullable until the installer owns the row or add an explicit CHECK
    constraint that enforces valid (status, launchState) pairs (e.g., only allow
    pending_install/awaiting_pr_merge/ready_to_launch/failed when status indicates
    an installable project); update any insert paths to explicitly set launchState
    where appropriate (references: projectLaunchStateEnum, launchState, status) and
    apply the same change where this enum/default appears later in the file (lines
    mentioned in review).

In @docs/shipshape-design.md:

  • Line 234: There are unlabeled fenced code blocks using just which trigger markdownlint MD040; update each unlabeled block (the bare occurrences) to
    include a language identifier such as text (or an appropriate language like json/```yaml) so the linter passes; search for the naked fence tokens and
    replace them with labeled fences for the blocks referenced in the comment.

Duplicate comments:
In @.claude/hooks/typecheck-on-stop.sh:

  • Line 26: The hook's changed_ts detection (variable changed_ts) uses git diff
    --diff-filter=ACMR which omits deleted files (D) so deleted .ts/.tsx that break
    imports won't trigger typecheck; update the git diff invocation to include
    deleted files (e.g. change --diff-filter=ACMR to --diff-filter=ACMRD or remove
    the filter) so deleted .ts/.tsx are captured by the grep and cause the hook to
    run.

In @docs/shipshape-design.md:

  • Around line 986-987: The risk table row introducing an "Existing project
    owners caught off-guard by 14-day window" violates the frozen invariant in
    SPEC.md and §11's immediate cut-over/no-grace-window rule; remove or replace the
    "14-day window" phrasing in the table (the offending table row text) so it
    reflects immediate cut-over behavior and the frozen no-grace-window policy, and
    update the mitigation column to list immediate notifications (in-app, email,
    dashboard banner) and require an explicit one-click unpause—ensure the docs
    reference SPEC.md/§11 as the authoritative invariant.
  • Around line 143-145: The document uses two different pacing keys
    (perWindowPrCap and perDayMergedPrCap) which will cause ambiguity; pick one
    canonical key name and replace all occurrences (including the instances at lines
    referenced and the other occurrence around 749-751) so the config keys are
    consistent—e.g., choose either perWindowPrCap or perDayMergedPrCap, update the
    definition block (where perPrCommitCap, perWindowPrCap, draftQueueEnabled are
    declared) and update every reference across the doc to that single name, and
    ensure any explanatory notes (like “see §6.5”) reflect the chosen canonical key.

In @docs/shipshape-implementation-plan.md:

  • Around line 37-83: The fenced dependency-graph block starting with "(DONE)
    18: schema migration ──┐" is missing a language tag which triggers MD040;
    update the opening triple-backtick fence to include a language (e.g., add "text"
    so the fence reads ```text) so the block is explicitly tagged and Markdown lint
    stops flagging it.

</details>

<details>
<summary>🪄 Autofix (Beta)</summary>

Fix all unresolved CodeRabbit comments on this PR:

- [ ] <!-- {"checkboxId": "4b0d0e0a-96d7-4f10-b296-3a18ea78f0b9"} --> Push a commit to this branch (recommended)
- [ ] <!-- {"checkboxId": "ff5b1114-7d8c-49e6-8ac1-43f82af23a33"} --> Create a new PR with the fixes

</details>

---

<details>
<summary>ℹ️ Review info</summary>

<details>
<summary>⚙️ Run configuration</summary>

**Configuration used**: defaults

**Review profile**: CHILL

**Plan**: Pro

**Run ID**: `85fab804-6046-449b-9a32-a343670f64bd`

</details>

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 67e241eb183546e37dd34f6bca0898b0af9bf0f8 and 6f08ad9d4adc5ae4b21375886db287fe00b6004e.

</details>

<details>
<summary>📒 Files selected for processing (18)</summary>

* `.claude/hooks/typecheck-on-stop.sh`
* `.claude/settings.json`
* `.claude/skills/audit/SKILL.md`
* `.claude/skills/spike/SKILL.md`
* `.gitignore`
* `CLAUDE.md`
* `SPEC.md`
* `apps/web/db/migrations/0019_awesome_boom_boom.sql`
* `apps/web/db/migrations/meta/0019_snapshot.json`
* `apps/web/db/migrations/meta/_journal.json`
* `apps/web/db/schema/contributor-penalties.ts`
* `apps/web/db/schema/contributors.ts`
* `apps/web/db/schema/index.ts`
* `apps/web/db/schema/organizations.ts`
* `apps/web/db/schema/pending-draft-reviews.ts`
* `apps/web/db/schema/projects.ts`
* `docs/shipshape-design.md`
* `docs/shipshape-implementation-plan.md`

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (5)</summary>

* .claude/settings.json
* apps/web/db/schema/index.ts
* apps/web/db/migrations/meta/_journal.json
* apps/web/db/schema/contributor-penalties.ts
* apps/web/db/schema/pending-draft-reviews.ts

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (3)</summary>

* .gitignore
* apps/web/db/schema/organizations.ts
* apps/web/db/schema/contributors.ts

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Comment thread .claude/skills/audit/SKILL.md Outdated
Comment thread .claude/skills/spike/SKILL.md Outdated
Comment thread apps/web/db/migrations/0020_shipshape_spine_v1.sql
Comment on lines +216 to +217
-- when PR 2 ships. The 14-day shipshape migration window (§11) handles the
-- runbook side separately.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove stale migration-window wording from the backfill comment.

The “14-day shipshape migration window” note contradicts the no-grace/no-migration-window contract and can mislead future maintainers.

As per coding guidelines: "SPEC.md is the frozen list of invariants and explicit non-goals."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/db/migrations/0019_awesome_boom_boom.sql` around lines 216 - 217,
Edit the backfill comment that currently reads "The 14-day shipshape migration
window (§11)..." in the migration comment block and remove or replace the
"14-day shipshape migration window" wording so it no longer implies a migration
window; keep the rest of the comment context but ensure it aligns with SPEC.md
invariants and the no-grace/no-migration-window contract (i.e., delete the
phrase or rewrite to state there's no migration window).

Comment on lines +147 to +150
/**
* Project launch state machine (shipshape design doc §12). Every transition
* re-verifies the launching user's GitHub admin permission on the target
* repo; the gate fails closed.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Enforce launch metadata once the state machine advances.

The state-machine contract says later transitions re-verify the launching GitHub admin and depend on the install PR, but the schema allows awaiting_pr_merge / ready_to_launch / launched rows with installerGhUserId and PR metadata still null. That creates unrecoverable rows the launch flow cannot safely resume or validate. A state-dependent CHECK in the schema/migration would close that gap.

Also applies to: 225-230

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/db/schema/projects.ts` around lines 147 - 150, Add a state-dependent
CHECK constraint on the projects table to require launch metadata when state
advances: update the schema/migration in apps/web/db/schema/projects.ts to add a
CHECK that when state IN ('awaiting_pr_merge','ready_to_launch','launched') then
installerGhUserId IS NOT NULL AND installPrNumber IS NOT NULL AND
installPrHeadSha IS NOT NULL (and/or any other PR metadata columns used). Apply
the same constraint placement where the projects table is defined/altered (also
for the section referenced around lines 225-230) so the DB rejects rows that
enter those states without the required metadata.

Comment thread apps/web/db/schema/projects.ts
Comment thread docs/shipshape-design.md Outdated
@SYMBaiEX SYMBaiEX merged commit 536d2b7 into SYMBaiEX:main Apr 29, 2026
6 of 7 checks passed
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