From Documents to Code: How We Implement at StratoNext
The first post in this series described how we design software at StratoNext, requirements first, architecture second, every decision recorded, every assumption tracked. This post is about what happens next: implementation.
The short version is that implementation becomes straightforward when the design is already done. The developer agent does not invent architecture. It does not make assumptions. It reads what was designed and builds it.
The Problem With Implementing Without Context
Most implementation agents, and most developers, start from a ticket or a brief description and fill in the gaps themselves. They make assumptions about data models, naming conventions, error handling, and architectural boundaries. Some of those assumptions are right. Many are not. The ones that are wrong become bugs, refactors, or silent deviations from the intended design.
The deeper problem is that these gaps are invisible. Nobody knows an assumption was made until something breaks.
The Software Developer Skill
We give our implementation agent a second skill: software-developer.
Where the software-architect skill governs design, the software-developer skill governs implementation. It enforces the project tech stack, naming conventions, file structure, testing requirements, linting, CI/CD setup, and documentation standards, consistently, across every repository, every session.
The skill is not a style guide that developers are expected to remember. It is a structured definition the agent reads before writing a single line of code. The agent does not freelance.
The First Step Is Always Reading
Before writing any code, the skill instructs the agent to read, in order:
1. AGENTS.md repository-specific rules and entry points
2. docs/architecture/ the relevant architecture document(s)
3. docs/architecture/decisions/ the ADRs that govern the design
4. requirements.md the requirement being satisfied
5. docs/architecture/assumptions/ open AARs that may affect implementation
6. _AGENT/OPEN_POINTS.md unresolved items in the area being touched
This is not optional ceremony. It is the mechanism that prevents the agent from inventing what was already decided. By the time the agent writes the first line of code, it knows:
- What the component is supposed to do and why
- What it must not do (constraints from the architecture)
- What decisions were already made and why alternatives were rejected
- What assumptions are still open and may affect the implementation
- What was already deferred in this part of the codebase, and why
The architecture documents produced by the software-architect skill are the primary input. They describe the component’s responsibility, its interactions, its constraints, and the ADRs (Architecture Decision Records) that govern its design. The agent reads these as a specification, not as background reading.
No Assumptions, No Surprises
Consider implementing the ApprovalService. The architecture document tells the agent:
- ApprovalService receives credential requests from AgentService, persists approval records, invokes the RiskClassifier, evaluates auto-approval rules, and drives credential generation via CredentialBrokerService
- Only one credential request may be active per task at a time; new requests invalidate prior pending ones
- Credentials are generated at fetch time, not at approval time
- The approval record transitions through:
pending→approved→consumed(orexpired/invalidated) - All operations are authorization-checked via AuthorizationService before business logic runs
The agent does not decide any of this. It reads it. The implementation follows directly from the specification. If something is unclear, the agent asks, it does not guess.
Open AARs (Architecture Assumption Records) are equally important. AAR-006 from the first post, the one covering cross-agent credential fetch, is still open: the security model has not been formally analyzed. The agent sees this before implementing the fetch endpoint and can flag it rather than silently implementing a potentially insecure flow.
The Tech Stack Is Non-Negotiable
The skill enforces the tech stack without discussion:
Backend services C# on .NET
Agents Python 3.13, uv, AWS Strands
Frontend React SPA, Vite, pnpm
The agent does not propose alternatives. It does not introduce new dependencies without justification. It does not use npm when pnpm is required, or var when an explicit type is available. These rules are in the skill, and the skill is what the agent follows.
Every repository gets the same structure, the same Taskfile tasks, the same CI/CD pipeline, the same required files. A developer or agent opening any StratoNext repository for the first time knows exactly where to look and exactly what commands to run.
task compile type-check or compile
task build produce a deployable artifact
task run run locally
task test run unit tests, exit non-zero on failure
task lint run linter, zero warnings required
The Naming Convention Is Enforced
Component naming follows our opinionated conventions, enforced by the skill:
Service- callable components (AgentService,TaskService,ApprovalService)Engine- event and timer-driven components (CoreEngine,A2AEngine)Repository- persistence components (TaskRepository,WorkflowRepository)
File and directory names are always lowercase kebab-case. No exceptions. The agent does not create AgentService.cs in a folder called Services, it creates agent-service.cs in src/agent-service/.
Every Repository Is Agent-Ready
Every repository the developer skill produces includes an AGENTS.md file. This file describes the purpose of the repository, the key entry points, and the local rules. It is the first thing any agent reads when working in that repository.
The skill keeps AGENTS.md alive. After every implementation, the agent reviews what was built and identifies anything worth sharing with future agents: non-obvious patterns, reusable utilities, important constraints, or gotchas discovered during implementation. It proposes each candidate entry before writing:
Agent: "I found the following worth adding to AGENTS.md:
The ApprovalService uses a distributed lock keyed on task_id to enforce
the single-active-request constraint. Any code that creates approval
records must acquire this lock first.
Shall I add it?"
Nothing is written without explicit confirmation. The result is a living document that grows more useful with every implementation cycle, without accumulating noise.
This means the codebase is self-describing for agents. A new agent joining the project reads AGENTS.md, reads the architecture documents, reads the requirements, and has everything it needs to contribute without making assumptions.
The Two Skills Together
The architect skill and the developer skill are designed to work in sequence:
software-architect skill software-developer skill
| |
requirements.md --> reads requirements.md
ARCH-XXX docs --> reads architecture docs
ADR records --> reads decisions
AAR records --> reads open assumptions
| |
design is done implementation begins
The architect skill ensures the design is complete before implementation starts. The developer skill ensures the implementation follows the design without deviation. Neither skill leaves room for the agent to fill gaps with guesses.
When the Design and Reality Diverge
Sometimes the implementation hits something the architecture did not anticipate. A dependency behaves differently than expected. A model is missing a field. An external API requires something not present in the design.
The skill handles this explicitly, and it splits the response in two depending on whether the issue blocks correct implementation.
Blocking is when the spec cannot be followed as written, conflicts with the architecture, or needs a decision nobody has documented. The agent does not silently pick an alternative and move on. It adds a TODO|CLARIFICATION NEEDED comment at the exact location in the code and stops.
// TODO|CLARIFICATION NEEDED: ARCH-004 specifies that CredentialBrokerService generates
// credentials at fetch time, but the AWS STS SDK requires a role ARN that is not
// present in the current ApprovalRecord model. Proceeding requires either adding
// role_arn to the approval record or sourcing it from a different location.
// Stopping here pending developer input.
The developer sees exactly where the problem is, what the conflict is, and what decision is needed. The architecture can be updated, the assumption can be resolved, and implementation continues with the correct design.
Non-blocking is everything else: a deliberate simplification, a deferred edge case, a known gap, a reasonable default that still deserves a second look. Stopping the session for each of these would make the agent useless. Swallowing them silently is how technical debt becomes invisible. So the agent does neither. It appends one entry to _AGENT/OPEN_POINTS.md and keeps going.
## 2026-07-13, TaskRepository.list()
Pagination is offset-based, not cursor-based. Fine at current row counts;
revisit if a table this queries passes ~100k rows.
Each entry carries a date, a location, and a line or two on what was deferred and why. There is no status field to maintain: an entry is open until someone deletes it. The agent lists every entry it added in its summary, and deletes the ones this session resolved as part of the same change.
The result is that deviations are never silent and debt is never hidden. Blocking issues stop the work. Non-blocking ones are written down where the next agent will read them, before it touches the same code.
Design Before Code
The reason this works is simple: by the time the developer agent opens a code editor, every significant decision has already been made. The architecture document is the specification. The ADRs are the rationale. The AARs are the known risks. The requirements are the acceptance criteria.
The agent’s job is to translate a complete, well-reasoned design into working code, not to design while coding. That separation is what makes agent-driven implementation reliable.