GenAI Development - From APM to OpenSpec

Version 2 · Last Updated 2026 June 14

Evolved from GenAI Development - From Vibe Coding to APM. That node covers the shift from vibe coding to APM. This node picks up where it left off.

Core Idea

APM was the right instinct but the wrong calibration for part-time, pet project work. A leaner, externally validated spec-driven approach (OpenSpec) produces more natural collaboration with GenAI — more real-time decisions, more token efficiency, and more trust extended to the model. The process feels like steering a conversation rather than enforcing a ruleset.


State of Thinking

APM worked as a mental model but failed in practice because I over-engineered the guardrails. The constraints were too narrow and too numerous — the result was something closer to LLM automation than agentic partnership. The model was doing what I told it to, precisely, which meant I had to anticipate everything upfront. That is expensive to maintain and brittle when the project direction shifts.

OpenSpec changes the dynamic in two ways. First, it is leaner — fewer rules, less overhead re-establishing context, less token cost per exchange. Second, it uses a publicly available framework from a recognised and trusted source, which means I am willing to defer to it rather than enforce my own constraints. The psychological shift matters: I am not relaxing standards, I am trusting a validated external framework instead of a self-written rulebook.

The process now feels like a real-time conversation I am steering. Decisions happen as the work reveals them, rather than being pre-specified. For a part-time project of this scale, that is the right fit — agile enough to respond to what emerges, structured enough to avoid drift.

The UI-first approach on the Helper Buddy rebuild is a separate but compatible decision. UI/UX takes disproportionate time to get right, so tackling it first gives the rest of the build a settled foundation. OpenSpec’s conversational dynamic suits this — the UI surface reveals decisions that no upfront spec could have fully anticipated.

A second project — StoryLab — has now run on OpenSpec long enough to test whether the approach holds up as complexity grows. The framework itself holds: OpenSpec’s propose → apply → archive discipline scaled across roughly three weeks of design-and-build work, and a formalised five-pass verification framework (source tracing, cross-file consistency, developer simulation, routing audit) became load-bearing for that entire stretch.

But two things became visible only at this scale. First, OpenSpec has no native concept of “not yet started” — it tracks what done looks like (specs) and what’s in progress (active changes), but not what’s queued. StoryLab worked around this with a separate sequencing file (CLAUDE-CODE.md) sitting outside OpenSpec’s own structure. Second — and more important — formalising process discipline into a reusable skill (storylab-reviewer) didn’t prevent drift. The same day the skill was packaged, a session deviated from it: checkpoints skipped, fixes applied inline, the design-brief template not consulted. The framework doesn’t drift; applied discipline does, under the same pressures that caused drift before.

This reframes the original open question. It isn’t “does OpenSpec hold up as complexity grows” — the framework holds. It’s “does my discipline in following it hold up” — and the early evidence is that it still requires active maintenance, the same way any process does, regardless of how lean or trusted the framework is.


Thinking Trace

The frustration with APM built slowly. It was not one moment — it was the cumulative friction of feeling like I was managing a very obedient but very literal assistant rather than a thinking partner. Every constraint I had written was doing exactly what I intended, which meant the ceiling of what I could get out of it was exactly what I had imagined upfront. That is not how good collaboration works.

Moving to OpenSpec came from wanting to trust the model more. Using a framework I did not write — one from a recognised source — made that easier. It was not my guardrails anymore, so I was not second-guessing whether they were right. I could focus on the work.

Token efficiency turned out to be a meaningful side benefit. Leaner process means less noise in each exchange. Over a longer project, that compounds — less time re-establishing context, more of each session spent on actual work.

The Claude Design vs Figma Make observation fits the same pattern: Claude Design produces higher-quality output with less post-generation editing needed. Figma Make allows more customisation but requires more intervention. For someone who wants quality output without acting like a UI designer, Claude Design is the better tool. That is essentially the same trade-off as OpenSpec vs APM — less control overhead, more trust in the output.

StoryLab as a second test case:

  • StoryLab adopted OpenSpec specifically for its propose → apply → archive discipline in Claude Code sessions — not for spec management, since the existing docs hierarchy already handled that better. Same “trust the external framework” pattern as the original APM → OpenSpec shift.
  • The CLAUDE-CODE.md workaround for “not yet started” tracking is a real structural gap in OpenSpec, not a misuse of it — worth remembering if OpenSpec is adopted on future projects.
  • The process-drift moment — skipping the storylab-reviewer skill the same day it was created — is humbling. It suggests the earlier APM frustration (“very obedient but very literal”) was never really about APM specifically. Any process, however lean, needs active upkeep under build pressure.

What changed?

v2

Cross-project evidence (StoryLab) confirms OpenSpec holds up at greater complexity, but surfaces two new findings: OpenSpec has no native concept of “not yet started” work, requiring a separate sequencing file; and formalising process discipline into a reusable skill didn’t prevent drift under build pressure — the framework holds, but applied discipline still needs active maintenance.

v1

— skip —

Why it changed?

v2

The original open questions — does OpenSpec hold up as complexity grows, and how to document real-time decisions — could only be answered with a second project at sufficient scale. StoryLab provided that test. The drift finding in particular reframes the earlier APM frustration: it was never really about APM’s specific constraints, but about the general tendency for process discipline to erode under pressure, regardless of framework.

v1

— skip —


Evidence / Signals

  • Helper Buddy rebuild using OpenSpec felt more collaborative and less like issuing directives
  • UI-first approach confirmed: UI/UX is the highest-friction layer; settling it first gives downstream work a stable base
  • Token efficiency is a real, compounding benefit — leaner process means more actual work per session
  • Claude Design output quality noticeably higher than Figma Make for users who do not want to post-edit like a UI designer
  • StoryLab: OpenSpec adopted for Claude Code session discipline, validated across roughly three weeks of build work
  • StoryLab: five-pass verification framework became the de facto documentation standard for the project
  • StoryLab: storylab-reviewer skill packaged to make the review workflow reusable across sessions — then deviated from the same day, evidence that packaging a process doesn’t by itself sustain it
  • StoryLab: CLAUDE-CODE.md introduced as a “not yet started” sequencing layer outside OpenSpec’s native structure

Open Questions

  • How do you maintain process discipline under build pressure once a workflow is formalised — is a periodic re-grounding ritual needed, and what would trigger it?
  • Is the CLAUDE-CODE.md “not yet started” pattern something to set up proactively on future OpenSpec projects, or only once a project reaches a certain size?
  • Is there a project scale at which the lean approach breaks down and tighter structure is needed again? (carried over from v1 — not yet tested)

Connections


Changelog

  • v2 — Model shift: see What/Why changed
  • v1 — Initial node