[object Object]

← back to Cli Printing Press

feat(cli): reimplementation gate in absorb scoring and dogfood (#238)

00b9a0d42498d7f810ffc0ef4bac3c06db27ecab · 2026-04-22 10:24:01 -0700 · Matt Van Horn

Adds two enforcement points that together refuse to ship CLIs whose
novel-feature commands synthesize API responses locally instead of
calling the API they claim to wrap.

Absorb scoring gains a Kill Check #6 that rejects reimplementation
candidates before they enter the feature list. Dogfood gains a new
ReimplementationCheck that scans every built novel-feature handler
for the two legitimate data sources - the generated API client or
the local SQLite store - and flags any handler file showing neither.

The check exempts local-data commands (stale, bottleneck, health,
reconcile) via the store signal, and treats an empty RunE body as
a distinct flag so the reviewer knows to implement vs. rewrite.

Suspicious findings surface as WARN in the dogfood verdict so they
are visible in the shipcheck block without hard-blocking early
iterations. AGENTS.md documents the rule under a new
Anti-Reimplementation subsection.

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 00b9a0d42498d7f810ffc0ef4bac3c06db27ecab
Author: Matt Van Horn <mvanhorn@users.noreply.github.com>
Date:   Wed Apr 22 10:24:01 2026 -0700

    feat(cli): reimplementation gate in absorb scoring and dogfood (#238)
    
    Adds two enforcement points that together refuse to ship CLIs whose
    novel-feature commands synthesize API responses locally instead of
    calling the API they claim to wrap.
    
    Absorb scoring gains a Kill Check #6 that rejects reimplementation
    candidates before they enter the feature list. Dogfood gains a new
    ReimplementationCheck that scans every built novel-feature handler
    for the two legitimate data sources - the generated API client or
    the local SQLite store - and flags any handler file showing neither.
    
    The check exempts local-data commands (stale, bottleneck, health,
    reconcile) via the store signal, and treats an empty RunE body as
    a distinct flag so the reviewer knows to implement vs. rewrite.
    
    Suspicious findings surface as WARN in the dogfood verdict so they
    are visible in the shipcheck block without hard-blocking early
    iterations. AGENTS.md documents the rule under a new
    Anti-Reimplementation subsection.
    
    Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
    Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 AGENTS.md                                          |  18 ++
 internal/pipeline/dogfood.go                       |  47 ++-
 internal/pipeline/reimplementation_check.go        | 236 ++++++++++++++
 internal/pipeline/reimplementation_check_test.go   | 348 +++++++++++++++++++++
 skills/printing-press/references/absorb-scoring.md |   1 +
 5 files changed, 636 insertions(+), 14 deletions(-)

diff --git a/AGENTS.md b/AGENTS.md
index 7b1bc70d..46f2d72d 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -15,6 +15,24 @@ This repo contains **the machine** (generator, templates, binary, skills) that p
 
 **When adding a capability that affects scoring**, update the scorer in the same change. The goal is not to inflate scores — it's to ensure the scorer accurately reflects the capability. If you add composed cookie auth but the scorer only recognizes Bearer/Basic, it will penalize a correctly-implemented CLI. Fix the scorer to recognize the new pattern, not to give it a free pass.
 
+### Anti-Reimplementation
+
+A printed CLI wraps an API. It does not replace the API. Novel-feature commands must call the real endpoint, or read from the local SQLite store populated by sync. Anything in between is a reimplementation, and reimplementations are worse than the API they pretend to replace.
+
+Concretely, the generator and review loop reject:
+
+- Hand-rolled response builders that return constants, hardcoded JSON, or struct literals shaped like an API payload
+- Endpoint stubs that return `"OK"` or a canned success message without calling the client
+- Aggregations computed in-process when the API has an aggregation endpoint
+- Enum mappings and reference data synthesized locally when the API returns them
+
+Two carve-outs are legitimate:
+
+- Commands that read from the generated `internal/store` package to join or query sync'd data (the `stale`, `bottleneck`, `health`, `reconcile` family). These are local-data commands, not fake API calls.
+- Commands that cache an API response in the store after calling it. Presence of both a client call and a store call is fine.
+
+The rule is enforced in two places. The absorb manifest has a Kill Check (see `skills/printing-press/references/absorb-scoring.md`) that rejects reimplementation candidates before they enter the feature list. Dogfood runs `reimplementation_check` over every built novel-feature command and flags any handler file that shows neither a client call nor a store access.
+
 ## Build, Test & Lint
 
 ```bash
diff --git a/internal/pipeline/dogfood.go b/internal/pipeline/dogfood.go
index a448d8f3..b3aff31c 100644
--- a/internal/pipeline/dogfood.go
+++ b/internal/pipeline/dogfood.go
@@ -19,20 +19,21 @@ import (
 )
 
 type DogfoodReport struct {
-	Dir                string                   `json:"dir"`
-	SpecPath           string                   `json:"spec_path,omitempty"`
-	Verdict            string                   `json:"verdict"`
-	PathCheck          PathCheckResult          `json:"path_check"`
-	AuthCheck          AuthCheckResult          `json:"auth_check"`
-	DeadFlags          DeadCodeResult           `json:"dead_flags"`
-	DeadFuncs          DeadCodeResult           `json:"dead_functions"`
-	PipelineCheck      PipelineResult           `json:"pipeline_check"`
-	ExampleCheck       ExampleCheckResult       `json:"example_check"`
-	WiringCheck        WiringCheckResult        `json:"wiring_check"`
-	NovelFeaturesCheck NovelFeaturesCheckResult `json:"novel_features_check"`
-	TestPresence       TestPresenceResult       `json:"test_presence"`
-	NamingCheck        NamingCheckResult        `json:"naming_check"`
-	Issues             []string                 `json:"issues"`
+	Dir                   string                      `json:"dir"`
+	SpecPath              string                      `json:"spec_path,omitempty"`
+	Verdict               string                      `json:"verdict"`
+	PathCheck             PathCheckResult             `json:"path_check"`
+	AuthCheck             AuthCheckResult             `json:"auth_check"`
+	DeadFlags             DeadCodeResult              `json:"dead_flags"`
+	DeadFuncs             DeadCodeResult              `json:"dead_functions"`
+	PipelineCheck         PipelineResult              `json:"pipeline_check"`
+	ExampleCheck          ExampleCheckResult          `json:"example_check"`
+	WiringCheck           WiringCheckResult           `json:"wiring_check"`
+	NovelFeaturesCheck    NovelFeaturesCheckResult    `json:"novel_features_check"`
+	ReimplementationCheck ReimplementationCheckResult `json:"reimplementation_check"`
+	TestPresence          TestPresenceResult          `json:"test_presence"`
+	NamingCheck           NamingCheckResult           `json:"naming_check"`
+	Issues                []string                    `json:"issues"`
 }
 
 // NamingCheckResult reports non-canonical command verbs and flag names
@@ -202,6 +203,7 @@ func RunDogfood(dir, specPath string, opts ...DogfoodOption) (*DogfoodReport, er
 	report.ExampleCheck = checkExamples(dir)
 	report.WiringCheck = checkWiring(dir)
 	report.NovelFeaturesCheck = checkNovelFeatures(dir, cfg.researchDir)
+	report.ReimplementationCheck = checkReimplementation(dir, cfg.researchDir)
 	report.TestPresence = checkTestPresence(dir)
 	report.NamingCheck = checkNamingConsistency(dir)
 	report.Issues = collectDogfoodIssues(report, spec != nil)
@@ -1240,6 +1242,13 @@ func deriveDogfoodVerdict(report *DogfoodReport, hasSpec bool) string {
 	if len(report.NovelFeaturesCheck.Missing) > 0 {
 		return "WARN"
 	}
+	if len(report.ReimplementationCheck.Suspicious) > 0 {
+		// Hand-rolled responses and empty-stub commands surface as WARN so
+		// they're visible in the shipcheck block without hard-blocking a
+		// run that may legitimately be in an early iteration. Reviewers
+		// upgrade to FAIL when the pipeline integrity check also drops.
+		return "WARN"
+	}
 	return "PASS"
 }
 
@@ -1292,6 +1301,16 @@ func collectDogfoodIssues(report *DogfoodReport, hasSpec bool) []string {
 			report.NovelFeaturesCheck.Planned,
 			strings.Join(report.NovelFeaturesCheck.Missing, ", ")))
 	}
+	if len(report.ReimplementationCheck.Suspicious) > 0 {
+		parts := make([]string, 0, len(report.ReimplementationCheck.Suspicious))
+		for _, f := range report.ReimplementationCheck.Suspicious {
+			parts = append(parts, fmt.Sprintf("%s (%s) — %s", f.Command, f.File, f.Reason))
+		}
+		issues = append(issues, fmt.Sprintf("%d/%d novel features look reimplemented: %s",
+			len(report.ReimplementationCheck.Suspicious),
+			report.ReimplementationCheck.Checked,
+			strings.Join(parts, "; ")))
+	}
 	if len(report.TestPresence.MissingTests) > 0 {
 		issues = append(issues, fmt.Sprintf("pure-logic packages with no tests: %s",
 			strings.Join(report.TestPresence.MissingTests, ", ")))
diff --git a/internal/pipeline/reimplementation_check.go b/internal/pipeline/reimplementation_check.go
new file mode 100644
index 00000000..6d1ac0d9
--- /dev/null
+++ b/internal/pipeline/reimplementation_check.go
@@ -0,0 +1,236 @@
+package pipeline
+
+import (
+	"os"
+	"path/filepath"
+	"regexp"
+	"strings"
+)
+
+// ReimplementationCheckResult flags novel-feature commands whose handler
+// files show no sign of calling the generated API client and no sign of
+// consulting the local store. Those are the two legitimate data sources
+// for a printed CLI; a novel feature that uses neither is synthesizing
+// behavior - a hand-rolled response, a constant return, or an empty
+// stub that pretends to do work.
+//
+// The check is structural, not semantic. It does not parse Go or try to
+// understand what the function returns. It looks at the file that
+// implements the command and asks: does any part of this file call
+// through the generated client package, or read from the generated
+// store package? If neither, the command is flagged.
+//
+// SQLite-derived commands (stale, bottleneck, health, reconcile) pass
+// this check because their files call `store.Open` and consult the
+// store package. That is correctly a local-data command, not a
+// hand-rolled response.
+type ReimplementationCheckResult struct {
+	// Checked is the number of built novel-feature commands inspected.
+	Checked int `json:"checked"`
+	// ExemptedViaStore is the number of commands that passed the check
+	// by consulting the local store package (SQLite-derived features).
+	ExemptedViaStore int `json:"exempted_via_store"`
+	// Suspicious is the list of commands whose files show no client
+	// call and no store access - the candidate hand-rolled responses.
+	Suspicious []ReimplementationFinding `json:"suspicious,omitempty"`
+	// Skipped is true when the check could not run (no research dir, no
+	// novel features, no matchable files).
+	Skipped bool `json:"skipped,omitempty"`
+}
+
+// ReimplementationFinding names a single suspicious command and gives
+// the reviewer enough context to act: the command as planned, the file
+// that implements it, and the specific reason it was flagged.
+type ReimplementationFinding struct {
+	Command string `json:"command"`
+	File    string `json:"file"`
+	Reason  string `json:"reason"`
+}
+
+// These signals are intentionally string-match and regex based. AST
+// parsing would be more precise but adds scope and dependency weight
+// this check does not need at v1. If false-positive pressure grows,
+// we upgrade to AST in a follow-up.
+
+var (
+	// storeImportRe catches the generated store package import in any
+	// printed CLI: `"<module>/internal/store"`. The module prefix varies
+	// per CLI, so we anchor on the shared trailing path segment.
+	storeImportRe = regexp.MustCompile(`"[^"]*/internal/store"`)
+
+	// storeCallRe catches direct calls into the store package - the most
+	// common shape is `store.Open(...)`. Agent-authored commands that
+	// read sync'd data consistently use this entry point.
+	storeCallRe = regexp.MustCompile(`\bstore\.[A-Z]\w*\s*\(`)
+
+	// clientImportRe catches the generated client package import:
+	// `"<module>/internal/client"`. Not every client call requires this
+	// (the command can go through `flags.newClient`), but its presence
+	// is a reliable positive signal.
+	clientImportRe = regexp.MustCompile(`"[^"]*/internal/client"`)
+
+	// clientCallRe catches the canonical API-call entry points used by
+	// generated endpoint commands and by well-behaved novel features:
+	// `flags.newClient()` and direct `http.Get/Post/Do` calls. Commands
+	// that build their own raw http.Request also land here.
+	clientCallRe = regexp.MustCompile(`\b(flags\.newClient\s*\(|http\.(Get|Post|NewRequest|Do)\s*\(|c\.Do\s*\(|c\.Get\s*\(|c\.Post\s*\()`)
+
+	// trivialBodyRe catches the classic empty-stub shape used when an
+	// agent wires a Cobra command but never implements it:
+	//
+	//   RunE: func(cmd *cobra.Command, args []string) error { return nil }
+	//
+	// with optional whitespace variations. If the command's handler body
+	// is only this, no other signal is going to save it.
+	trivialBodyRe = regexp.MustCompile(`RunE:\s*func\s*\(\s*cmd\s*\*cobra\.Command\s*,\s*args\s*\[\]string\s*\)\s*error\s*\{\s*return\s+nil\s*\}`)
+)
+
+// checkReimplementation scans the files that implement built novel
+// features and classifies each. A command whose file calls the store
+// package is exempt. A command whose file calls the client is fine. A
+// command whose file does neither - or whose handler is a trivial stub
+// - is flagged for review.
+//
+// When researchDir is empty or research.json has no novel features the
+// check returns Skipped. This mirrors the behavior of checkNovelFeatures:
+// if there is nothing planned, there is nothing to validate.
+func checkReimplementation(cliDir, researchDir string) ReimplementationCheckResult {
+	if researchDir == "" {
+		return ReimplementationCheckResult{Skipped: true}
+	}
+	research, err := LoadResearch(researchDir)
+	if err != nil || len(research.NovelFeatures) == 0 {
+		return ReimplementationCheckResult{Skipped: true}
+	}
+
+	cliFilesDir := filepath.Join(cliDir, "internal", "cli")
+	entries, err := os.ReadDir(cliFilesDir)
+	if err != nil {
+		return ReimplementationCheckResult{Skipped: true}
+	}
+
+	// Build a quick index: leaf command name -> candidate file paths.
+	// A file is a candidate for a command if it contains `Use: "<leaf>"`.
+	// We only index non-infrastructure, non-test source files.
+	leafToFiles := map[string][]string{}
+	fileContent := map[string]string{}
+	infra := map[string]bool{
+		"helpers.go": true,
+		"root.go":    true,
+		"doctor.go":  true,
+		"auth.go":    true,
+	}
+	useLineRe := regexp.MustCompile(`Use:\s*"([^"\s]+)`)
+	for _, e := range entries {
+		name := e.Name()
+		if e.IsDir() || !strings.HasSuffix(name, ".go") {
+			continue
+		}
+		if strings.HasSuffix(name, "_test.go") {
+			continue
+		}
+		if infra[name] {
+			continue
+		}
+		data, readErr := os.ReadFile(filepath.Join(cliFilesDir, name))
+		if readErr != nil {
+			continue
+		}
+		content := string(data)
+		fileContent[name] = content
+		for _, m := range useLineRe.FindAllStringSubmatch(content, -1) {
+			leaf := m[1]
+			leafToFiles[leaf] = append(leafToFiles[leaf], name)
+		}
+	}
+
+	result := ReimplementationCheckResult{}
+	for _, nf := range research.NovelFeatures {
+		leaf := lastPathSegment(commandPath(nf.Command))
+		if leaf == "" {
+			continue
+		}
+		files := leafToFiles[leaf]
+		if len(files) == 0 {
+			// No file owns this command leaf. checkNovelFeatures already
+			// reports this as Missing; no double-count here.
+			continue
+		}
+		// When a leaf maps to multiple files (rare), inspect all of them
+		// and take the most favorable classification - any single file
+		// with the right signals vindicates the command.
+		result.Checked++
+		finding, exempt, ok := classifyReimplementation(files, fileContent)
+		if exempt {
+			result.ExemptedViaStore++
+			continue
+		}
+		if !ok {
+			finding.Command = nf.Command
+			result.Suspicious = append(result.Suspicious, finding)
+		}
+	}
+
+	if result.Checked == 0 {
+		result.Skipped = true
+	}
+
+	return result
+}
+
+// classifyReimplementation returns the best classification across the
+// set of files that implement a single command. The rules, in order:
+//
+//  1. If any file shows a store signal, the command is exempted as a
+//     local-SQLite feature. Return (_, true, true).
+//  2. If any file shows a client signal, the command is fine. Return
+//     (_, false, true).
+//  3. Otherwise the command is suspicious. Return a ReimplementationFinding
+//     naming the primary file and a reason. Return (finding, false, false).
+//
+// The trivial-body regex is consulted only when rule 3 fires, to pick
+// between "empty stub" and "hand-rolled response" as the reason.
+func classifyReimplementation(files []string, fileContent map[string]string) (ReimplementationFinding, bool, bool) {
+	hasClient := false
+	hasTrivialBody := false
+	primaryFile := files[0]
+	for _, f := range files {
+		content, ok := fileContent[f]
+		if !ok {
+			continue
+		}
+		if hasStoreSignal(content) {
+			return ReimplementationFinding{File: f}, true, true
+		}
+		if hasClientSignal(content) {
+			hasClient = true
+		}
+		if trivialBodyRe.MatchString(content) {
+			hasTrivialBody = true
+		}
+	}
+	if hasClient {
+		return ReimplementationFinding{File: primaryFile}, false, true
+	}
+	reason := "hand-rolled response: no API client call, no store access"
+	if hasTrivialBody {
+		reason = "empty body: no implementation"
+	}
+	return ReimplementationFinding{File: primaryFile, Reason: reason}, false, false
+}
+
+func hasStoreSignal(content string) bool {
+	return storeImportRe.MatchString(content) || storeCallRe.MatchString(content)
+}
+
+func hasClientSignal(content string) bool {
+	return clientImportRe.MatchString(content) || clientCallRe.MatchString(content)
+}
+
+func lastPathSegment(path string) string {
+	_, leaf := splitCommandPath(path)
+	if leaf != "" {
+		return leaf
+	}
+	return path
+}
diff --git a/internal/pipeline/reimplementation_check_test.go b/internal/pipeline/reimplementation_check_test.go
new file mode 100644
index 00000000..35dd9e76
--- /dev/null
+++ b/internal/pipeline/reimplementation_check_test.go
@@ -0,0 +1,348 @@
+package pipeline
+
+import (
+	"encoding/json"
+	"os"
+	"path/filepath"
+	"strings"
+	"testing"
+)
+
+// seedReimplementationFixture writes a minimal generated-CLI directory
+// layout at root: internal/cli/<file>.go for each named command, and a
+// research.json at pipelineDir listing the novel features. Returns
+// (cliDir, pipelineDir) for passing into checkReimplementation.
+func seedReimplementationFixture(t *testing.T, files map[string]string, novel []NovelFeature) (string, string) {
+	t.Helper()
+
+	root := t.TempDir()
+	cliFilesDir := filepath.Join(root, "internal", "cli")
+	if err := os.MkdirAll(cliFilesDir, 0o755); err != nil {
+		t.Fatalf("mkdir cli: %v", err)
+	}
+	for name, content := range files {
+		if err := os.WriteFile(filepath.Join(cliFilesDir, name), []byte(content), 0o644); err != nil {
+			t.Fatalf("write %s: %v", name, err)
+		}
+	}
+
+	pipelineDir := filepath.Join(root, "pipeline")
+	if err := os.MkdirAll(pipelineDir, 0o755); err != nil {
+		t.Fatalf("mkdir pipeline: %v", err)
+	}
+	research := ResearchResult{NovelFeatures: novel}
+	data, err := json.MarshalIndent(research, "", "  ")
+	if err != nil {
+		t.Fatalf("marshal research: %v", err)
+	}
+	if err := os.WriteFile(filepath.Join(pipelineDir, "research.json"), data, 0o644); err != nil {
+		t.Fatalf("write research.json: %v", err)
+	}
+	return root, pipelineDir
+}
+
+// Happy path: a novel-feature command that calls the generated client
+// and transforms its response passes both the kill check and the dogfood
+// scan. Nothing is flagged.
+func TestCheckReimplementation_CallsClient_Passes(t *testing.T) {
+	files := map[string]string{
+		"digest.go": `package cli
+
+import "github.com/spf13/cobra"
+
+func newDigestCmd(flags *rootFlags) *cobra.Command {
+	return &cobra.Command{
+		Use: "digest",
+		RunE: func(cmd *cobra.Command, args []string) error {
+			c, err := flags.newClient()
+			if err != nil { return err }
+			_ = c
+			return nil
+		},
+	}
+}
+`,
+	}
+	cliDir, pipelineDir := seedReimplementationFixture(t, files, []NovelFeature{
+		{Name: "Digest", Command: "digest"},
+	})
+
+	got := checkReimplementation(cliDir, pipelineDir)
+	if got.Skipped {
+		t.Fatalf("expected non-skipped result, got Skipped=true")
+	}
+	if got.Checked != 1 {
+		t.Fatalf("Checked: want 1, got %d", got.Checked)
+	}
+	if len(got.Suspicious) != 0 {
+		t.Fatalf("Suspicious: want 0, got %d (%v)", len(got.Suspicious), got.Suspicious)
+	}
+}
+
+// Happy path (exempt): a SQLite-derived command that calls store.Open
+// but never the client is treated as a local-data command and exempted.
+// This is the carve-out that keeps stale/bottleneck/health legitimate.
+func TestCheckReimplementation_StoreOnly_Exempted(t *testing.T) {
+	files := map[string]string{
+		"bottleneck.go": `package cli
+
+import (
+	"github.com/spf13/cobra"
+
+	"example.com/mod/internal/store"
+)
+
+func newBottleneckCmd(flags *rootFlags) *cobra.Command {
+	return &cobra.Command{
+		Use: "bottleneck",
+		RunE: func(cmd *cobra.Command, args []string) error {
+			db, err := store.Open("x.db")
+			_ = db
+			_ = err
+			return nil
+		},
+	}
+}
+`,
+	}
+	cliDir, pipelineDir := seedReimplementationFixture(t, files, []NovelFeature{
+		{Name: "Bottleneck", Command: "bottleneck"},
+	})
+
+	got := checkReimplementation(cliDir, pipelineDir)
+	if got.Checked != 1 {
+		t.Fatalf("Checked: want 1, got %d", got.Checked)
+	}
+	if got.ExemptedViaStore != 1 {
+		t.Fatalf("ExemptedViaStore: want 1, got %d", got.ExemptedViaStore)
+	}
+	if len(got.Suspicious) != 0 {
+		t.Fatalf("Suspicious: want 0, got %d", len(got.Suspicious))
+	}
+}
+
+// Error path: a novel-feature command body that returns a constant
+// string with no client calls is flagged with "hand-rolled response."
+func TestCheckReimplementation_ConstantString_Flagged(t *testing.T) {
+	files := map[string]string{
+		"fake.go": `package cli
+
+import "github.com/spf13/cobra"
+
+func newFakeCmd(flags *rootFlags) *cobra.Command {
+	return &cobra.Command{
+		Use: "fake",
+		RunE: func(cmd *cobra.Command, args []string) error {
+			_ = "OK"
+			return nil
+		},
+	}
+}
+`,
+	}
+	cliDir, pipelineDir := seedReimplementationFixture(t, files, []NovelFeature{
+		{Name: "Fake", Command: "fake"},
+	})
+
+	got := checkReimplementation(cliDir, pipelineDir)
+	if len(got.Suspicious) != 1 {
+		t.Fatalf("Suspicious: want 1, got %d", len(got.Suspicious))
+	}
+	f := got.Suspicious[0]
+	if f.Command != "fake" {
+		t.Errorf("Command: want fake, got %s", f.Command)
+	}
+	if !strings.Contains(f.Reason, "hand-rolled response") && !strings.Contains(f.Reason, "empty body") {
+		t.Errorf("Reason should mention hand-rolled response or empty body: %q", f.Reason)
+	}
+}
+
+// Error path: a novel-feature command whose handler returns only a
+// hardcoded struct literal with no client/store signals is flagged.
+// The check cannot know the literal matches a schema, but the absence
+// of any data-source call is enough to surface it for review.
+func TestCheckReimplementation_HardcodedStructLiteral_Flagged(t *testing.T) {
+	files := map[string]string{
+		"ghost.go": `package cli
+
+import (
+	"encoding/json"
+	"os"
+
+	"github.com/spf13/cobra"
+)
+
+func newGhostCmd(flags *rootFlags) *cobra.Command {
+	return &cobra.Command{
+		Use: "ghost",
+		RunE: func(cmd *cobra.Command, args []string) error {
+			out := map[string]any{"id": "42", "status": "ok"}
+			return json.NewEncoder(os.Stdout).Encode(out)
+		},
+	}
+}
+`,
+	}
+	cliDir, pipelineDir := seedReimplementationFixture(t, files, []NovelFeature{
+		{Name: "Ghost", Command: "ghost"},
+	})
+
+	got := checkReimplementation(cliDir, pipelineDir)
+	if len(got.Suspicious) != 1 {
+		t.Fatalf("Suspicious: want 1, got %d", len(got.Suspicious))
+	}
+	if got.Suspicious[0].Command != "ghost" {
+		t.Errorf("Command: want ghost, got %s", got.Suspicious[0].Command)
+	}
+}
+
+// Edge case: a novel-feature command that calls BOTH the API client AND
+// the store passes the check. The store signal is sufficient on its own,
+// but a command that caches API responses locally should not be penalized.
+func TestCheckReimplementation_ClientAndStore_Exempted(t *testing.T) {
+	files := map[string]string{
+		"sync.go": `package cli
+
+import (
+	"github.com/spf13/cobra"
+
+	"example.com/mod/internal/store"
+)
+
+func newSyncCmd(flags *rootFlags) *cobra.Command {
+	return &cobra.Command{
+		Use: "sync",
+		RunE: func(cmd *cobra.Command, args []string) error {
+			c, err := flags.newClient()
+			if err != nil { return err }
+			_ = c
+			db, err := store.Open("x.db")
+			_ = db
+			_ = err
+			return nil
+		},
+	}
+}
+`,
+	}
+	cliDir, pipelineDir := seedReimplementationFixture(t, files, []NovelFeature{
+		{Name: "Sync", Command: "sync"},
+	})
+
+	got := checkReimplementation(cliDir, pipelineDir)
+	if got.ExemptedViaStore != 1 {
+		t.Errorf("ExemptedViaStore: want 1, got %d", got.ExemptedViaStore)
+	}
+	if len(got.Suspicious) != 0 {
+		t.Errorf("Suspicious: want 0, got %d", len(got.Suspicious))
+	}
+}
+
+// Edge case: an empty RunE body is flagged with the distinct "empty
+// body" reason. This is the classic agent-wired-but-unimplemented
+// failure mode; surfacing it with its own reason makes the fix
+// obvious to the reviewer.
+func TestCheckReimplementation_EmptyBody_FlaggedWithDistinctReason(t *testing.T) {
+	files := map[string]string{
+		"stub.go": `package cli
+
+import "github.com/spf13/cobra"
+
+func newStubCmd(flags *rootFlags) *cobra.Command {
+	return &cobra.Command{
+		Use: "stub",
+		RunE: func(cmd *cobra.Command, args []string) error { return nil },
+	}
+}
+`,
+	}
+	cliDir, pipelineDir := seedReimplementationFixture(t, files, []NovelFeature{
+		{Name: "Stub", Command: "stub"},
+	})
+
+	got := checkReimplementation(cliDir, pipelineDir)
+	if len(got.Suspicious) != 1 {
+		t.Fatalf("Suspicious: want 1, got %d", len(got.Suspicious))
+	}
+	if !strings.Contains(got.Suspicious[0].Reason, "empty body") {
+		t.Errorf("Reason should mention empty body: %q", got.Suspicious[0].Reason)
+	}
+}
+
+// Integration: running the check on a fixture with one compliant and
+// one non-compliant novel-feature command produces a report that names
+// only the non-compliant one.
+func TestCheckReimplementation_MixedFixture_ReportsOnlyOffender(t *testing.T) {
+	files := map[string]string{
+		"real.go": `package cli
+
+import "github.com/spf13/cobra"
+
+func newRealCmd(flags *rootFlags) *cobra.Command {
+	return &cobra.Command{
+		Use: "real",
+		RunE: func(cmd *cobra.Command, args []string) error {
+			c, err := flags.newClient()
+			if err != nil { return err }
+			_ = c
+			return nil
+		},
+	}
+}
+`,
+		"fake.go": `package cli
+
+import "github.com/spf13/cobra"
+
+func newFakeCmd(flags *rootFlags) *cobra.Command {
+	return &cobra.Command{
+		Use: "fake",
+		RunE: func(cmd *cobra.Command, args []string) error {
+			return nil
+		},
+	}
+}
+`,
+	}
+	cliDir, pipelineDir := seedReimplementationFixture(t, files, []NovelFeature{
+		{Name: "Real", Command: "real"},
+		{Name: "Fake", Command: "fake"},
+	})
+
+	got := checkReimplementation(cliDir, pipelineDir)
+	if got.Checked != 2 {
+		t.Fatalf("Checked: want 2, got %d", got.Checked)
+	}
+	if len(got.Suspicious) != 1 {
+		t.Fatalf("Suspicious: want 1, got %d (%v)", len(got.Suspicious), got.Suspicious)
+	}
+	if got.Suspicious[0].Command != "fake" {
+		t.Errorf("Offender: want fake, got %s", got.Suspicious[0].Command)
+	}
+}
+
+// Skip path: when research.json is missing the check returns Skipped
+// rather than crashing.
+func TestCheckReimplementation_NoResearchDir_Skipped(t *testing.T) {
+	got := checkReimplementation(t.TempDir(), "")
+	if !got.Skipped {
+		t.Errorf("expected Skipped=true, got %#v", got)
+	}
+}
+
+// Skip path: an empty research.json (no novel features) returns
+// Skipped. Nothing planned means nothing to validate.
+func TestCheckReimplementation_NoNovelFeatures_Skipped(t *testing.T) {
+	root := t.TempDir()
+	pipelineDir := filepath.Join(root, "pipeline")
+	if err := os.MkdirAll(pipelineDir, 0o755); err != nil {
+		t.Fatalf("mkdir: %v", err)
+	}
+	if err := os.WriteFile(filepath.Join(pipelineDir, "research.json"), []byte(`{}`), 0o644); err != nil {
+		t.Fatalf("write: %v", err)
+	}
+	got := checkReimplementation(root, pipelineDir)
+	if !got.Skipped {
+		t.Errorf("expected Skipped=true, got %#v", got)
+	}
+}
diff --git a/skills/printing-press/references/absorb-scoring.md b/skills/printing-press/references/absorb-scoring.md
index 7cb74771..426b52cc 100644
--- a/skills/printing-press/references/absorb-scoring.md
+++ b/skills/printing-press/references/absorb-scoring.md
@@ -65,6 +65,7 @@ see features that can actually ship.
 | **Auth the user doesn't have** | Feature requires write access, OAuth scopes, or paid tiers the user hasn't confirmed | **Gate** behind an auth check, or **cut** if the feature is useless without it. Read-only features using the same auth as other commands are fine. |
 | **Scope creep** | Feature is really an application, not a command. Would take >200 lines to implement, needs a TUI, or requires persistent background processes. | **Descope** to the one-command version. "Dashboard" → "summary stats." "Monitor" → "poll once with --watch." If the one-command version isn't useful, **cut**. |
 | **Verifiability** | Feature can't be tested in dogfood. No way to verify the output is correct without manual inspection or domain expertise. | **Flag** as low-confidence. Keep only if the value is high enough to justify manual QA. |
+| **Reimplementation** | Feature synthesizes API responses locally instead of calling the API. Hand-rolled response builders, hardcoded JSON returned as an "API result," endpoint stubs that return constants, or aggregations computed in-process when the API has an aggregation endpoint. | **Cut or rewrite.** A printed CLI that pretends to call the API is strictly worse than the API call it replaces. The one exception is features that read from the local SQLite store (`stale`, `bottleneck`, `health`, `reconcile`); those are local-data commands, not fake API calls. Dogfood's `reimplementation_check` enforces this at generation time. |
 
 **For each surviving feature, write one sentence proving it's buildable:**
 "This uses [specific API endpoint or local data] to compute [specific output]

← e2ca1825 docs(cli): add 9-phase pipeline contract at docs/PIPELINE.md  ·  back to Cli Printing Press  ·  feat(cli): add live_api_verification scorecard dimension (#2 440f654d →