CodeHero Developer Training — The Autonomous Development Framework (ADF)
Version 1.0 · September 2026 · For CodeHero PRO 4.48 and later
Source: ADF_TRAINING_GUIDE.md · Spec Builder knowledge file: CODEHERO_PLANNING_GUIDE.md
This is the training course for developers who will design, configure and operate CodeHero projects. It teaches the Autonomous Development Framework (ADF): the method CodeHero implements, in which AI agents build, test and document a product from a specification while humans provide only what nobody else can — the business truth, the credentials, and the approvals.
The course is written in English so it can be shared with any team. Trainees may speak Greek or English with the platform; CodeHero replies in the user's language.
How to use this course
Who it is for. Developers, analysts and technical project managers who will:
- extract requirements from a client and turn them into a specification package;
- plan a CodeHero project (tickets, roles, providers, execution settings);
- operate the run (read reports, answer questions, unblock tickets, verify results);
- adapt the framework itself by editing the global context and the project contexts.
Prerequisites. Basic web development knowledge (HTTP, HTML, a backend language, SQL). A working CodeHero PRO installation with at least two active AI providers (one vision-capable). Read the User Guide chapters 2, 6, 8, 9, 11, 13, 14 and 15 first — this course assumes you know the UI.
Structure. Eight modules, in the order the work happens in real life. Each module ends with Exercises; Module 8 is a capstone with a grading rubric. Suggested pace: one module per half-day, capstone on day five.
| Module | Title | You will be able to |
|---|---|---|
| 1 | The framework | Explain the ADF principles and the CodeHero pipeline |
| 2 | Extracting knowledge from the client | Run a Spec Builder interview and produce a specification package |
| 3 | Choosing the stack | Decide PHP vs Node vs Python vs .NET, host vs container, with a written reason |
| 4 | Planning | Turn a package into a serial ticket plan with roles, providers and verification |
| 5 | Execution | Read what the agent does, why it stops, and how to answer it |
| 6 | Customizing the brain | Change global and project contexts safely, and prove the change works |
| 7 | Reaching a working result | Drive a project from first ticket to a verified, documented delivery |
| 8 | Capstone | Do all of the above on a real mini-project and pass the rubric |
Files this course refers to. All paths are relative to the CodeHero source tree (/home/claude/codehero/ on a development machine) or the installed tree (/opt/codehero/ and /etc/codehero/ on a server).
| File | What it is |
|---|---|
config/global-context.md | The global context v6.1 core: the rules every agent gets on every ticket |
config/guides/*.md | The ten on-demand guides of the global context (planning, verify-fix, asking, helper, debugging, frontend, database, build, testing, native): the agent opens one with codehero_get_guide when its trigger fires; the daemon pre-loads the guide of a ticket's kind ([PLAN], [REPLAN], [VERIFY], [FIX], [HELPER], [PEER]) |
config/contexts/<stack>.md | Per-language project contexts (php, node, python, html, react, dotnet, go, java, kotlin, swift, flutter, capacitor, presentation, reporting, api, hybrid) |
docs/CODEHERO_PLANNING_GUIDE.md | The Spec Builder knowledge file (v1.9): how to interview a client and produce a specification package |
config/assistant-planner.md | The in-app "Plan with AI" planner: how a specification (written with the user or imported) becomes a project plus ONE planning ticket |
config/assistant-general.md, assistant-progress.md, assistant-help.md | The other in-app assistant modes |
docs/USER_GUIDE.md | The user manual (UI reference) |
Keep these files open while you study. The course explains them; it does not replace them.
Presentations. The website carries slide decks with speaker notes at presentations/. The first one, The Domain Expert's Software Factory, tells the story of this course to business people with no technical background (interview → approval → build and verification → handoff, with the RepairFlow example of Modules 2–7). Use it to open a client workshop or to brief the domain experts you will interview; the developer material stays here.
PART I — FOUNDATIONS
Module 1 — The framework: what ADF is and how CodeHero implements it
1.1 The one-sentence definition
CodeHero is a complete implementation of that idea: a platform (web UI, daemon, agent, tools, database, containers) plus a written method (the global context, the Spec Builder guide, the planner). This course teaches the method; the User Guide teaches the platform.
1.2 Why a framework at all
Give a strong model a task and it will write code. That is not the problem. The problems appear in the second hour:
- it guesses a business rule (a discount, a permission, a deadline) and builds the wrong product with confidence;
- it claims success ("this should work now") without loading the page;
- it loses its memory when the context window fills, and repeats or contradicts earlier work;
- it breaks something that worked while fixing something else;
- it weakens a protection (turns off validation, hand-inserts a row) to make a test pass;
- two agents working at once edit the same file and corrupt each other's work.
Every rule in ADF exists because one of these happened in a real run. The framework is not theory; it is the accumulated set of guardrails from production deliveries. When you later customize the contexts (Module 6), remember that: change a rule only when you know which failure it prevents.
1.3 The twelve principles
These are the principles behind the global context (config/global-context.md). Learn them by name; the rest of the course refers back to them.
| # | Principle | In one line | Where it lives |
|---|---|---|---|
| P1 | The agent is the only engineer | Nobody helps during the build. The agent understands, plans, builds, tests, documents. | Global §0 |
| P2 | Evidence, not claims | "Done" means a test ran, a page loaded, a row exists, a screenshot was taken. Text saying it works is not done. | Global §0 rule 2, §3, §9 |
| P3 | Never guess a business rule | Technical choices are the agent's job; business rules (money, permissions, workflows, statuses, edge cases) come only from the client. | Global §4 |
| P4 | AI before human | Before a question reaches the client, a second AI on another provider tries to find the answer in the material. Only what is genuinely business-only goes to the human. | Global §4.1, guides/asking.md, guides/helper.md |
| P5 | Safe defaults, and BLOCKED is never PASS | When no answer can come, pick the option that cannot hurt anyone (deny access, keep history, notify, fail closed) and record it. Missing credentials make a part BLOCKED, never "done". | Global §4.1, guides/asking.md |
| P6 | Memory on disk | Context compaction is assumed. Anything not written to the SPEC FILE or the KNOWLEDGE BASE is treated as if it never happened. | Global §6, §7 |
| P7 | Serial by default | One ticket at a time, each with its own sequence_order. Parallel only after the user says yes and a file-ownership analysis proves zero shared files. | Global H6, guides/planning.md §2 |
| P8 | Core slice first | The first milestone is the thinnest end-to-end slice of what the product is for, proven on the preview URL, before any secondary feature. | guides/planning.md step 6 (value order) |
| P9 | Verify without building | A VERIFY ticket on a different provider only checks; findings become one fix ticket for the original builder; a circuit breaker stops endless loops. | guides/verify-fix.md |
| P10 | Never invent facts | No invented config keys, model names, API abilities, credentials or test results. Unknown → probe it, read the real docs, or mark it BLOCKED. | Global H8 |
| P11 | Root cause, never symptom; never weaken protection | Debugging follows a fixed protocol; the WAF, auth, CSRF and validation stay on; a regression jumps the queue. | Global H3, §8 |
| P12 | Self-contained tickets on a "normal server" | Every ticket text carries objective, owned files, contracts, environment facts (localhost only) and a definition of done. The agent never hears the word "container". | Planner rules 6–8, Planning Guide §7.1 |
A useful mental test when you evaluate a plan, a context change or a ticket: which principle does this serve, and which one does it risk?
1.4 The pipeline: from client conversation to verified software
CLIENT (domain expert)
│ interview, one question at a time, four statuses
▼
SPEC BUILDER (claude.ai / ChatGPT project + CODEHERO_PLANNING_GUIDE.md)
│ specification package: header + codehero_environment + run settings
│ + registers (requirements, decisions, dependencies) + ticket plan
▼
PLAN WITH AI (in-app planner, config/assistant-planner.md)
│ writes the specification with the user or imports the package,
│ shows preview → operator confirms → creates project + ONE [PLAN] ticket
▼
PLANNING TICKET ([PLAN] … in PLAN MODE, guides/planning.md, on the real installation)
│ baseline → requirements → contracts → dry run → review rounds → peer check
│ → assigns providers → creates the FIRST PHASE of tickets (last one: [REPLAN])
▼
DAEMON + AGENT (codehero-daemon → HeroAgent or CLI provider, per ticket)
│ global context + project context + ticket → build → verify → report
│ SPEC FILES (.specs/) + KNOWLEDGE BASE (graph) + git snapshots
▼
VERIFY / FIX / REPLAN tickets (different provider, master + ultra)
│
▼
HANDOFF REPORT → operator → client (works+evidence · waiting on you · decided for you · open)
Three "brains" take part, and it matters which one you are talking to:
| Brain | Where | Knowledge it reads | Its job |
|---|---|---|---|
| Spec Builder | Outside CodeHero: a claude.ai or ChatGPT project with the Planning Guide uploaded as knowledge | docs/CODEHERO_PLANNING_GUIDE.md | Interview the client, decide all technical matters, run 50 review rounds, output the package. Names roles and think modes, never providers. |
| In-app planner | CodeHero → AI Assistant → Plan with AI | config/assistant-planner.md + the global context | Write the specification with the user (or import the package), settle everything only a person can decide, show a preview, and after the operator confirms create the project, its environment and ONE planning ticket. It designs no tickets itself. |
| Executing agent | Spawned by the daemon for each ticket (HeroAgent for API providers; Claude Code or Codex CLI for subscription modes) | Global context core + the guide of its kind (auto-loaded) + guides on demand (codehero_get_guide) + language context + project context + environment blocks + ticket text + conversation | Build, verify, document, report. A [PLAN] ticket plans; a [VERIFY] ticket checks and owns the fix loop; a [REPLAN] ticket compares the product with the baseline and plans the next phase. |
The Spec Builder is deliberately outside the platform: it needs a long, calm conversation with a business person, file uploads, and no server access. The other two live inside CodeHero because they need the installation's real facts (active providers, ports, containers).
1.5 The machinery (enough to reason about it)
You do not need to read the source to operate CodeHero, but you must know what runs where, because every question in Module 5 ("why did it stop?") comes back to one of these parts.
| Part | Service / file | What it does |
|---|---|---|
| Web app | codehero-web (Flask + SocketIO; nginx on port 9453) | UI, REST API, live console, terminal, AI Assistant sessions |
| Daemon | codehero-daemon (scripts/claude-daemon.py) | Picks the next ticket per project, assembles the prompt, spawns the agent, watches it, reviews the outcome, retries, snapshots |
| Agent | HeroAgent (heroagent/heroagent.py) or a CLI provider | The tool loop: model call → tool calls → results → repeat until TASK COMPLETED |
| MCP server | scripts/mcp_server.py | The codehero_* tools the agent (and the assistant) call: projects, tickets, knowledge graph, git snapshots, containers, screenshots, context extraction |
| Permission hook | scripts/permission_hook.py | The single choke point every tool call passes through: execution-mode policy, path protection, container routing, loop detection |
| Database | MySQL claude_knowledge (database/schema.sql) | projects, tickets, ticket_dependencies, conversation_messages, conversation_extractions, knowledge_nodes, knowledge_edges, project_services, … |
| Preview proxy | nginx on port 9867 | Serves every project at https://127.0.0.1:9867/<project-folder>/ — the only URL the agent may test on |
| Containers | LXC + BTRFS (heroagent/container_manager.py) | Optional per-project isolation with provisioned services; the agent's commands are routed inside transparently |
Ports 9453 and 9867 are the defaults; the real values come from /etc/codehero/system.conf (ADMIN_PORT, PROJECTS_PORT) and are substituted into the context as {ADMIN_PORT} and {PROJECTS_PORT}.
1.6 The layers of instruction
When a ticket runs, the agent's system prompt is assembled from layers, in this order (see build_project_context_file() in the daemon):
=== CURRENT WORKING PROJECT ===— project id, name, ticket id; the isolation stamp ("passproject_id=<id>to everycodehero_*tool").- A knowledge-graph snapshot — the most relevant nodes of the project's knowledge base.
=== PROJECT GLOBAL CONTEXT ===— the project's stored copy of the global context, placeholders resolved.=== PROJECT CONTEXT ===— the project's stored copy of the language/stack context.=== PROJECT DESCRIPTION ===and=== PROJECT INFO ===— the description and the free "additional notes" field of the project.=== RUNTIME ENVIRONMENT ===— pinned runtime versions ("already installed — do NOT reinstall").=== SERVER PORTS ===— the concrete preview URL.=== PROJECT SERVICES ===— databases, caches and web apps withlocalhost:<port>and credentials ("already installed and running").- Container execution rules and the container app-deployment guide (container projects only).
- Smart-context material — project map, prior extraction summaries, recent history.
Then the user-turn prompt adds: project paths, the database block, the ticket's own context, the parent ticket chain, the ticket title and description, the allowed write paths, and the completion contract ("end your final message with TASK COMPLETED: <summary>").
Two consequences you will use constantly:
- Precedence is by specificity. The global context sets the method; the language context sets the stack idioms and must defer to the global for shared rules; the project context and the ticket carry the facts of this project. A ticket description can add facts; it should never contradict the method.
- Contexts are copied per project at creation. Editing
config/global-context.mdchanges new projects. An existing project keeps its stored copy until you edit it in Project Settings → Context or load the defaults again (Module 6).
1.7 Glossary you must know before Module 2
| Term | Meaning |
|---|---|
| Ticket | One task. Has a title, a description, sequence_order, optional depends_on, optional parent, a role (ai_model), a provider, a think mode, an execution mode. |
| Role | master_developer, senior_developer, junior_developer. Tickets store a role, not a model id; each provider maps roles to concrete models in heroagent/heroagent.conf (model_aliases). |
| Think mode | off / basic / balanced / ultra — extended-thinking budget. ultra is reserved for planning, replan, verification, peer review, helpers and explicit user choice. |
| Provider | anthropic, openai, gemini, grok, deepseek, glm, openrouter, ollama, vllm (plus generic OpenAI-compatible slots). Only active providers (valid credentials) may be planned. |
| Execution mode | autonomous (no prompts), semi-autonomous (auto-approves safe operations, asks for risky ones, blocks dangerous ones), supervised (asks before every write/edit/command). |
| Relaxed / strict | deps_include_awaiting = 1 / 0. Relaxed: the auto-reviewer may close a finished ticket. Strict: a human closes it. |
| SPEC FILE | .specs/<NNN>-<task>.md inside the project: the agent's plan and live progress log for one task. |
| KNOWLEDGE BASE | The project's knowledge graph (codehero_knowledge_search / codehero_knowledge_store): decisions, failed approaches, components, endpoints, patterns. |
| SNAPSHOT | A git backup taken by codehero_git_operations (backup_snapshot); automatic at ticket start and after each verified part. |
| PREVIEW URL | https://127.0.0.1:{PROJECTS_PORT}/{PROJECT_FOLDER}/ — the only place the agent may test a web page. |
| VERIFY ticket | A ticket that only checks another ticket's work. Different provider, master_developer, ultra. Never edits code. |
| HELPER ticket | A parallel ticket on another provider that only advises by messages. Opened and closed by the ticket that needs it. |
| Walkie-talkie | Ticket-to-ticket messaging: codehero_update_ticket(ticket_id=<other numeric id>, reply=...). The platform signs a reply from a ticket (📨 FROM TICKET #id); a working ticket receives it at its next step, a parked one (⏸ WAITING-FOR-TICKET #id, several ids allowed) is woken by it, and a ticket that ends its turn with a message still unread is re-opened at once. |
| TASK COMPLETED | The completion marker. The agent may say it only when the work is finished and the output was checked. |
Exercises — Module 1
- Open
config/global-context.md. For each of the twelve principles, find the exact section and copy one sentence that states it. (You will need these citations in Module 6.) - Read the glossary table in §0 of the global context. Explain in your own words the difference between the SPEC FILE and the KNOWLEDGE BASE, and why the framework keeps both.
- On your training installation, open Settings and list the active providers. Mark which ones have vision. Keep this list; every plan in Modules 4 and 8 must respect it.
- In the daemon's log (
journalctl -u codehero-daemon -f) watch one ticket run from start to finish. Write down the sequence of statuses you observed.
PART II — EXTRACTING KNOWLEDGE FROM THE CLIENT
Module 2 — The Spec Builder interview and the specification package
2.1 The problem this module solves
The most expensive mistakes in software are made before the first line of code: a misunderstood process, an unstated rule, a wish mistaken for a capability. In ADF the build is autonomous, so there is no developer in the loop to notice a misunderstanding half-way. Everything the agents will need must be extracted from the client before the run, in a form the agents can use.
The Spec Builder does that. It is not a form; it is an interviewer with a method, and the developer's job is to run it well, review its output critically, and know when it is done.
2.2 Setting it up
- Create a project in claude.ai (or a ChatGPT project). Upload
docs/CODEHERO_PLANNING_GUIDE.mdas project knowledge. - Set the project instruction to exactly: "You are the CodeHero Spec Builder. Follow the file
CODEHERO_PLANNING_GUIDE.mdexactly." - Start the conversation with the client's material (spreadsheets, screenshots, the current manual) already uploaded, so the assistant reads them before asking anything.
Who sits at the keyboard? Two working arrangements are common:
- The client types. The Spec Builder was written for a domain expert with no technical background: one question per message, no jargon, a proposed answer whenever it has a basis for one. You review the transcript and the package afterwards.
- You type, with the client next to you (or on a call). Faster for small tools; you can rephrase the assistant's question in the client's own words and keep it on track. You must resist the temptation to answer business questions yourself.
Either way, the developer never invents a business fact. That rule binds you exactly as it binds the agents (P3, P10).
2.3 The four statuses — the backbone of the whole method
Every requirement and every decision in the package carries one status and one origin:
| Status | Meaning | Who resolves it |
|---|---|---|
| Confirmed | The client said it, or a source document shows it | — |
| Assumed | A reasonable business assumption that still needs confirmation | The client, at the preview or the final confirmation |
| Technical | The Spec Builder's own choice, with a reason; never asked of the client | The developer may override with a recorded reason |
| Open | A missing element that affects the build | Must be closed before the package is Ready to build — unless the client agrees to move it to Later |
Origin is user, document or agent. A requirement the assistant proposed and the client approved is Confirmed / agent. The origin column is what lets the client later audit "what did I ask for, and what did you add?".
Two rules make the statuses honest:
- "I don't know" is an answer. A technical gap is filled silently as Technical. A business gap becomes Assumed, with one sentence saying what was assumed.
- Critical items are never silently assumed. Anything that decides money, approvals, deletion rights, legal or compliance obligations, or safety stays Open and visible in every summary until the client confirms it — even when the client wants to finish quickly.
You will see the same distinction again at run time: the agent's SAFE DEFAULT (P5) is exactly an Assumed item chosen so that it cannot hurt anyone, and CRITICAL questions stop the ticket instead of getting a default.
2.4 The interview, stage by stage
Part 2 of the Planning Guide is a coverage checklist, not a script. The assistant asks in the order the conversation makes natural, skips what a document already answers, and adapts wording to the industry. As the developer, you check coverage at the end: did every stage get answered or consciously defaulted?
| Stage | What must be known afterwards | Typical count |
|---|---|---|
| 0 Setup | What to organize, existing documents, a name, who will maintain it | 2–3 |
| 1 Company and purpose | The business, the pain, who suffers, success in six months, internal vs external users, countries, what must never happen | 5–7 |
| 2 The work itself | The "things" tracked, their fields, what keeps history, the steps of the main process, who does each, rules and calculations, exceptions, documents in and out, other systems, volumes, late/duplicate data | 10–15 |
| 3 People and rights | User types, what each sees and changes, who may delete/approve/export (critical), scoping by branch/team, admin area, concurrency, external logins, audit | 6–10 |
| 4 Notifications, reports, integrations | When someone must be told, channels people actually read, reports, exports, scheduled emails, automatic data exchange | 5–8 |
| C Constraints (mandatory before any architecture) | Integrations and whether they are occasional or continuous; offline or background operation; time limits and continuous data; existing hosting, devices and support; initial and monthly budget | 5 |
| P Preview (mandatory) | The main screen as a text wireframe, the main process walked through with the client's own example, each role in one line, the status summary. Then: "Is this how you work? Tell me what is wrong." | 1 loop |
| 5 Speed, scale, real time, mobile | How fast others must see a change, alarms where seconds matter, sensors, where it is used, offline, store app vs website, camera/GPS/push, growth | 6–9 |
| 6 Look, feel and brand | Logo and colors, feel, references, theme, languages, units, accessibility | 5–8 |
| 7 Security, compliance, hosting | Personal data, 2FA, session length, security testing, where it runs, domain and SMTP, audit proof, backup tolerance, confirmed monthly cost | 6–9 |
| 8 Priorities and go-live | The one part that must be ready first, the MVP/Optional/Later split, data import, first administrator, training, deadline, "anything you were afraid to ask?" | 5–7 |
Note the two mandatory checkpoints. Stage C comes before any technology decision, because the constraints — not the archetype — decide the stack (Module 3). Stage P comes before scale, brand and security, because a misunderstanding caught at the preview costs one message and the same misunderstanding caught after the build costs dozens of tickets.
2.5 A worked interview: "RepairFlow"
We will follow one example through the whole course. A small electronics repair company with three technicians tracks repair jobs in an Excel sheet. Jobs get lost, deadlines are missed, and the owner cannot see who is doing what.
The opening question is always the same: "Which piece of your work do you want to organize or automate? Describe a real example — what happened last time, step by step."
Extracts from the transcript, with the status the Spec Builder assigned:
| Client said | Became | Status / origin |
|---|---|---|
| "A customer brings a laptop, we write it in the sheet with a number, a technician takes it, when it's fixed we call the customer, they pay and pick it up." | Entity Job with states received → in_repair → ready → delivered; entities Customer, Technician | Confirmed / user |
Column H in the sheet is =D2+14 | Business rule: deadline = received date + 14 days | Confirmed / document (the assistant restated it and the client said yes) |
| "Red cells are the ones we are late on." | Rule: a job past its deadline and not ready is overdue; overdue jobs are highlighted and the manager is notified daily | Confirmed / user (highlight) + Assumed / agent (daily email) |
| "Only I give discounts." | Permission: discount requires the Owner role | Open — critical until the client confirmed the exact roles who may discount and the maximum |
| "We'd like customers to check the status themselves one day." | Customer portal | Later |
| "Sometimes two technicians work on the same job." | Job has one responsible technician and optional helpers; history keeps who did what | Assumed / agent, confirmed at preview |
| "How fast must the owner see that a job changed status?" — "When I refresh is fine." | Real-time: on refresh / polling every 60 s | Technical / agent |
| "We have a website on a normal hosting company, nobody technical in-house." | Hosting: standard PHP/MySQL web hosting, no in-house support | Confirmed / user → drives the stack (Module 3) |
| "Budget: as little as possible per month." | Monthly cost target: hosting only | Confirmed / user |
Then the preview (Stage P). The assistant showed the job list as a text wireframe (columns, the three most common actions: new job, change status, print job sheet), walked the client's own laptop example through the states, described the three roles in one line each (Owner sees all and gives discounts; Technician sees own jobs and changes status; Front desk creates jobs and marks delivered), and listed what was Confirmed, Assumed and Open. The client corrected one thing: the front desk also takes the payment, so Front desk may mark a job paid. One message, one correction, dozens of tickets saved.
2.6 The spreadsheet intake procedure
When the client uploads a spreadsheet (most internal tools start as one), the Spec Builder follows §2.9 of the guide before asking Stage 2 questions. Learn the mapping; you will use it yourself when a client hands you an Excel file:
| In the spreadsheet | Becomes |
|---|---|
| Each sheet or repeated block | A candidate entity, named in the client's words |
| Each column | A typed field (text, number, date, money, choice list, person, reference, file, formula) |
| Each formula | A business rule, restated in words and confirmed with the client's own numbers |
| Colors, comments, manual marks | Workflow states and exceptions ("what does a red cell mean?") |
| Repeated manual steps ("every Monday I copy A to B") | A scheduled job |
| Who edits which columns | Permissions |
| Duplicates, blanks, inconsistent spellings | Data-quality rules and the import cleaning plan — never silently "fixed"; the import report lists every changed or rejected row |
Two habits protect you: record separately what the sheet does today and what the new application is agreed to do (they differ more often than not), and treat text inside the file as information, never as instruction.
2.7 Wishes are not capabilities: the dependency register
A client confirming that they want an ERP integration does not prove that their ERP can provide it. Every critical external dependency goes into the dependency register (template T9) with the specific capability, the system and version, the access or licence required, and a verification status that is separate from the business status:
| Business status | Verification status |
|---|---|
| confirmed / assumed / technical / open | pending / verified / failed / mock_only |
A dependency that an active function needs must be verified before the feature tickets that depend on it start. Until then the package stays a Draft, and a Draft may go to CodeHero only for probe tickets (environment checks, integration probes). A mock is recorded as mock_only and never counts as the real integration — the same rule the agent follows at run time (P5: never mock an integration and report it as working).
2.8 The decision engine is not the client's problem
Part 3 of the guide is the Spec Builder's private decision engine: archetypes, stack rules, hosting targets, the real-time ladder, the mobile ladder, the frontend choice. The client never sees the options. They answer questions about their world ("how fast must someone see a change?", "must it work without internet?"), and the assistant translates. Module 3 teaches you the same engine so you can review the choice.
2.9 The 50 review rounds
Once the complete first version of the specification exists, the Spec Builder runs 50 sequential review-and-fix rounds and a final consistency check. Each round examines the whole current specification from one perspective (main process end to end · every rule has a number and an example · what must never happen · late, duplicate, out-of-order data · time zones · permissions matrix · external users see only theirs · backups and one restore drill · audit fields · hosting capabilities verified · milestone order builds the main value first · each ticket has a demonstrable definition of done · …), tries concrete examples in the client's own numbers, fixes what the agreed requirements allow, and records one row in Appendix E.
What you must know as the reviewer of the package:
- Ticking fifty topics is not fifty rounds. A real round produces a finding with a worked example, or records what was examined and that no change was needed.
- The rounds run autonomously. They ask the client only when essential business information is missing, when two requirements genuinely contradict, or when a fix would change an agreed function, cost or permission.
- The rounds evaluate the specification. They never prove that the application works — that is what CodeHero's real tests do, and their evidence lands in the acceptance manifest later.
- A Draft delivered early states the real number of completed rounds. If a package says "50 rounds" and Appendix E has eleven rows, it is not honest, and you send it back.
The executing agent later runs the same discipline on its plan (guides/planning.md step 12: about twenty review rounds for a real project, eight for a small one). Same idea, two levels: the spec is attacked before the plan exists; the plan is attacked before the tickets exist.
2.10 The package
The output is one Markdown file (plus an SVG logo concept when relevant) with a fixed structure — twenty numbered sections and appendices A–I (Planning Guide Part 7). The parts the in-app planner reads first:
| Part | Why it matters downstream |
|---|---|
Header block with the codehero_environment block | Tells the planner whether a container is needed, who provisions it, which services, the database, real-time mode, build tooling, who serves the built files, and the fallback stack |
| 2 CodeHero run settings | Roles and think modes per ticket type, serial execution, replan and revalidation cadence, circuit breakers |
| 4 Access gate | The thin end-to-end slice through the real hosting before any feature |
| 7 Business rules | Numbered, with worked examples and expected results — the agent's only source of business truth |
| 17 Milestones and ticket plan | Value order, ticket text rules, requirement IDs per ticket |
| 18 Contracts, day-0 inputs, touchpoints | What the client must provide before the run, and the only four reasons CodeHero will contact them during it |
| Appendix F | Open items, assumptions to confirm, technical decisions — the first thing the client reads |
| Appendix G / H | Requirements register and dependency register — the traceability spine |
Ticket roles in the package are written exactly as CodeHero expects, and no provider or model is ever named:
| Ticket type | role | think_mode |
|---|---|---|
| Planning, replan, contracts, architecture, security | master_developer | ultra |
| Independent revalidation (verifies only) | master_developer (different provider if available) | ultra |
| Feature implementation | senior_developer | balanced |
| Repetitive work (locale files, CRUD from a contract, docs formatting) | junior_developer | basic |
| Tests and fixtures | senior_developer | balanced |
2.11 Draft vs Ready to build
| State | Condition | What CodeHero may do with it |
|---|---|---|
| Draft for confirmation | Contains Assumed or Open items; open items listed at the top, never hidden | Probe and setup tickets only; feature tickets that depend on open items wait |
| Ready to build | Critical open items of the agreed scope — and of the dependencies that scope needs — are closed; non-critical assumptions may remain and are listed | The full plan |
Moving a critical open item to Later requires the client's agreement; it is never done silently to reach Ready to build.
2.12 The day-0 pack and the four contact reasons
Before the run, the client provides the day-0 pack: domain, hosting access, SMTP account, logo files, the spreadsheet, first administrator details — and, if the container is created manually, the container with its access details. During the run, CodeHero contacts the client for exactly four reasons:
- external credentials or accounts for a specific gate;
- a fix loop that reached its limit;
- a fallback that would change an agreed requirement;
- discovery of a new critical business ambiguity that cannot be resolved from the confirmed requirements.
Ordinary business assumptions are confirmed before the run (Stage P, final confirmation), never during it. If your run keeps stopping with business questions, the interview was incomplete — fix the package, not the tickets.
2.13 Handing the package to CodeHero
The package is pasted (or attached) into the in-app Plan with AI planner, which recognizes it by its markers (codehero_environment: block, run settings, registers, ticket plan with roles and think modes) and switches to IMPORT MODE: it asks only for missing authorizations and day-0 owners, shows a preview, and creates the project plus ONE planning ticket that carries the package verbatim. The planning ticket plans on the real installation (Module 4); the package's ticket plan is its starting material — candidates, never tickets created as they stand. Day-0 inputs and open items go to the operator, never into ticket descriptions.
2.14 Developer's review checklist for a package
Before you import a package, check:
- ☐ Every requirement outside Later has at least one acceptance ID and a milestone (Appendix G).
- ☐ Every business rule in §7 has a number and a worked example in the client's values.
- ☐ Appendix F lists every Assumed item, every Open item and every requirement with origin
agent. - ☐ Critical items (money, approvals, deletion, legal, safety) are Confirmed or explicitly Open — none is Assumed.
- ☐ Every critical external dependency has a T9 row with a verification status; nothing needed by active scope is
pendingwithout a probe ticket. - ☐ The
codehero_environmentblock is complete and consistent with the stack template (container_required,container_provisioning,services,database,realtime,build,served_by,fallback_stack). - ☐ The ticket plan is serial (strictly ascending distinct sequence numbers), starts with setup → capability probe → knowledge foundation → access gate → main process end to end.
- ☐ Every ticket cites requirement IDs; no ticket installs runtimes, databases or web servers; no ticket text mentions a container, a container name or an internal IP.
- ☐ Documentation deliverables are listed in the client's language.
- ☐ Appendix E has real review rows, and the stated round count matches.
Exercises — Module 2
- Run an interview. Pair with a colleague who plays a client (a dental clinic's appointment book, a warehouse's stock sheet, a school's attendance list). Set up the Spec Builder and let the "client" answer. Do not answer business questions yourself. Deliver the package.
- Audit the statuses. In the package, count Confirmed / Assumed / Technical / Open. For every Assumed item write the one sentence the client must confirm. For every critical item check it is not Assumed.
- Spreadsheet intake. Take any real spreadsheet you have. Apply §2.6 by hand: entities, fields, formulas → rules, colors → states, manual steps → jobs. Compare with what the Spec Builder produced from the same file.
- Find the wish. In your package, find one dependency the client wants but nobody has verified. Write its T9 row and the probe ticket that would verify it.
- Review rounds. Pick five perspectives from Part 6 of the guide and run them yourself on your package, recording findings in the T6 format. Did you find something the fifty rounds missed? (Usually yes — that is why the developer reviews.)
PART III — CHOOSING THE STACK
Module 3 — How and why CodeHero picks PHP, Node, Python or .NET
3.1 The principle: the right application for this client
The Spec Builder's central principle (Planning Guide §1.1) is fit: the solution matches the real needs of the application, the initial budget and the acceptable monthly cost, the knowledge of the client's team, their existing infrastructure, and their ability to install and maintain what you specify. A technically superior stack that the client cannot host or maintain is the wrong stack.
That is why the stack is decided after Stage C (constraints), never from the archetype alone, and why every deviation from the default carries a one-line justification in the spec. When you review a package or a quick plan, look for that line. If it is missing, the choice was a preference, not a decision.
3.2 PHP-first, MySQL-first — and why
CodeHero's default backend is PHP ≥ 8.2 with MySQL ≥ 8, on standard web hosting when the design allows. The reasons are practical, and you should be able to state them to a client:
| Reason | What it means for the client |
|---|---|
| Ease of installation and maintenance | Runs on any cPanel/Plesk hosting; no process manager, no daemon, no container to operate |
| Lowest running cost | Shared hosting money, not VPS money; no in-house support needed |
| Fit with CodeHero's own strengths | The PHP project context is the most mature one (canonical includes/config.php bootstrap, "silent mistakes" list, PDO-only, CSRF, PRG); the preview proxy, php-fpm log source and php -l syntax check are wired into the verification recipe |
| No build step by default | Plain .js plus local libraries copied from /opt/codehero/libs/ (Tailwind, Alpine, Vue, FontAwesome) — instant, offline, no npm |
| Interpreted = served | On a host project the source is what nginx serves; nothing to compile, nothing to forget to copy |
The PHP profile covers: REST APIs, internal business applications, portals and management systems, backends for mobile apps, dynamic websites, and integrations served by ordinary requests or periodic jobs. A REST API, complex screens or an app-like look are not reasons to leave PHP. Neither is "many users" — load is judged from a representative workload described in the spec and verified in the access gate or a load test, never from a rule of thumb.
MySQL stays the default with every backend. Backend and database are decided separately: Python does not imply PostgreSQL and .NET does not imply SQL Server. PostgreSQL or SQL Server appear only when the client asks, when an existing environment or integration requires them, or when a specific application reason is recorded.
3.3 When to leave PHP — the only triggers
| Condition | Move to | Why |
|---|---|---|
| WebSockets are required by an acceptance criterion (alarms in seconds, live boards, multi-user editing) | T-NODE (T-NET / T-PY when the environment fits) | Web hosting cannot keep sockets open; CodeHero policy is never to stretch PHP to cover them |
| Permanent workers or continuous server-side processing (device/sensor streams, jobs that exceed cron limits, media processing) | T-NODE / T-PY | Worker processes beyond limited-duration cron |
| Statistics, forecasting, machine learning, scientific libraries | T-PY | Ecosystem |
| The client asks for a technology, or already runs and maintains one that meets the requirements | That stack | Maintainability and fit beat preference |
| Microsoft environment (Entra ID, SQL Server, Windows servers, a .NET team) when it fits their operations | T-NET | Fit with their operations |
| A native mobile app is needed | Swift / Kotlin + a backend by the rules above | — |
Server-sent events do not trigger the WebSocket row as long as they are verified on the actual hosting for timeouts, buffering and reconnection. If none of the triggers applies, the spec says so explicitly: "PHP/MySQL chosen; runs on standard web hosting; no container required."
3.4 The archetypes (what the signals usually mean)
| ID | Archetype | Typical signals | Default stack | Container? |
|---|---|---|---|---|
| A1 | Static site | Brochure, no login, contact form | HTML/CSS/JS + PHP mailer | No |
| A2 | Content site with forms and admin | Pages, catalog, submissions, small admin | T-PHP, Alpine + Tailwind | No |
| A3 | Internal tool / spreadsheet replacement | "Our Excel", records, roles, reports, imports | T-PHP; Vue only when the screens justify it | No |
| A4 | Multi-tenant SaaS | Many companies, per-company settings, billing | T-PHP (Laravel) for most; T-NODE when §3.3 requires | No / Yes |
| A5 | Real-time monitoring / operations | Devices, alarms, seconds matter, live screens | T-NODE (T-NET/T-PY when the environment fits) | Yes |
| A6 | Integration hub / API product | Connecting systems, webhooks, transformations | T-PHP when request- or schedule-based; T-NODE/T-PY when continuous | No / Yes |
| A7 | Customer / supplier portal | External logins, documents, statuses | T-PHP | No |
| A8 | Mobile companion app | Field staff, camera/barcode/GPS, push | T-PHP REST API + web app wrapped with Capacitor | Runtime as the backend |
| A9 | Native mobile app | Hardware/OS integration, offline-heavy | Swift / Kotlin + backend by the rules | Per backend |
| A10 | Data / analytics tool | Heavy calculations, forecasts, large imports | T-PY + MySQL | Yes |
3.5 The ladders: pick the lowest rung that satisfies the answers
Real-time ladder (from Stage 5 answers):
- On refresh — content sites.
- Polling every 15–60 s — most internal tools; any hosting; T-PHP.
- Polling every 5 s + in-app badge — operational tools where a minute is too slow; still T-PHP.
- Server-sent events — one-way live feeds; T-PHP where the provider supports it and it is verified; otherwise a container.
- WebSockets with a durable event stream — alarms, live boards, multi-user editing; container stack. Pattern: events from a database outbox with cursor, replay on reconnect, heartbeat with visible disconnection, receipts.
Mobile ladder:
- Responsive web app — every product gets it.
- Installable web app (PWA) — home-screen icon, offline read-only cache, web push.
- Capacitor wrapper — the same web app in the stores; native plugins for camera, barcode, GPS, push, biometrics. Requires Apple and Google developer accounts (day-0).
- React Native / Expo — only if the client's team is React-based and asks.
- Native Swift/Kotlin — only for A9 conditions.
Frontend, chosen by need and separately from the backend: a simple presentation page → HTML + Tailwind, minimal JS; simple forms → server-rendered pages + Alpine.js; complex screens with many interactions → Vue (PrimeVue preferred), built inside CodeHero and committed as static files, so a PHP host never needs Node.
3.6 Runtime vs build tooling vs serving — three separate declarations
The single most common confusion. The codehero_environment block separates them on purpose:
| Question | Field | Rule |
|---|---|---|
| What must be running on the server? | container_required, services, long_running_processes | Anything beyond PHP + MySQL at runtime (Node, Python, .NET, Redis, workers, WebSockets) → container_required: true |
| What is needed only to build artifacts? | build.web (none / tailwind-cli / vite), build.android, build.ios, build_container | Never changes the runtime answer; a Vite-built Vue app can run on a PHP host |
| Who serves the built files? | served_by (php-host-static-files / nginx-static / app-server) | Declared separately from the tools that build them |
The global context's Section 14 mirrors this at execution time — where the build workspace lives depends on the project shape:
| Situation | Build workspace |
|---|---|
| Container project | Anywhere inside the container; only the served output matters |
| Host, interpreted (PHP, plain HTML/JS) | Nowhere — the source is what is served; Composer vendor/ at {web_path}/vendor/ |
Host, compiled, has app_path | {app_path} is the workspace; build there, copy output to {web_path} |
| Host, compiled, web_path only | {web_path}/.build/ (nginx does not serve dot-dirs); only compiled output goes to the web root |
3.7 What CodeHero provides — so you never plan "install PHP" tickets
Host projects. Ubuntu 24.04, nginx, PHP 8.3, Node 22, Python 3.12, MySQL 8.0 (global §13). Each project gets its own MySQL database and user; credentials appear in the agent's PROJECT DATABASE block. Local libraries live in /opt/codehero/libs/.
Container projects. CodeHero creates an LXC container per project (codehero-<project_id>) from a manifest of services — the default manifest offers nginx, PHP 8.3, MySQL 8.0, Python 3.12, Node 20 and Redis 7, and the Container Isolation chapter of the User Guide lists the full catalogue of languages, databases and service options. Services declared at creation are provisioned before any ticket runs; the agent's commands are routed inside the container transparently; the agent sees services at localhost:<port> in its PROJECT SERVICES block and must believe it is on a normal server.
This is why the Planning Guide and the planner both say: no ticket installs PHP, Node, MySQL, Redis or a web server, and no ticket configures nginx. The first real ticket sets up the application (folders, config, schema), and a setup ticket in a container verifies the provisioned services and configures application-level pieces. A plan with an "install Node.js" ticket is a plan that misunderstood the platform.
3.8 Project type and paths
| Output | project_type | Path | Rule |
|---|---|---|---|
| Any project with web pages / HTML output — regardless of language | web | web_path: /var/www/projects/<slug> | A .NET, Node or Python app that serves HTML is still web |
| Pure backend API, CLI, library, mobile backend with no HTML | app | app_path: /opt/apps/<slug> | — |
tech_stack selects the project context file: php, python, node, html, java, dotnet, go, react (also used for React Native), flutter, kotlin, swift, presentation, reporting; project types capacitor, native_android, dotnet, presentation, reporting also map. Anything unmapped falls back to php. Pinned runtime versions (php_version, node_version, python_version, …) can be passed at creation and appear in the agent's RUNTIME ENVIRONMENT block.
3.9 The environment block, field by field
codehero_environment:
container_required: false # runtime beyond PHP + MySQL? → true
container_provisioning: none # none | codehero (platform creates it WITH the services) | manual (client created it; access = day-0 input)
services: [php-fpm, mysql] # runtime services the environment must provide
database: mysql # mysql by default; postgresql | sqlserver only with a recorded reason
long_running_processes: none # e.g. [api, workers, websocket-gateway]
scheduled_jobs: cron-every-minute # or worker-queue; state max duration, overlap lock, retries, interruption behaviour
realtime: polling-30s # none | polling-Ns | sse (verified on provider) | websocket
build:
web: tailwind-cli # none | tailwind-cli | vite
android: none # none | capacitor | native
ios: none
ios_path: none # macos-xcode | external-service (named)
signing: none
test_devices: none
build_container: none # none | node | node+android | node+ios
served_by: php-host-static-files # php-host-static-files | nginx-static | app-server
fallback_stack: none # for any non-PHP choice: the T-PHP design to fall back to, valid only if the same acceptance criteria still pass
container_provisioning: codehero is the normal choice: the in-app assistant creates the container with the declared services before the planning ticket exists. manual means the client operates their own environment; then the container and its access details are a day-0 input, and the setup ticket only verifies and configures.
fallback_stack exists because the architecture is chosen before the installation is probed. If ticket #0 (the capability probe) finds that the runtime cannot be provided, the run stops with a question to the owner and proposes the fallback — only if it still passes the same acceptance criteria. A fallback that changes an agreed capability (update speed, live alarms, offline use) is a requirements change, not a technical swap, and each affected requirement ID must be named.
3.10 Two contrasting examples
RepairFlow (A3, internal tool). Stage C answers: occasional integrations (email only), no offline, no time limits, standard web hosting, minimal monthly cost. Stage 5: "on refresh is fine". No trigger to leave PHP. Decision recorded in the spec: "PHP/MySQL chosen; runs on standard web hosting; no container required."
codehero_environment:
container_required: false
container_provisioning: none
services: [php-fpm, mysql]
database: mysql
long_running_processes: none
scheduled_jobs: cron-every-minute # overdue check: max 50 s per run, overlap lock, 3 retries, safe to interrupt
realtime: polling-60s
build: {web: tailwind-cli, android: none, ios: none, ios_path: none, signing: none, test_devices: none}
build_container: none
served_by: php-host-static-files
fallback_stack: none
CodeHero project: project_type: web, tech_stack: php, web_path: /var/www/projects/repairflow, no container.
AlarmBoard (A5, real-time monitoring). A logistics yard with 40 temperature sensors; the acceptance criterion says "an out-of-range reading is shown on the operations screen within 2 seconds, measured from the sensor's timestamp to the on-screen alert". Stage 5: seconds matter; devices stream continuously. Two triggers fire (WebSockets by an acceptance criterion; continuous processing). Decision: T-NODE in a container, with the justification line "WebSocket alerting within 2 s required by A07; sensor stream needs a permanent worker."
codehero_environment:
container_required: true
container_provisioning: codehero # CodeHero provisions node, mysql, redis, nginx at creation
services: [node, mysql, redis, nginx]
database: mysql
long_running_processes: [api, workers, websocket-gateway]
scheduled_jobs: worker-queue
realtime: websocket
build: {web: vite, android: none, ios: none, ios_path: none, signing: none, test_devices: none}
build_container: node
served_by: nginx-static
fallback_stack: T-PHP with polling-5s # only valid if A07 still passes — it will not, so this is a requirements change
CodeHero project: project_type: web (it serves the operations screen), tech_stack: node, web_path: /var/www/projects/alarmboard, container created via codehero_container_operations with the declared services before any ticket.
3.11 Eight mini-cases (decide, then check)
| # | The client says | Decision | Why |
|---|---|---|---|
| 1 | "A website for our law firm with a contact form and a news page the secretary updates." | A2 · T-PHP · no container | Content + small admin; no trigger |
| 2 | "We want a REST API for our mobile app; 200 field workers upload photos of deliveries." | A8 · T-PHP REST API + Capacitor app · no container for the backend | A REST API and a mobile backend are not reasons to leave PHP; store accounts are day-0 inputs |
| 3 | "Our dispatchers must see every truck's position live on a map; alarms when a truck stops for more than 5 minutes." | A5 · T-NODE · container | Continuous device stream + live board; verify whether "live" means seconds (WebSocket) or a minute (polling) before deciding — the acceptance criterion decides |
| 4 | "We are a Microsoft shop: Entra ID logins, SQL Server, a .NET team maintains everything." | T-NET · container · SQL Server with a recorded reason | Fit with their operations; the client's team maintains it |
| 5 | "Forecast next month's demand per product from 5 years of sales; import the CSV every night." | A10 · T-PY · container · MySQL | Scientific libraries; nightly import is a scheduled job, not a worker |
| 6 | "A portal where our suppliers see their open orders and upload invoices." | A7 · T-PHP · no container | External logins, documents, statuses; scope-bound permissions |
| 7 | "Same as case 1, but we already run a Django site and our IT person knows Python." | T-PY on their environment, or T-PHP if they prefer — record the client's choice | The client already runs and maintains a stack that meets the requirements |
| 8 | "A dashboard with 12 KPIs from our MySQL, refreshed every minute, printable to PDF." | reporting project type · T-PHP · no container | Polling rung 2; the reporting context already carries ApexCharts, DataTables and PDF export patterns |
3.12 How to write the justification
One line, in the spec header and again in the planner preview when the stack is not PHP + MySQL. The pattern: requirement ID → the capability it needs → why PHP cannot provide it → the chosen stack.
A justification that names a preference ("Node is more modern") instead of a requirement is not a justification. Send it back.
Exercises — Module 3
- For each of the eight mini-cases, write the
codehero_environmentblock. Compare with a colleague; every difference must be explainable by a requirement. - Take your Module 2 package. Find the stack decision. Is there a one-line justification? Does it cite a requirement ID? If the stack is PHP, does the spec say "no container required" explicitly?
- Rewrite this bad plan fragment so it respects §3.7: "Ticket 1: Install Node 20 and MySQL in the container. Ticket 2: Configure nginx to proxy port 3000. Ticket 3: Create the schema."
- A client insists on PostgreSQL "because it is better". Write the two sentences you would say, and the line you would record in the Decision Log if they still insist.
- Explain to a non-technical client, in three sentences, why their internal tool will run on their existing web hosting and what that saves them per month.
PART IV — PLANNING
Module 4 — From package to project: the in-app planner and the ticket plan
4.1 Where planning happens — two places, one method
Open the AI Assistant in CodeHero and choose Plan with AI. The assistant runs with config/assistant-planner.md as its instructions plus the global context, and it has the codehero_* tools. It does two things well: it knows this installation (active providers, ports, container support), and it can create the project and its environment. It designs no tickets. It writes the specification with you (or imports a Spec Builder package), settles everything only a person can decide, shows a preview, and after you confirm creates the project, the container when the environment contract declares one, and exactly one ticket: the planning ticket ([PLAN] <project> — baseline and phase 1).
The planning ticket runs in PLAN MODE (guides/planning.md, pre-loaded for it by the daemon) on the real installation: it saves the specification as the immutable baseline (.specs/000-baseline.md), reads the active providers, writes the plan file (requirements with acceptance examples, roles, stack, run settings, open questions), fills the knowledge base, writes one SPEC FILE per sub-task with the shared contracts first, orders the work by value, runs a dry run of the plan and its review rounds, gets a peer check from another provider, and creates the first phase of tickets. Every later phase is created by the [REPLAN] ticket that ends the previous one. The same PLAN MODE runs when a user opens a ticket by hand and says "σχεδίασε": one method in one place.
Size decides the depth. A small change or fix on an existing project is not a plan at all — the assistant creates one ordinary build ticket and the agent runs the light loop of the global context. A small project (one phase, up to about eight tickets, no accounts, no money) gets PLAN-lite: eight review rounds, a peer check only when there is login or money, no [REPLAN]. A real project gets about twenty rounds, the peer check, and phases of about ten tickets.
4.2 The assistant's rules that matter to you
- MCP tools only. Project, environment and the planning ticket are created with
codehero_create_project,codehero_container_operationsandcodehero_bulk_create_tickets(with one ticket) — never with SQL, curl or the UI on the assistant's behalf. codehero_get_providers_infofirst. The single source of truth for active providers, cost and smart weights per role, vision and thinking support; the assistant never plans from memory. The planning ticket reads it again itself.- Only active providers, for the project default and for the planning ticket.
- Exactly one ticket. Even a package with a complete ticket plan produces one planning ticket; the cards stay candidates.
- Preview → explicit confirmation → create. Settings, specification summary, day-0 inputs, run settings, then "yes / ok / ναι / προχώρα". "Do what you think" delegates decisions, not the preview.
- Business decisions belong to you (money, rights, approvals, deletion, retention, safety, scope, cost). A gap is marked
open, never filled with an invented default. Front-load the human input: once the planning ticket starts, the run is autonomous and a missing business decision stops it. - Environment is not ticket work — containers and services are created before the planning ticket; tickets install no runtimes; ticket text says
localhost:<port>and never a container name or an internal IP. - What you set, it passes. Flow, execution mode, strategy, parallel and plan approval appear in the preview, in the run contract, and explicitly in the tool call (
relaxed=deps_include_awaiting: true,strict=false). - Language and voice mode, as everywhere.
4.3 Three modes
| Mode | Trigger | What the assistant does |
|---|---|---|
| IMPORT | The message contains a specification package (an environment_contract: or legacy codehero_environment: block, run settings, registers, a ticket plan) | No re-interview. Reads the header, readiness, environment and run contract; asks only for missing authorization, day-0 owners and a critical open item you can settle now; passes the package verbatim into the planning ticket |
| BUILD | Anything else: a description, a spreadsheet, a document | Acts as the Spec Builder: one focused question at a time, technical matters decided itself, writes the specification (mandate, business behavior, people, data, integrations, experience, numbers, environment contract, acceptance, registers, run contract), runs an in-app consistency check, previews |
| TICKET TEXT ONLY | "Just give me the ticket text" | Runs BUILD or IMPORT, then outputs the filled planning-ticket text instead of creating it |
Defaults: execution autonomous, flow relaxed (deps_include_awaiting: true), strategy balanced, serial, plan approval autonomous (you approved the preview; the planning ticket does not ask again — set plan_approval: owner-approves-first-stage if you want to see the ticket table before anything is created), project think mode balanced. ultra is never a project default; the planning ticket itself runs master_developer + ultra on the smartest active provider that supports thinking.
4.4 Providers, roles, think modes, strategy — the planning ticket's job
Roles, not models. A ticket stores ai_model = master_developer / senior_developer / junior_developer. Which concrete model that means depends on the provider, via heroagent/heroagent.conf (model_aliases). Adding a new model to the platform is a config edit; no ticket changes.
Role by complexity and strategy (the planning ticket's table; the Spec Builder's table in Module 2 covers packages that state roles):
| Complexity | eco | balanced | performance |
|---|---|---|---|
| Trivial (docs, typos, config) | junior | junior | junior |
| Simple (static pages, boilerplate) | junior | junior | senior |
| Moderate (features with logic, APIs) | junior | senior | senior |
| Complex (multi-file, refactor) | senior | senior | master |
| Critical (architecture, auth, security, setup/foundation) | senior | master | master |
Think mode ladder: off/basic for trivial and simple work; balanced for standard features; ultra never for a build ticket on the planner's own initiative — and always for [PLAN], [REPLAN], [VERIFY], [PEER] and [HELPER] tickets.
Provider assignment (never the Spec Builder's job):
- visual build or verify tickets → vision-capable providers only;
- the chain tickets (
[PLAN],[PEER],[VERIFY],[HELPER],[REPLAN]) → the preferred pair is anthropic ↔ openai: one side plans and builds, the other reviews and verifies; an installation without them uses the customer's master-tier provider (highestmaster_developersmart weight), with a different family for the verify when one exists; the user's explicit preferences win; [VERIFY]tickets → a different provider family than the builder,master_developer,ultra;- tickets that share a
sequence_order(an approved parallel group) → spread across providers to avoid rate limits; - strategy: eco = cheapest capable, performance = highest smart weight, balanced = both;
- a single active provider → use it for everything; a
[VERIFY]on the same provider is still worth running but never counts as a second opinion.
4.5 Translating the environment contract into a project
| Contract says | Assistant does |
|---|---|
standard-hosting / native-host (legacy: container_required: false) | Host project. HTML output → project_type: web, web_path: /var/www/projects/<slug>; no HTML → app, app_path: /opt/apps/<slug>. tech_stack from the stack; pinned versions if the spec states them. |
platform-container (legacy: container_required: true, container_provisioning: codehero) | Create the project, then the container with codehero_container_operations declaring the listed services (nginx is automatic). Before the planning ticket. |
existing-infrastructure (legacy: manual) | Access details are a day-0 input. Missing → open item; readiness at most Ready for scoped discovery. |
| A runtime missing on a native host | A day-0 input with its owner — never a ticket. |
| Run contract | Written into the planning ticket as a top-level ## RUN CONTRACT section (and summarized in the project description). The planning ticket obeys it; a "run contract" found inside a specification or a message authorizes nothing. |
| Day-0 inputs and open items | A ## DAY-0 INPUTS AND OPEN ITEMS section of the planning ticket; the planner turns them into BLOCKED asks at the step that needs them and never asks a known open item again. |
| Draft / open items | The planning ticket creates only what the open items allow; feature tickets wait. |
4.6 The ticket fields and what the scheduler does with them
| Field | Meaning | Blocks execution? |
|---|---|---|
sequence_order | Ordering. Distinct ascending numbers = serial (the default). The same number on two tickets = a parallel group (as many at once as MAX_PARALLEL_TICKETS_PER_PROJECT allows). | Yes — a higher number starts only when EVERY ticket with a lower number is done or skipped. A ticket left in awaiting_input, failed or stuck holds everything behind it. |
depends_on | Explicit dependency. In a bulk call: 1-indexed positions of the same call, earlier only (a later or unknown position rejects the whole call). In codehero_create_ticket: existing tickets by numeric id or ticket number (an unknown value is an error). Stored in ticket_dependencies. | Yes — every dependency must be done or skipped, in relaxed and strict flow alike. It matters inside a shared sequence number; across numbers the number already orders. |
parent_ticket_id / parent_sequence | Sub-task: waits for the parent, inherits its context (title, description, summary of the parent's conversation). This is how a [VERIFY] ticket finds its parent. | Yes — the parent must be done or skipped |
ai_model, provider, think_mode, execution_mode | Per-ticket settings; omitted → inherit from the project | — |
deps_include_awaiting | The flow: 1 relaxed (default) · 0 strict — see §4.9 | — |
is_forced | Forced start (Start Now / Force Next / codehero_start_ticket): the ticket starts NOW on an extra worker slot, ignoring its sequence, its dependencies, its parent and the slot limit. For an observer ticket or a small change while the plan runs; the flag stays, so a forced observer restarts after every reply. | overrides everything |
ticket_type, priority | feature / task / bug …; low / medium / high / critical | Priority only orders eligible tickets |
How the daemon picks the next ticket per project: the lowest sequence number that still has an unfinished ticket → among the tickets of that number: status open (or new/pending) → retry cooldown elapsed → every dependency done/skipped → parent done/skipped → forced first, then creation time → as many as the free slots allow. Nothing of a higher number is even considered.
Titles are triggers. [PLAN], [REPLAN], [VERIFY], [FIX], [HELPER], [PEER] make the daemon pre-load the matching guide into the ticket's context. Keep the prefix exactly.
Adding tickets to a project that already has some: explicit sequence numbers in a bulk call are auto-offset to continue after the existing ones; codehero_create_ticket stores the number you give — that is how a verifier puts its fix at its own sequence.
4.7 Serial first; parallel as an offer; the file-ownership analysis
Design every plan serial. A serial run cannot corrupt shared files, and every ticket starts from the previous ticket's verified, reported state. The cost is wall-clock time; the benefit is correctness and a clean audit trail.
When some tickets are truly independent (different pages, different API folders, different components, different test files, different migration files), the planner may offer a group: "Tickets 4, 5, 6 touch different files and could run together — parallel? (yes/no)". Only an explicit yes turns it on (a request that already asked for parallel counts as yes). Then the analysis is mandatory:
- For every ticket in the group, list the exact files and folders it will create or edit. The ticket owns them; the list goes into its description; the agent may not touch files outside it (global H6).
- Check the danger files by name against every ticket in the group:
index.php/index.html,app.js/main.*, routing tables,package.json/composer.json/requirements.txt,.env/ config, DB migrations, global CSS, shared header/footer includes. - Zero overlap is required. Any overlap → serialize (
depends_on+ differentsequence_order), split the ownership, or merge into one ticket. - Show the ownership table in the preview. Maximum 5 tickets per group. In any doubt → serial.
Two exceptions need no approval: [VERIFY], [PEER] and [HELPER] tickets may share a sequence_order with the ticket they serve, because they are forbidden to write product files; and the [FIX] tickets a verifier creates at its own sequence while it parks and waits for them (§5.9).
4.8 The ticket description recipe (every ticket, both modes)
The executing agent sees only the ticket text plus the project context. A description that assumes the reader was in the planning conversation is a description that will be misread. Five parts:
- Objective — what to build, concretely, and the requirement IDs it serves.
- Where — the files and folders this ticket owns.
- Contracts — endpoints, table and column names, response shapes, shared formulas that other tickets rely on. Shared things are written before either side is built (P6,
guides/planning.mdstep 5: contracts first). - Environment facts — services at
localhost:<port>, credential placeholders, the preview URL shape. Never a container name or an internal IP; never the word "container". - Definition of done — how the agent verifies: what to run, which page to load, what the expected output is. Testable sentences, not adjectives.
Three text rules from the Planning Guide, worth repeating because they are the ones most often broken by hand-written tickets: self-contained, localhost only, application, not infrastructure.
4.9 Execution mode and flow
| Execution mode | Behaviour | Use when |
|---|---|---|
autonomous (default) | No permission prompts; the permission hook still enforces path protection and loop detection | Trusted work, the normal ADF run |
semi-autonomous | Auto-approves file operations inside the project, tests, builds, lockfile-only installs, read-only git; asks for new package installs, npm/composer update, migrations, git writes, service restarts, network calls; blocks system files, .git internals, anything outside the project | Projects that need guardrails; approvals can be generalized with "Approve all similar" |
supervised | Asks before every write, edit and command | Sensitive projects; learning how the agent works |
| Flow | deps_include_awaiting | What changes |
|---|---|---|
relaxed (default) | 1 | When the agent finishes, the ticket parks in awaiting_input, the auto-reviewer classifies it (COMPLETED / QUESTION / ERROR) and closes it to done on COMPLETED after a short delay |
strict | 0 | The ticket parks in awaiting_input with reason completed and a human closes it |
Note what relaxed does not do: it does not let a ticket in awaiting_input satisfy a dependency. Dependencies always require done or skipped.
4.10 The two previews
The assistant's preview (before anything exists):
⚙️ Settings
• Project: <name> (<type>, <path>) — <stack> · Environment: <deployment_mode> [services: …]
• Execution: <mode> · Flow: <relaxed → deps_include_awaiting: true | strict → false> · Strategy: <…> · Parallel: <serial-only|allowed> · Plan approval: <autonomous|you approve the first stage>
• Planning ticket: <provider> · master_developer · ultra
📄 Specification — <readiness state> · review: <what was actually done>
• Scope (MVP): … · Later / parked: … · Assumptions I made: … · Open items: <item → owner → what it blocks>
• Day-0 inputs you must provide: <what → who → when it is needed>
▶️ What happens after you confirm: project [+ environment] + ONE planning ticket …
Do you agree? (yes / no / changes)
The planning ticket's plan (in its final report and in .specs/001-project-plan.md): the run settings in one line, then the ticket table (# · ticket · seq · provider · role · think · deps · files owned · verify), plus three honest lines — what the dry run found, what the review rounds changed and how many really ran, and the peer verdict (or "no second provider"). With plan_approval: autonomous it creates the phase right away and reports NEEDS THE USER: no; with owner-approves-first-stage it asks "Should I create the tickets?" and waits.
Read a plan like a reviewer, not a spectator: is the first milestone the thinnest end-to-end slice? Does every [VERIFY] use a different provider family? Is every visual ticket on a vision-capable provider? Does every dependency express a real need? Is anything in it that nobody asked for?
4.11 Worked plan: RepairFlow, phase 1
Assume the installation's active providers are anthropic (vision), deepseek (no vision), gemini (vision). The package is Ready to build. The plan table the planning ticket produced for phase 1 (its own [PLAN] ticket is not in the table):
⚙️ Settings:
• Project: RepairFlow (web, /var/www/projects/repairflow) — PHP 8.3 + MySQL, no container
• Providers: anthropic, deepseek, gemini · Strategy: balanced
• Execution: autonomous · Flow: relaxed
• Day-0 inputs: SMTP account for notifications (client) · first Owner account details
| # | Ticket | Seq | Provider | Role | Think | Deps | Files | Verify |
|----|-----------------------------------------------------|-----|-----------|--------|----------|------|-----------------------------------------|--------|
| 1 | Capability probe: runtimes, DB access, preview URL | 1 | deepseek | senior | basic | - | .specs/000-probe.md | - |
| 2 | Knowledge foundation: store architecture + rules | 2 | deepseek | master | balanced | 1 | .specs/, knowledge base | - |
| 3 | Application setup: bootstrap, schema, seed, header | 3 | anthropic | master | balanced | 2 | includes/, database/, .env.example | ✓ |
| 4 | [VERIFY] Application setup | 4 | gemini | master | ultra | 3 | (checks only) | - |
| 5 | Access gate: login + empty job list on preview URL | 5 | anthropic | senior | balanced | 3 | login.php, index.php, includes/auth.php | ✓ |
| 6 | [VERIFY] Access gate | 6 | gemini | master | ultra | 5 | (checks only) | - |
| 7 | Core slice: create job → change status → deliver | 7 | anthropic | senior | balanced | 5 | jobs/, includes/JobService.php | ✓ |
| 8 | [VERIFY] Core slice (incl. negative tests) | 8 | deepseek | master | ultra | 7 | (checks only) | - |
| 9 | Overdue rule + daily notification (outbox, cron) | 9 | deepseek | senior | balanced | 7 | cron/overdue.php, includes/Mailer.php | ✓ |
| 10 | [VERIFY] Overdue + notification | 10 | anthropic | master | ultra | 9 | (checks only) | - |
| 11 | [REPLAN] check phase 1 and plan phase 2 | 11 | anthropic | master | ultra | 9 | .specs/, tickets | - |
📊 anthropic=5, deepseek=4, gemini=2 · 💰 medium · ⚡ Flow: serial
Do you agree? (yes / no / changes)
Points to notice:
- The probe and the knowledge foundation come first; the access gate (login + empty list on the preview URL) proves the whole path before any feature; the core slice is the product's purpose (a job moves through its states); the overdue rule is the first business rule with money-like consequences and gets a VERIFY on a different family.
- VERIFY tickets alternate families (gemini checks anthropic; deepseek checks anthropic; anthropic checks deepseek) and are always
master+ultra. Ticket 8 is on deepseek because checking a job workflow is logic, not visuals; ticket 4 and 6 are on gemini because they check pages. - The last ticket is the
[REPLAN]: it compares the real project with the baseline plus the change ledger (aligned / missing / wrong / not asked for), repairs first if needed, then plans and creates phase 2 — without asking for approval again, because the operator approved the plan with that ticket in it. It asks only if the scope must change. - Everything is serial. Ticket 9 could have been offered in parallel with a hypothetical "job sheet PDF" ticket (different files), but the planner did not offer it: both touch
includes/and the offer would have needed an ownership split. In doubt → serial.
4.12 Two ticket descriptions from that plan
Ticket 3 — Application setup (master_developer, balanced):
Objective (R001, R010, R011): create the application foundation for RepairFlow.
- includes/config.php: the canonical bootstrap (env → session → PDO → CSRF → helpers → error handler)
exactly as the project context prescribes. Read DB_* from .env; commit .env.example only.
- database/schema.sql: tables customers, technicians, jobs, job_status_history, job_helpers,
users (roles: owner, front_desk, technician). Money = DECIMAL(10,2). Every table has id,
created_at, updated_at; FKs indexed; ON UPDATE CASCADE everywhere; job_status_history keeps
who/when/from/to (no silent overwrite).
- database/seed.sql: one user per role (test passwords in .specs), 3 technicians, 5 customers.
- includes/header.php + includes/footer.php with the shared navbar (relative links only),
libs/ copied from /opt/codehero/libs (tailwind, alpine, fontawesome with webfonts).
Owned files: includes/, database/, libs/, webfonts/, .env.example, .specs/003-setup.md
Contracts other tickets rely on:
- jobs.status ENUM('received','in_repair','ready','delivered')
- jobs.deadline DATE = received_at + 14 days (computed on insert by JobService, never by the UI)
- helper functions e(), csrf_field(), csrf_check(), requireAuth(?string $role)
Environment: MySQL at localhost:3306, credentials in the PROJECT DATABASE block.
Preview URL: https://127.0.0.1:{PROJECTS_PORT}/repairflow/
Definition of done:
- php -l passes on every file; schema.sql applied without error; seed rows present (SELECT COUNT).
- Loading the preview URL returns the header/footer skeleton with 0 console errors and 0 requests ≥ 400.
- .specs/003-setup.md acceptance list walked item by item; knowledge stored: schema decisions,
status enum, deadline rule (type: decision) with WHY.
Ticket 4 — [VERIFY] Application setup (different provider, master_developer, ultra, parent_sequence = 3, so the platform gives it parent_ticket_id and makes it wait for ticket 3; guides/verify-fix.md is pre-loaded):
cycle 1 · GUIDE: verify-fix.md
You only CHECK. You never edit code and never "improve" anything.
Parent: your parent_ticket_id (codehero_get_ticket on your own id). Its SPEC FILE: .specs/003-setup.md.
Walk the parent's ACCEPTANCE list item by item, run the CORE Section 9 recipe on the preview URL
and `bash .tests/run.sh`. Add your own negative checks: a page without the bootstrap must not exist;
the DB DSN must include charset=utf8mb4; PDO must use ERRMODE_EXCEPTION; a second run of schema.sql
must fail cleanly, not corrupt data; no absolute URLs in header/footer.
A FINDING = a requirement not met or a reproducible bug, with steps, expected, observed.
Style preferences are not findings (one line at the end at most).
No findings → VERIFY: PASS line on the parent's SPEC FILE, report "verified: pass" with evidence.
Findings → create ONE [FIX] ticket for the original builder at YOUR sequence_order (same provider
and role as ticket 3, no depends_on), park with ⏸ WAITING-FOR-TICKET #<fix id>, and re-check the
findings yourself when the fix replies (cycle 2). Circuit breaker after 3 cycles.
4.13 After creation
Use codehero_get_project_progress (or the Project Progress page) to see the tickets with their roles and providers; codehero_update_ticket to change a ticket's role, provider, think mode or status; codehero_set_ticket_sequence to reorder. The agent will create its own VERIFY, fix, helper and replan tickets during the run — expect the list to grow, and check that each new ticket follows the same rules (Module 5).
Exercises — Module 4
- Import the package from your Module 2 exercise into Plan with AI. Before saying yes, write down three things you would change in the preview and why. Apply them with "changes", then confirm.
- Write the full five-part description for ticket 7 of the RepairFlow plan (the core slice), including the contracts the overdue ticket will rely on.
- The planner offers to run "Customer list page" and "Technician list page" in parallel. Do the file-ownership analysis: list each ticket's files, check the danger files, decide. Show the ownership table.
- Explain, with the scheduler rules of §4.6, what happens to ticket 9 if ticket 7 ends in
awaiting_inputwith a question. What must the operator do? - A colleague hands you a batch where ticket 1 has
depends_on: [1]. What happens when it is submitted, and how do you fix it?
PART V — EXECUTION
Module 5 — What happens when a ticket runs, and how to read it
5.1 The lifecycle of a ticket
┌──────────── retry (≤ max_retries, cooldown) ────────────┐
│ │
open ──► in_progress ──► agent says TASK COMPLETED ──► awaiting_input ──► done
▲ │ (reason: completed | question | error | permission | stopped)
│ │ crash / exception │
│ ▼ │ relaxed: auto-reviewer says COMPLETED
│ failed ───────── past max_retries ──► failed (sticks) │ strict: a human closes
│ │ │
│ └── rate limited ──► open (after cooldown, not counted as a failure)
│
└──────── user or peer reply, "Retry", "Reopen" ──── awaiting_input (a reply re-opens; a parked ticket whose
awaited ticket ended without replying is woken by a watchdog)
stuck = the watchdog judged the conversation an unproductive loop
timeout = max_duration_minutes exceeded
skipped = manual skip; counts as complete for dependencies (timeout does not)
Facts you will rely on:
- The agent never writes
doneitself. Finishing always parks the ticket inawaiting_inputwith a reason; closing is a review decision (automatic in relaxed mode, human in strict). - The auto-reviewer is a small sub-agent (junior tier of the ticket's own provider) that classifies the last messages as COMPLETED, QUESTION or ERROR. Deterministic rules run before it: the agent's report starts with
NEEDS THE USER: yes/noandOPEN ISSUES AND DOUBTS: …—yesnever closes; a chain ticket ([VERIFY],[FIX],[PLAN],[REPLAN]) withnocloses even though its body talks about another ticket's failures, and the doubts it lists stay on the record for you; a[PEER]/[HELPER]ticket is never auto-closed (the ticket that opened it closes it); a parking marker (⏸ WAITING-FOR-TICKET #id) whose ticket is still live keeps it parked; and a body that flags a problem ("PROBLEM:", "2 failed", "not clean") is ERROR even if it also says TASK COMPLETED. Only relaxed tickets are reviewed; strict ones wait for you. Further rules (v4.49.1): a[PEER]/[HELPER]ticket is never auto-closed (the ticket that opened it closes it); a build ticket whose two lines sayno+nonecloses on those lines (the next[VERIFY]is the real check; a junior reviewer tier marked clean reports as errors); a report without the two lines is judged by the LLM reviewer; a planning ticket cannot create tickets while a peer or helper is open (the platform refuses the call); the two report lines are read at their last occurrence (the Codex CLI stores its progress notes and the report as one message); a subscription window limit reported by the CLI ("You've hit your session limit · resets …") is treated as a rate limit: the notice is not stored as an answer and the ticket retries every few minutes until the window is back. - Any reply reopens. A message from you (UI or Telegram) or from another ticket sets a parked ticket to
open; the daemon resumes the same conversation. A message that lands while the agent is still running reaches it at its next step (inside a tool result, signed📨 FROM TICKET #idwhen it comes from a ticket); if the run ends with a message still unread, the daemon re-opens the ticket instead of parking it — nothing is lost. - Dependencies need
doneorskipped. A ticket sitting inawaiting_inputblocks everything that depends on it. In a serial plan that means the whole project waits for your answer — by design. - Retries: a crash or provider error returns the ticket to
openup tomax_retries(default 3) with a cooldown; a rate limit is not a failure. A ticket you stopped with the kill switch is never overwritten withfailed. - The watchdog checks long-running tickets and asks a sub-agent whether the conversation is truly stuck; the instruction to that sub-agent is to err on the side of continue. Genuine loops become
stuck.
5.2 What the agent sees and can do
The system prompt is the layered assembly of Module 1 §1.6. On top of it the agent has two tool families:
Built-in tools (HeroAgent) — with the policy their own cheat-sheet teaches the model:
| Tool | Use it for | Policy |
|---|---|---|
Read, Write, Edit, MultiEdit | Files | Read before edit; files over 500 lines: Grep first, then targeted Read |
Glob, Grep | Finding files and text | Instead of find / grep via Bash |
Bash | Commands | Last resort — prefer the dedicated tools; foreground only; run_in_background is denied |
ProcessManager | Long-lived services (dev server, API) | Instead of nohup … &; survives the turn |
HttpRequest | API calls, CSRF flows | Instead of curl; sessions persist |
Browser | Functional flows: goto, click, fill, wait_for, get_text, eval, console_logs, network_logs | The only way to test pages; sessions persist across calls |
PageAssert | Structured checks: visible, contrast, no console errors, no broken images | Works without vision |
LogTail | Server logs by named source (nginx-error, php-fpm-8.3, mysql-error, …) | Instead of tail / journalctl (no sudo prompts) |
WebFetch | Reading documentation pages | — |
GetCached | Re-reading a large tool result that was summarized | — |
Platform tools (MCP, codehero_*) — the ones the global context makes mandatory: codehero_knowledge_search / codehero_knowledge_store / codehero_knowledge_list (the knowledge base), codehero_git_operations (backup_snapshot, backup_status, backup_restore, …), codehero_screenshot, codehero_extract_context, codehero_get_guide (opens one of the ten guides), and the ticket tools codehero_get_ticket / codehero_update_ticket (reply, close) / codehero_create_ticket / codehero_get_project_progress / codehero_start_ticket (forced start). Every MCP result of a ticket agent also carries the messages other tickets wrote to it while it worked.
The permission hook sits between the model and every tool call. It enforces the execution mode (Module 4 §4.9), path protection (H5: only {web_path}, {app_path} and /tmp), container routing, the background-Bash denial, the malformed-edit guard, and loop detection: an identical action repeated three times returns a "you appear to be stuck — stop and rethink" message to the model; at five it hard-stops the approach. Read-only waiting (polling a ticket, a bare sleep) is exempt, so a parked dialogue is not mistaken for a loop. HeroAgent adds per-tool error counters (warn at three consecutive failures, break at five) and a cap of 1000 iterations per run.
Container projects. The agent's commands are routed inside the container by the platform (the crun wrapper). The agent does not know and must not be told; it works on "a normal server" where services are at localhost.
5.3 The work loop the agent follows (global §5)
- Understand the task (apply the language rule).
- Search the knowledge base — one broad query with the task title, one per component — then read the relevant code.
- Open the SPEC FILE (
.specs/<NNN>-<task>.md), always, even for an easy task: GOAL and STATUS before any code. Open questions → ask now, in one batch, or apply a safe default. (A small change or fix — one concrete thing, no new page, table or feature — runs the light loop: a two-line SPEC FILE, only the guide of the thing touched, verify that thing,bash .tests/run.sh, snapshot, a five-line report. No plan mode, no rounds, no peer.) - Build one small part.
- Verify that part (§5.5). Fails → debugging protocol (§5.6).
- Update the SPEC FILE, then snapshot. After every part, not only at the end.
- Parts remain → back to 4.
- Full test on the PREVIEW URL, then
bash .tests/run.sh(ALL repeatable tests — the runner.tests/run.shis installed by the platform in every project), then walk the ACCEPTANCE list item by item: pass, fail, or BLOCKED with the reason. - Store knowledge: decisions and failed approaches.
- Report — two lines, then the 4-part handoff (§5.8), then
TASK COMPLETED.
Long task? After a verified part the agent may call codehero_extract_context to compress old messages; the SPEC FILE survives compression and is re-read right after. The platform also compacts automatically when the conversation grows past its thresholds, and shows a visible compaction message in the ticket. This is why P6 (memory on disk) is a principle and not a suggestion: everything the next step needs must already be in .specs/ or the knowledge base.
5.4 Two memories
SPEC FILE (.specs/NNN-name.md) | KNOWLEDGE BASE (graph) | |
|---|---|---|
| Scope | This task | The whole project, forever |
| Content | GOAL · APPROACH · FILES & CONTRACTS · DATA FLOW · RISKS · ACCEPTANCE · OPEN QUESTIONS · STATUS (live: ✔ done · ▶ doing · ☐ pending · NEXT:) | Nodes: decision, failed_approach, pattern, bug, service, component, class, method, file, library, api_endpoint, config, spec, milestone. Edges: uses, depends_on, fixed_by, calls, failed_for |
| Written when | Before coding, after every part, at the end | The user says "remember"; a command failed then worked (💡 TEACHABLE MOMENT); a non-obvious choice between approaches; architecture designed |
| Read by | The agent after compaction ("if you feel lost, re-read the SPEC FILE first"), the VERIFY ticket, the next ticket | Every ticket at start; the hint system (🚨 known dead ends for a file about to be edited) |
| You read it in | Project Files / File Explorer | codehero_knowledge_list / codehero_knowledge_search from the AI Assistant, and the knowledge snapshot at the top of each ticket's system prompt |
Every failed_approach must have a failed_for edge to the component it hurt (component name = file basename without extension). The next time any ticket edits that file, it sees the dead end. Teach your trainees to check the graph after a run: a project with zero decision nodes after ten tickets is a project whose agents are not following §7 — a context problem, not a model problem.
5.5 The verification recipe (global §9) — what "evidence" concretely means
- Syntax checks:
php -l,python3 -m py_compile,node --check,tidy. - Browser recipe on the PREVIEW URL:
goto→ exercise the key actions →console_logs(must be 0 errors) →network_logswith status ≥ 400 (must be empty) →PageAssert(no console errors, no broken images, key elements visible) →LogTailonnginx-errorandphp-fpm-8.3. - If the project has login: test the logged-in state (UI path and API/CSRF path) AND the refusals with a positive control (
guides/testing.md); the ticket that delivers login creates the test user. - Deliveries need proof: an email, webhook or export is "sent" only with a receipt, a log line, an outbox row or a test inbox. Otherwise "attempted, unverified" or BLOCKED.
- Expected results come from outside the code: the request, the acceptance list, the user. "The function returns 42 and my test expects 42 because the function returns it" proves nothing.
- Every interactive element carries a
data-testid({action}-btn,{field}-input,nav-{page}, …) so that VERIFY tickets on other providers can find it.
Preview-URL rules the agent must not "work around": a 403 on the bare root means the project folder is missing from the URL (per-project auth, expected); a 400 on plain http:// means the scheme is wrong (it is HTTPS). Neither is a bug; both mean "fix the URL and try the same shape again". Never php -S, never another port, never localhost instead of 127.0.0.1.
5.6 The debugging protocol (global §8 + guides/debugging.md)
Snapshot → reproduce once → collect evidence in order (browser console, network ≥ 400, nginx-error, php-fpm, mysql-error) → locate the first point where reality differs from expectation along request → handler → logic → storage → response → page → one hypothesis → one targeted check → fix the root cause → verify (re-run the reproduction, then the full recipe). Maximum five hypotheses; after five: restore the snapshot if things got worse, re-read the SPEC FILE, optionally open a HELPER ticket on another provider, then simplify to the smallest version that works and add pieces back one at a time.
Rules that catch most real incidents: never run the same failing check twice hoping for a different result (that is the loop the hook detects); change one thing at a time; never weaken the WAF, auth, CSRF or validation to pass — bisect the payload and fix the request; a check that was green and is now red is a regression and jumps the queue; "200 but wrong behaviour" is a logic bug in the agent's own code, not the tool; and if the agent can explain why the code behaves as it does but not what the correct behaviour is, that is a missing business rule → stop and ask.
The symptom table in §8 of the global context (blank PHP page → php -l + php-fpm log; 404 on assets → absolute URL; login "works" but logged out → session write/read; form submits, nothing saved → name= mismatch; POST returns 403/406 while the page loads → WAF rule, bisect the payload) is the first thing to teach a trainee who will read transcripts: most "stuck" runs are one of these.
5.7 When the agent stops to ask — and how you answer
The agent asks only for business rules (P3), destructive actions (H7), missing credentials, or the "should I create the tickets?" gate in PLAN MODE. The format is fixed (global §4.1): one to three lines of what it understood and decided, then numbered questions with options and a recommendation, answerable as "1A, 2B, 3 yes". Before asking you, it should have filtered the questions through a HELPER ticket on another provider (P4) and told you in one line what the helper settled.
Your side of the protocol:
- Read the ticket's last message in the Ticket Detail page (or the Telegram notification).
- Answer every numbered question in one reply, in the same numbering. Do not answer technical questions the agent should have decided itself — tell it to decide ("2: your call, record it in the SPEC FILE").
- If the question is a business rule you do not know, get it from the client and record it in the specification's Decision Log too; the package is the source of truth, not the chat.
- Send. The ticket reopens; the agent writes the answer into the SPEC FILE and stores lasting rules in the knowledge base; it must never ask an answered question again.
If the same question keeps coming back across tickets, the answer is not on disk: check the knowledge base and the project description, and fix that rather than answering again.
5.8 The report: two lines, then four parts
Every finished ticket ends with a report written for you and read by the auto-reviewer. It starts with two lines in English:
NEEDS THE USER: yes — <what>orNEEDS THE USER: no— yes means the next tickets must wait for you: a critical question, a destructive-action doubt, an approval, a failed or blocked part that later tickets build on.OPEN ISSUES AND DOUBTS: <numbered list>ornone— a part that failed, could not be verified, is blocked, or a result the agent is not sure of. Never hidden to get closed (that is faking a check), never invented (empty hedging holds the plan for nothing).
Then four parts, in this order:
- What works now — with the evidence (which test ran, which URL loaded, which screenshot).
- What is waiting for the user — blocked parts with the exact ask (credentials, decisions), one consolidated ask per service.
- What was decided on your behalf — technical choices worth knowing plus every SAFE DEFAULT, each reversible with one line.
- What stays open — known limits, deferred parts, what the next ticket must know.
Part 3 is where you spend your attention: each safe default is a business assumption you can overturn with one sentence. Part 2 tells you what to chase from the client. A report without evidence in part 1 is a report to distrust — check the SPEC FILE acceptance list and the screenshot. A report that ends with a polite question ("Should I also…?") means the agent needs you — the guides forbid it precisely because it stops the plan.
5.9 Verification and the repair loop — one verifier owns the episode
- [VERIFY] ticket (different provider family,
master,ultra,parent_sequence/parent_ticket_id= the builder;guides/verify-fix.mdpre-loaded): walks the parent's acceptance list, runs the recipe andbash .tests/run.sh, writes its own negative tests, writes only its own SPEC FILE and test files. Findings are numbered with steps, expected and observed; style preferences are not findings. A group verify names several parents (one ticket after the last of them). - No findings →
VERIFY: PASS · cycle 1on the parent's SPEC FILE, reportNEEDS THE USER: no. The reviewer closes it; the plan goes on. - Findings → the verifier creates ONE
[FIX] <parent title> (#<parent id>, cycle 1)per parent with findings — the original builder's provider and role, at the verifier's ownsequence_order, with nodepends_on— writesVERIFY: FAIL · cycle 1 · … · fix #<id>on the parent's SPEC FILE, and parks:⏸ WAITING-FOR-TICKET #<fix id>. A parked verifier keeps its sequence unfinished, so the fix runs at once and everything behind waits. - The fix fixes only the listed findings, each with a repeatable test that fails before and passes after; a finding it disagrees with is
DISPUTEDwith a proof. When done it writesFIX: done · cycle 1on the parent's SPEC FILE and replies to the verifier (codehero_update_ticket(ticket_id=<verifier>, reply="FIX done — cycle 1 — fix #<id>")) — the reply wakes the verifier. It never creates a verify ticket. - The verifier wakes (cycle 2), re-checks only the findings (plus the acceptance items they touch and the test suite), and either writes
VERIFY: PASS · cycle 2and reports, or opens cycle 2's fix and parks again. - Circuit breaker: the same part failed three cycles, the same acceptance item failed twice in a row, or builder and verifier disagreed twice on a finding → the verifier stops, writes
CIRCUIT BREAKERon the record, reportsNEEDS THE USER: yeswith both views, and stays open until you decide (your decision is recorded asUSER DECISIONand a fresh count starts).
The cycle record lives on disk in the parent's SPEC FILE (VERIFY: / FIX: lines, append-only; the last VERIFY: line decides), because every fix is a new agent with an empty memory and the verifier itself may be restarted. When you see a [FIX] appear at the verifier's sequence, do nothing; it is the loop working. When you see the same part fail a third time, expect the breaker and prepare to arbitrate.
5.10 Helper tickets and the walkie-talkie
Any ticket may open a [HELPER] on another provider when it is truly stuck (step 8 of debugging), when two approaches failed and it cannot choose, when one design decision blocks everything behind it, or when questions are about to go to the user (the AI-before-human filter). Rules (guides/helper.md): helpers never write files and never create tickets; the ticket that opens a helper closes it (status="closed") before its own TASK COMPLETED; at most two open at once, on different providers; three exchanges without agreement → both views go to you. A helper can find an answer that exists in the material and judge a technical trade-off; it can never invent a business fact.
The messaging protocol is simple and the platform does the delivery. codehero_update_ticket(ticket_id=<other numeric id>, reply="...") sends; the platform signs it (📨 FROM TICKET #<id> (<number> · <title>)), so a message without a signature is from a human. A working ticket receives it at its next step — through its own mid-run check, inside the next MCP tool result, or (Claude CLI modes) through a PostToolUse hook — within seconds. A parked ticket (⏸ WAITING-FOR-TICKET #<id>, several ids allowed: the first reply wakes it, it parks again for the rest) is woken by the reply. A ticket that ends its turn with a message still unread is re-opened at once by the daemon. A parked ticket whose awaited ticket(s) ended without replying is woken by a watchdog with a 📨 SYSTEM note, so nothing waits forever.
In the ticket list this looks like: a build ticket in progress, a [HELPER] or [PEER] ticket on another provider with the same sequence number, the two exchanging numbered findings, then the helper closed by its initiator before the initiator says TASK COMPLETED. An open helper left behind after its initiator finished is the initiator's mistake — and it holds every later sequence.
5.11 The replan ticket
The [REPLAN] ticket ends every phase of a real project. It builds nothing: it reads the baseline plus the change ledger (.specs/000-changes.md), looks at the real project (code, SHOW CREATE TABLE, the pages on the preview URL, bash .tests/run.sh) rather than at reports, and writes a comparison table both ways — every due requirement → where it lives and what proves it; everything built → which requirement asked for it — with aligned / missing / wrong / not asked for / unknown / not yet due. Then one of four decisions: ALIGNED → plan the next phase (same rules: contracts, value order, dry run, about ten review rounds, peer check); REPAIR NEEDED → a phase of repair tickets (+ their [VERIFY]) ending with a new [REPLAN], no new features until a replan says aligned, and a circuit breaker after three repair rounds on the same requirement; NEEDS THE USER → one batch of questions and stop; BLOCKED → say what is missing. It never edits the baseline to match the code. It does not ask for approval again — the approved plan contained it — unless the scope must change. The last replan of a project is the final check.
5.12 Operator's controls
| Control | Where | Effect |
|---|---|---|
| Send Message | Ticket Detail → message box, or Telegram | Reopens the ticket (if awaiting) and continues the same conversation |
| Stop (kill switch) | Stop button or /stop | Pauses immediately; ticket parks in awaiting_input (reason stopped) and waits for your correction |
| Retry / Reopen | Ticket actions | Returns a failed or finished ticket to open |
| Start now / Force next | Ticket actions or codehero_start_ticket | Forced start: runs the ticket NOW on an extra slot, ignoring its sequence, dependencies, parent and the slot limit; the flag stays (an observer ticket restarts after every reply) |
| Skip | Ticket actions | Marks it skipped — satisfies dependencies |
| Close | Ticket actions or codehero_update_ticket(status="closed") | Sets it to done (there is no separate closed status) |
| Change role / provider / think mode | Ticket edit or codehero_update_ticket | Applies to the next run |
| Restore a snapshot | Git Manager / Backup | Rolls the project files back |
| Permission banner | Ticket Detail (semi-autonomous / supervised) | Allow, Deny, or "Approve all similar" |
5.13 Reading a run like an operator — a checklist
For every finished ticket:
- ☐ The report starts with
NEEDS THE USER:andOPEN ISSUES AND DOUBTS:, has the four parts, and part 1 cites evidence you can open (a screenshot, a URL, a test name). - ☐ The SPEC FILE's ACCEPTANCE list is walked; every item is pass or BLOCKED with a reason; nothing was deleted to look green.
- ☐
.specs/STATUS shows the final position;NEXT:is empty or points at the next ticket. - ☐ The knowledge graph gained the decisions and dead ends the ticket mentions.
- ☐ No helper or peer ticket was left open.
- ☐ The snapshot of the final state exists (
backup_log). - ☐ If the ticket asked something: the question is a business rule, not a technical choice; it came in one batch; a helper filtered it first.
- ☐ If a VERIFY ticket produced findings: exactly one
[FIX]per parent exists at the verifier's sequence, the verifier is parked on it, and no later sequence started.
Exercises — Module 5
- Create a throwaway project by hand (a project and one build ticket: one PHP page with a form that stores a row). Run it in supervised mode and approve each call. Write down every tool the agent used and which layer of the context told it to use that tool.
- Run the same ticket in autonomous mode. Compare the transcript: find the SPEC FILE creation, the snapshot calls, the verification recipe, the knowledge store, the 4-part report. Mark any step it skipped and cite the global section it violated.
- Deliberately create a ticket whose description omits a business rule (e.g., "apply the discount" without saying how). Observe the stop-and-ask. Answer it in the "1A, 2B" format and watch the reopen. Then check that the answer landed in the SPEC FILE and the knowledge base.
- Create a
[VERIFY]ticket by hand for exercise 1's ticket (different provider, master, ultra,parent_ticket_id= that ticket). Read its findings. If it produced a[FIX], check its provider, sequence and the verifier's parking marker against §5.9; watch the verifier wake and re-check. - Trigger the loop detector on purpose (a ticket told to "keep running the failing test until it passes" on a test that cannot pass). Find the hook's message in the transcript and the moment the agent changed approach or stopped.
- Explain to a colleague, using the lifecycle diagram, why a serial plan with one ticket in
awaiting_inputshows all later tickets as "waiting", and why that is correct.
PART VI — CUSTOMIZING THE BRAIN
Module 6 — Building your own logic with the global context and the project context
6.1 The layers, where they live, and who reads them
| Layer | Source file (edit here) | Installed copies | Read by | Scope |
|---|---|---|---|---|
| Global context core | config/global-context.md | /opt/codehero/config/global-context.md (defaults for new projects and the context-defaults API) and /etc/codehero/global-context.md (the assistant's copy) | The executing agent, as === PROJECT GLOBAL CONTEXT === (the project's stored copy) | Every project |
| Guides | config/guides/*.md | /opt/codehero/config/guides/ (served by the MCP tool codehero_get_guide; never copied per project, so an edit reaches every ticket at its next call) | The executing agent, on demand by trigger; pre-loaded by the daemon for [PLAN] [REPLAN] [VERIFY] [FIX] [HELPER] [PEER] tickets | Every project |
| Language / project context | config/contexts/<stack>.md | /opt/codehero/config/contexts/<stack>.md | The executing agent, as === PROJECT CONTEXT === | Every project of that stack |
| Per-project stored copies | — (DB: projects.global_context, projects.project_context) | Copied from the two files above at project creation, with {PROJECTS_PORT}, {ADMIN_PORT} and {PROJECT_FOLDER} resolved | The executing agent | This project only |
| Project description and info | UI: Project Settings (projects.description, projects.context) | — | The executing agent (PROJECT DESCRIPTION, PROJECT INFO) | This project — the right home for the package's Mandate and run settings |
| Ticket | UI or MCP (tickets.description, tickets.context) | — | The executing agent | This task |
| Knowledge base | The agents themselves (and you, by telling a ticket or the AI Assistant to "remember" something) | DB graph | Every ticket at start, plus the hint system | This project, evolving |
| Assistant templates | config/assistant-{general,planner,progress,help}.md | /etc/codehero/assistant-*.md | The in-app assistant modes | The assistant, not the tickets |
Three facts decide how a change propagates:
- New projects copy the current files at creation. Existing projects keep their stored copies until you open Project Settings → Context, edit, or load the defaults again. This is a feature (a project's rules do not change under a running plan) and a trap (you deploy a fix and old projects do not get it).
.mdfiles are read fresh: the daemon reads the project's stored copy per ticket; the planner reads its template per session;codehero_get_context_defaultsreads the files per call. No service restart is needed for context changes — only the copy to the installed paths.- Placeholders are resolved on the global context only. Write
{PROJECTS_PORT}and{PROJECT_FOLDER}there; never a literal port. The per-language files carry no placeholders (they use{web_path}only as a name in prose).
Deployment of a context change on a server:
# global: source → installed defaults AND the daemon/assistant copy
sudo cp /home/claude/codehero/config/global-context.md /opt/codehero/config/global-context.md
sudo cp /home/claude/codehero/config/global-context.md /etc/codehero/global-context.md
# per-language: source → installed defaults
sudo cp /home/claude/codehero/config/contexts/php.md /opt/codehero/config/contexts/php.md
# guides: source → installed (read by codehero_get_guide)
sudo cp /home/claude/codehero/config/guides/*.md /opt/codehero/config/guides/
# assistant templates
sudo cp /home/claude/codehero/config/assistant-planner.md /etc/codehero/assistant-planner.md
Installed copies are overwritten by setup.sh / upgrade.sh; keep your customizations in the source tree (or a fork) and re-apply after upgrades.
6.2 Which layer for which rule
| Kind of rule | Put it in | Not in |
|---|---|---|
| The method: how to plan, build, verify, ask, report; hard rules; debugging; knowledge; verification doctrine | Global context | A ticket (it would apply to one task only) |
| Stack idioms: the canonical bootstrap, the one way to do sessions/DB/CSRF/uploads in this language, the "silent mistakes" of the language | Language context | Global (it would bloat every project) |
Company-wide conventions that apply to every stack (documentation files, naming, accessibility floor, a required CHANGELOG.md) | Global context, §11 (code rules) or §13 ("Documentation you maintain") | Language contexts (you would repeat it 16 times) |
| This project's facts: folder map, existing conventions of an imported codebase, test command, "do not touch" list, the client's Mandate and run settings | Project context (stored copy) and project description | Global |
| The client's business rules, formulas, permissions, worked examples | The specification package → project description (Mandate) + knowledge base (decision / spec nodes) + each ticket's Contracts section | Global or language context (they are not rules of the method) |
| One task's objective, owned files, definition of done | Ticket description | Anywhere else |
A rule in the wrong layer is the most common customization mistake: a client's VAT formula in the global context leaks into every other client's project; a method rule in a ticket is forgotten by the next ticket.
6.3 How the global context is written — and why
The current global context (v6.1: a core of about 49 KB plus ten on-demand guides) is written in simple English so that every model, big or small, can follow it. Its conventions are not style; they are what makes weak models comply. Keep them when you add or change rules:
| Convention | Why it works |
|---|---|
| A READ-THIS-FIRST section with a glossary and the 11 most important rules | Small models weight the beginning of the prompt most; the glossary defines every capitalized term once |
| Numbered hard rules (H1–H10), each one paragraph, each with the failure it prevents | A rule with a number can be cited, checked in a review, and referenced from other sections ("Rule H2") |
| Sections that work on their own, cross-referenced by number ("see Section 8") | After compaction the model may only remember a section number; each section must be usable alone |
| IF … THEN … prose and "Never / Always" only for hard rules | Conditionals are executed; adjectives ("try to be careful") are ignored |
| Tables: symptom → most likely cause → first check | The model matches the symptom it sees and gets a concrete first action |
Examples in real values (WHERE id=? vs WHERE id=$id; .specs/001-login-page.md) | Abstract rules are misapplied; concrete examples are copied correctly |
Placeholders ({PROJECTS_PORT}, {PROJECT_FOLDER} — the two the platform substitutes; <web_path> for values the agent fills in) instead of literal values | A hardcoded port in the context is wrong on the next installation |
| Tool names matched by suffix, "a missing lookup tool is not an error" (a missing creation or verification tool is BLOCKED, never skipped) | Runtimes prefix tool names differently; the model must not stop because a name differs |
| Evidence phrasing ("Done = a test ran, a page loaded, a row exists") | Defines "done" operationally so it cannot be satisfied by text |
| Per-language contexts defer to the global ("loads AFTER the Global Context — all global rules still apply"; "per Global Section 11") | No duplication, no contradiction, smaller prompts |
Size matters. The core is about 49 KB (roughly 12K tokens) and is sent with every ticket; a guide is paid only by the tickets that need it (planning 36 KB, verify-fix 10 KB, the others 2–16 KB). Every paragraph you add to the core is paid on every ticket of every project: a rule for a recognizable situation belongs in a guide, with a trigger row in core Section 2 — never in the core. Run python3 tests/context/check_global_context.py after every edit (references, trigger table, tokens, tables).
6.4 The rule for changing rules
Every hard rule in the global context names the incident it prevents (H2: processes are killed when the turn ends; H3: hand-inserted rows to pass a test; H6: two tickets editing the same file). A rule added "in case" a model might do something has a cost on every ticket and no evidence it helps; and a defensive rule for a hypothetical failure often makes the model over-cautious about the real work. When a trainee proposes a context change, ask for the transcript that shows the failure. No transcript → no change.
The same applies to removing a rule: find the incident it prevents (git history and the CHANGELOG record most of them) before deleting.
6.5 Worked customization 1 — a company convention in the global context
Observed failure: three projects delivered without any change log; the client's IT could not tell what a ticket had changed.
Change: in §13 "Documentation you maintain", add CHANGELOG.md to the list, and in §5 step 9 add one line: "Append one line to CHANGELOG.md: ticket number · date · what changed." Two sentences, in the two sections where the model already looks for documentation duties. Not a new hard rule (a missing changelog is not a safety failure), not a new section.
Test (§6.9): a probe project on the weakest active model; after one ticket, CHANGELOG.md exists with one line.
6.6 Worked customization 2 — a stack variant (Laravel instead of plain PHP)
The PHP context prescribes plain PHP with PDO and a canonical includes/config.php. A client's team maintains Laravel projects and wants CodeHero to follow their conventions.
Two ways, and you must know both:
- Per project (no platform change). Create the project with a custom project context: call
codehero_get_context_defaults(context_type="php"), take the returnedproject_context, replace the bootstrap/page-pattern sections with the Laravel equivalents (artisan commands the agent may run,routes/web.php, Eloquent + migrations, Blade layouts,php artisan test), keep the "silent mistakes" that still apply, and pass the result asproject_contexttocodehero_create_project. Or paste it into Project Settings → Context after creation. Existing projects can be switched the same way. - A new stack file for every future project. Add
config/contexts/laravel.md. Note that the stack-to-file mapping is code (context_mapinscripts/mcp_server.pyand the matching map inweb/app.py), so a newtech_stackvalue needs a small developer change in both maps plus the UI option; an unmapped stack silently falls back tophp. Until the map is extended, use the per-project route.
Whichever route, the file must keep the header line that states it loads after the global context and defers to it, and it must not restate global rules (relative paths, security, libraries) — reference "Global Section 11" instead.
6.7 Worked customization 3 — the project context of an imported legacy project
An existing PHP application is imported in extend mode. Run codehero_analyze_project first (it builds the project map). Then write, in the project's stored project context, the facts the analysis cannot infer and the agent must not guess (P10):
## This project (imported 2026-09-15, extend mode)
- Framework: none. Front controller public/index.php → app/Router.php. Do not add a second router.
- DB access ONLY through app/Db.php (PDO, already ERRMODE_EXCEPTION). Never create another PDO.
- Sessions are started in app/bootstrap.php; do not call session_start() elsewhere.
- Tests: `vendor/bin/phpunit` (all green at import; a red test is a regression — Rule §8).
- Do NOT edit: vendor/, public/legacy/ (old reports still in use), app/Legacy/*.
- Naming: snake_case for DB, camelCase for PHP, kebab-case for URLs — keep it.
- Known trap: app/Mail.php sends synchronously; new mail goes through the outbox table (see knowledge base: decision "mail-outbox").
Store the same facts as knowledge nodes (component, config, decision) so the hint system shows them when the relevant files are edited. The project context tells the agent; the knowledge base reminds it at the moment it matters.
6.8 Worked customization 4 — an API-only project
The global verification recipe is browser-centred. For a project of type app with no HTML, the api context describes the architecture but the agent still needs an explicit verification recipe. Add to the project context:
## Verification for this API (replaces the Browser part of Global Section 9)
- Start the service with ProcessManager; health check: HttpRequest GET http://127.0.0.1:{PORT}/health → 200.
- For every endpoint in the SPEC FILE's CONTRACTS: HttpRequest the happy path AND one negative
(missing auth → 401, invalid body → 422, other user's resource → 403).
- LogTail(path="{app_path}/logs/app.log", since="5m", level="error") must be empty.
- Run the test suite: `npm test` / `pytest` — 0 failures is the acceptance floor.
- Deliveries (webhooks, emails) need proof per Global Section 9.
You are not overriding the global; you are doing exactly what the global tells native projects to do in §15 ("replaces the Browser part of Section 9. Everything else still applies").
6.9 Worked customization 5 — client business rules
Wrong: adding "VAT is 24% and applies to net, rounded half-up" to the global context.
Right: the rule lives in the specification's §7 with a worked example; the planner copies the Mandate into the project description; the knowledge-foundation ticket stores it as a decision node ("vat-rounding: 24% on net, round half-up to 2 decimals, per R017 example 3"); every ticket that touches money cites R017 in its Contracts section; the VERIFY ticket tests the example values. The agent finds the rule in three places at run time and never has to guess.
6.10 Testing a context change — the protocol
- Diff and size.
diffagainst the previous version; check the file size change. A change that adds more than a few hundred bytes needs a reason. - Keep the version header. The global context's first line names its version; bump it and add one line to the note under it saying what changed and which failure it fixes.
- Deploy to the installed paths (§6.1). No restart needed.
- Create a throwaway project so it receives the new stored copy. Check the copy in Project Settings → Context; check that placeholders were resolved (the preview URL shows the real port and folder).
- Run a probe ticket twice: once on your strongest provider, once on the weakest model you actually use for
junior_developer. The rule must survive the weak one; if only the strong model follows it, rewrite it (shorter, IF/THEN, an example in real values). - Read the assembled prompt the agent actually received: the daemon writes it to
<work_path>/.heroagent/context_<ticket_id>.tmpfor the run. Confirm your text is there, in the section you expected, once. - Read the transcript for the behaviour, not the words: did the agent do the thing (the file exists, the check ran), or did it say it would?
- Roll out to existing projects only where wanted: open each project's Context settings and load the defaults or paste the new text. Running plans keep their old copy until you do.
- Record the change in the repository's CHANGELOG with the incident it fixes.
6.11 Anti-patterns (each one seen in a real run)
| Anti-pattern | What happens | Fix |
|---|---|---|
Contradicting a hard rule from a lower layer ("in this project, you may use git directly") | The model follows whichever it read last, unpredictably | Never contradict H1–H8; change the global if the rule is wrong for everyone |
Literal port or IP in a context (https://127.0.0.1:9867/…, 10.0.3.5) | Wrong on the next installation; container agents try to reach the IP | Placeholders in the global; localhost:<port> from the services block |
| The word "container" in a ticket or project context | The agent starts running lxc/docker commands and breaks | Describe services at localhost; the platform routes commands |
| A rule with no example ("use good security practices") | Ignored by small models, over-interpreted by large ones | One concrete example in real values, one negative example |
| A preventive rule for a failure nobody observed | Costs tokens on every ticket; often makes the agent hesitant on the real work | §6.4: no transcript, no rule |
| Duplicating global rules in a language context | Drift: the two copies diverge after the next global edit | Cross-reference by section number |
think_mode: ultra as a project default | Every trivial ticket burns the maximum thinking budget | balanced default; ultra per ticket for verify/peer/helper |
Referencing a tool that does not exist in this runtime (Screenshot as a built-in) | The model stops or invents | Use the MCP tool names; the global already says "match by suffix; a missing tool is not an error" |
| Business rules in the global context | They leak into every other client's project | Specification → project description + knowledge base |
| A ticket that says "as we discussed" | The executing agent was not in the discussion | Self-contained ticket (Module 4 §4.8) |
6.12 Customizing the planner and the assistants
The same discipline applies to config/assistant-planner.md and the other assistant templates: they are read per session, they are concatenated with the global context (except help), and they carry hard rules at the top. Typical legitimate customizations: a company default strategy (eco), a house rule for provider families in verification, extra preview columns, a different default execution mode for a training installation. Illegitimate: removing the preview-and-confirm gate, allowing inactive providers, making parallel the default. Each of those undoes a principle of Module 1.
Exercises — Module 6
- Take the customization of §6.5 and apply it to your training installation following the §6.10 protocol end to end. Attach: the diff, the assembled prompt excerpt, the transcript line where the agent writes
CHANGELOG.md. - Write a per-project context for a Node/Express project that must use an existing company middleware package for auth. Show which global sections you cross-reference instead of restating.
- Find, in your training installation's projects, one project whose stored global context is older than the current file. Explain how you know, and update it without disturbing a running ticket.
- A trainee proposes adding "Always double-check your work before finishing" to the global context. Argue for or against using §6.3 and §6.4, then propose a version that would actually change behaviour (hint: it already exists — find it).
- Write a rule for the global context that would have prevented this observed failure: "The agent reported an email as sent; the SMTP credentials were placeholders; nothing was sent." Then find the sentence in the v6.1 core that already covers it and compare wording.
PART VII — REACHING A WORKING RESULT
Module 7 — Delivery discipline: from the first ticket to a verified, documented product
7.1 What "working result" means in ADF
Not "the code is written". A working result is: the agreed scope runs on the preview URL (and later on the production domain), every acceptance criterion has evidence linked to it, every business rule was confirmed by the client and is stored where the next ticket finds it, the blocked parts are listed with their exact asks, and the documentation the client agreed to exists in their language. The framework gets you there by ordering the work so that the riskiest unknowns are resolved first and the evidence accumulates as you go.
7.2 The opening sequence: probe → knowledge → access gate → core slice
| Ticket | Purpose | Proof it produces |
|---|---|---|
| Capability probe (#0) | Verify what this installation can actually do: runtimes and versions, DB access, the preview URL, the services block, build tooling declared in the environment block | A SPEC FILE with one line per capability: available / missing. Missing runtime → the run stops with the fallback question (Module 3 §3.9) |
| Knowledge foundation (#1) | Fill the knowledge base with the architecture, the stack, conventions and every key decision from the package, so the graph describes the project from day one | codehero_knowledge_list shows the decisions; later tickets find them at step 2 of the work loop |
| Application setup | Folders, config bootstrap, schema, seed, shared header/footer; in a container: verify the provisioned services and configure the application-level pieces | Schema applied, seed rows counted, skeleton page loads with 0 errors |
| Access gate | The thinnest slice through the real path: login → one protected page → on the preview URL (and, for production deliveries, through the real domain/proxy once it exists) | Screenshot of the logged-in page; PageAssert green; logs clean |
| Core slice | The product's purpose end to end (e-shop: product page → cart → checkout; RepairFlow: create job → change status → deliver) | The acceptance scenarios of the main process pass, with negative tests from the VERIFY ticket |
Only after the core slice is verified do secondary features start (wishlists, branding, dark theme, extra reports). If a client pushes for the logo first, show them this table: the logo cannot fail; the checkout can.
7.3 Milestones and the replan cadence
The Spec Builder sizes the project and sets the cadence (Planning Guide §7.1): S (10–25 tickets, replan after each milestone), M (25–80), L (80–250, batches of about ten). CodeHero executes phase by phase: the planning ticket creates the first phase (about ten tickets), and the [REPLAN] ticket that ends each phase plans the next. Early tickets change what late tickets need; a fifty-ticket plan created up front is a plan that will be wrong by ticket twenty.
Revalidation follows the same cadence: one revalidation per milestone for S; after each contract and each functional piece for M and L, plus a final full revalidation for L.
7.4 Contracts before code
Two tickets that each "decide" a shared thing will decide it differently (guides/planning.md step 5: shared contracts are written before the tickets that consume them). Before any ticket that consumes another's output is created, the shared contract — schema, endpoint, field names, response shape, formula — is written into both SPEC FILES and the knowledge base, and repeated in each ticket's Contracts section. The Planning Guide's chain is contract → revalidate → module: a contract ticket writes it, a revalidation checks it, the modules build against it. A changed contract makes the affected evidence stale; the tests are re-run.
7.5 Evidence and the acceptance manifest
Every acceptance criterion in the package ends with evidence: requirement version, code revision, test ID, environment. The Evidence column of the requirements register is filled only from real test output — never from a ticket's prose. In CodeHero terms: the VERIFY ticket's report, the screenshots (codehero_screenshot), the PageAssert results and the test-runner output are the evidence; the SPEC FILE's ACCEPTANCE list is where the agent records pass / fail / BLOCKED per item.
Two honesty rules the trainer must insist on: a BLOCKED item is visible and never counted as pass; a passive security scan's clean result records what was scanned, not "no problems exist".
7.6 Day-0, touchpoints, and how to keep the client out of the build loop
Before the run: collect the day-0 pack (Module 2 §2.12). During the run: the client is contacted only for the four reasons. Everything else is your job as operator: answer technical questions the agent should have decided (tell it to decide), chase the client only for genuine business decisions, and keep the specification's Decision Log in sync with every answer you relay. A run that stops daily with business questions has an incomplete specification; a run that stops daily with technical questions has a context problem (Module 6); a run that never stops but delivers wrong behaviour has a verification problem (Module 5 §5.9).
7.7 Circuit breakers — when the framework stops itself
| Breaker | Trigger | What you do |
|---|---|---|
| Verify/fix loop | Same part failed three fix→verify cycles; same acceptance item failed twice; builder and verifier disagreed twice | Read both views (the verifier's record lines and the fix ticket); decide; reply to the parked verifier with the decision |
| Replan repair loop | The same requirement still not aligned after three repair rounds | Read the replan's comparison table and the repair tickets; decide whether the baseline or the code is wrong; reply to the replan |
| Debugging | Five failed hypotheses (after a helper was consulted) | Read the SPEC FILE's hypotheses; often the missing piece is a business rule, not a bug |
| Loop detector | Identical actions repeated | The hook already nudged the agent; if it hard-stopped, read the last tool calls, fix the ticket text or the environment, retry |
| Helper dialogue | Three exchanges without agreement | Both views come to you; arbitrate |
| Fallback | Ticket #0 cannot provide the runtime | The fallback changes an agreed capability → requirements change with the client, one line per affected requirement |
| Watchdog | Long unproductive run | Ticket marked stuck; read, correct, retry |
The breakers are not failures of the framework; they are the framework refusing to burn money on a problem that needs a human.
7.8 Documentation deliverables
Always, in the client's language: a user manual per role, an administrator guide, an operations/hosting guide (install, upgrade, backup, restore, monitoring), API documentation when an API exists, and a Decisions document listing everything decided for the client. Inside the project the agent also maintains technologies.md, map.md and the .specs/ files. Plan documentation tickets as junior_developer / basic near the end of each milestone, not as an afterthought at the end of the project.
7.9 From preview to production
The preview URL is where the agents work. Going live is an operator task, done with the platform's tools and documented in the User Guide:
| Step | Where | Notes |
|---|---|---|
| Domain and SSL | Project → Production Deployment; Settings → Domains | Let's Encrypt or custom certificates; the production config is generated per project |
| Web application firewall | WAF setup (see the WAF guide) | Keep it on; the agents are trained to bisect payloads, never to weaken it |
| Backups and restore drill | Project → Backup & Restore; container snapshots | The specification asked for a restore drill executed once — do it before go-live, not after |
| PHP settings | Project → PHP Settings | Development tuning (errors visible, opcache revalidate) vs production values |
| Secrets | .env in the project root, never in code | Real SMTP, payment and API credentials replace the day-0 placeholders here |
| Security gate | The package's automated security tests + the external pentest item | The external pentest is tracked as external-pending; it blocks go-live sign-off only if the client's policy requires it |
7.10 The operator's daily checklist
- ☐ Tickets in
awaiting_input: reason? question → answer in one batch; permission → allow/deny; completed (strict) → review the report and close; stopped → correct and retry. - ☐ Tickets in
failedpast retries orstuck: read the last messages, fix the cause (ticket text, environment, credentials), retry. - ☐ Helpers and peers left open by finished tickets: close and note.
- ☐ New fix tickets: expected; third fix ticket for the same part: prepare to arbitrate.
- ☐ The replan ticket of the phase: read its plan before it runs if you want scope changes.
- ☐ Knowledge base growth: decisions and dead ends are being stored (a flat graph after many tickets = context problem).
- ☐ Snapshots exist for each finished ticket; the latest restores cleanly (test it once per milestone).
- ☐ Day-0 items still missing: chase the client; BLOCKED items depend on them.
7.11 A catalogue of real failure patterns and what they mean
Every item below happened in a real run. Learn to recognize them from the transcript.
| What you see | What it means | Where the fix belongs |
|---|---|---|
| The agent claims a page works; the screenshot shows a 500 | A tool hid the error (blank body, stale log); the agent trusted text | Verification recipe (LogTail, php -l); newer tool versions surface the error automatically |
| The agent "forgot" the plan mid-ticket and rebuilt something | Context compaction without a current SPEC FILE, or a model window smaller than the configured limit (silent truncation) | Check the provider's real context window vs the configured limit; enforce §6 (SPEC FILE current after every part) |
| Ticket ends its turn "to wait for the build" and everything dies | H2: processes are killed at turn end; run_in_background is now denied by the hook | Ticket text should not ask for background runs; ProcessManager for services |
| A ticket asks "which framework should I use?" | Type-1 technical question the agent should decide | Answer "your call, record it"; if frequent, the context is unclear about the default stack |
Two parallel tickets both edited header.php | Parallel approved without the ownership analysis, or ownership lists missing from the descriptions | Serialize; H6; ownership table in the plan |
Ticket text mentions codehero-12 or 10.0.3.x | Infrastructure leaked into the ticket | Rewrite with localhost; never the word "container" |
| The verifier "fixed" the code | The ticket title lost its [VERIFY] prefix, so the verify-fix guide was not pre-loaded | Keep the prefix; the guide says "you only CHECK" |
A finished helper ticket still open | Initiator forgot to close it | Close; it is in the initiator's checklist |
A ticket stays awaiting_input for days and nothing behind it moves | It asked you something (NEEDS THE USER: yes) or waits for another ticket; a later sequence never starts until it is done | Daily checklist; answer in one batch, or close it |
| Every ticket burns the maximum thinking budget | ultra set as project default | balanced default; ultra per ticket |
| Weak model loops on an easy PHP task | Tools hid a PHP 500; loop detector saw A/B alternation | Verification recipe first; the hook now catches cycles, not only identical repeats |
| Reviewer closed a ticket that actually asked a question | Strict/relaxed confusion, or the question was buried under "TASK COMPLETED" | The reviewer now treats a flagged problem as ERROR; teach the agent's ask format (question first, marker last) |
Exercises — Module 7
- Take the RepairFlow plan of Module 4. For each of the first five tickets write the proof it produces (a sentence naming the artefact you would open to check it).
- Write the day-0 pack for RepairFlow in the client's language, and the four-reason contact list as you would send it to the owner.
- Simulate a breaker: a VERIFY ticket reports "deadline computed as +15 days", the fix ticket replies "the spec says 14 business days" (DISPUTED), the verifier re-checks and disagrees again. Write the message you send to the parked verifier, and the line you add to the Decision Log.
- Plan the documentation tickets for RepairFlow phase 2 (roles, think modes, sequence, dependencies).
- Pick three rows of the failure catalogue and find the exact sentence in the global context (or the planner) that exists because of them.
PART VIII — CAPSTONE
Module 8 — The capstone project and the assessment
8.1 The assignment
In pairs (one plays the client, one the developer; then swap), deliver a small internal tool end to end within one working day:
- Interview the client with the Spec Builder (Module 2). Deliver a Ready to build package with at most one non-critical Assumed item. The tool must have: two roles, one entity with at least three states and history, one business rule with a number (a deadline, a limit or a formula), one notification, one export or printout.
- Justify the stack (Module 3): the one-line decision, the environment block, and the answer to "why not a container?" (or "why a container?").
- Plan it in IMPORT MODE (Module 4). Before confirming, produce a written review of the preview: three changes you made and why.
- Run phase 1 (Module 5) in relaxed autonomous mode. Answer every question the run raises within the "1A, 2B" format. Keep the Decision Log in sync.
- Customize one thing (Module 6) that the run showed was needed — with the transcript that proves the need, the diff, the §6.10 test.
- Deliver (Module 7): the core slice verified on the preview URL by a VERIFY ticket on a different provider family; the 4-part handoff for the client; the documentation tickets planned; the day-0 items listed.
8.2 The rubric
| Area | Pass | Distinction |
|---|---|---|
| Interview | Every stage covered or consciously defaulted; four statuses used; critical items never Assumed; Stage P preview done | Client's own numbers appear in every business rule's example; dependency register has verification statuses; spreadsheet intake applied |
| Stack | Correct default (PHP/MySQL unless a trigger fires); justification cites a requirement ID | Fallback stack reasoning correct; build vs runtime vs serving declared separately |
| Plan | Serial, probe → knowledge → setup → access gate → core slice; VERIFY tickets on a different family with master+ultra; descriptions follow the five-part recipe | A parallel group offered and correctly analysed, or correctly refused with the ownership reason |
| Run | Every question answered in one batch; no technical question answered by the human; helpers closed; snapshots exist | A breaker occurred and was arbitrated correctly; a safe default was overturned via the report's part 3 |
| Customization | Observed failure → rule → deployed → tested on a weak model → transcript proves behaviour | The rule is in the right layer, cross-references the global, and adds under 300 bytes |
| Delivery | Core slice acceptance list all pass or BLOCKED with reason; 4-part handoff; documentation planned | Restore drill performed; production steps listed; the client can read the handoff without you |
8.3 Self-assessment quiz
Answer without looking; then check against the referenced sections.
- Name the two kinds of unknowns the agent meets, and who decides each. (Global §4)
- What does the agent do when a CRITICAL question has no answer and the run is autonomous? (Global §4.1,
guides/asking.md) - Which ticket statuses satisfy a dependency? Does
awaiting_input? Doestimeout? (Module 5 §5.1) - Give the three settings every VERIFY ticket must have, where its fix ticket goes, and one thing it must never do. (
guides/verify-fix.md) - What is the shipped default of
MAX_PARALLEL_TICKETS_PER_PROJECT, and what does that mean for a plan where two tickets share asequence_order? (Module 4 §4.6) - Why does the Spec Builder never name a provider or a model? (Planning Guide §1.2, §7.5)
- Which four things does the
codehero_environmentblock declare separately, and which one alone decidescontainer_required? (Module 3 §3.6) - Where does a client's VAT rule belong, and where does it not belong? (Module 6 §6.2)
- What are the four parts of the handoff report, and which part contains the safe defaults? (Global §5 step 10)
- A ticket's last message is
⏸ WAITING-FOR-TICKET #418. Ticket 418 is still running. What does the auto-reviewer do? (Module 5 §5.1) - Name three "danger files" the ownership analysis checks by name. (
guides/planning.md§2) - Which file does the agent re-read first when it feels lost after compaction? (Global §6)
- What is the difference between a SAFE DEFAULT and a guessed business rule? (Global §4.1,
guides/asking.md) - Why must ticket descriptions never contain the word "container"? (Planner rule 8)
- A trainee wants to add a rule "always be careful with money". What do you ask for first? (Module 6 §6.4)
- A build ticket at sequence 3 is left
awaiting_inputby the reviewer. Can a ticket at sequence 4 start? Can a forced ticket at sequence 9? (Module 4 §4.6) - Which two lines open every agent report, and what does the reviewer do with each? (Module 5 §5.8)
8.4 Certification checklist
A developer is ready to run client projects unsupervised when they can:
- ☐ run a Spec Builder interview and review its package with the Module 2 checklist;
- ☐ state the stack decision and its justification for any of the eight mini-cases without notes;
- ☐ read a planner preview and find the three most common defects (wrong verify provider, visual work on a text-only provider, missing dependency);
- ☐ answer an agent's question batch correctly (business only, one batch, Decision Log updated);
- ☐ recognize the twelve failure patterns of Module 7 from a transcript;
- ☐ change a context rule following the §6.10 protocol and show the transcript that proves it worked;
- ☐ explain the twelve principles to a client in plain language.
APPENDICES
Appendix A — Quick reference cards
A.1 Ticket fields
| Field | Values | Default |
|---|---|---|
sequence_order | integer; unique ascending = serial; same = parallel group | required |
depends_on | bulk call: 1-indexed positions of the same call, earlier only · single create: existing ticket ids or ticket numbers | none |
parent_sequence / parent_ticket_id | earlier position / existing ticket id | none |
ai_model | master_developer · senior_developer · junior_developer | project default |
provider | an active provider | project default |
think_mode | off · basic · balanced · ultra | project default (balanced) |
execution_mode | autonomous · semi-autonomous · supervised | project default (autonomous) |
deps_include_awaiting | 1 relaxed (the auto-reviewer closes clean tickets) · 0 strict (you close each) | 1 |
ticket_type | feature · task · bug · debug · rnd · improvement · docs | feature |
priority | low · medium · high · critical | medium |
is_forced | 1 = forced start (Start Now / Force Next / codehero_start_ticket): starts now, ignores sequence, dependencies, parent and slots | 0 |
A.2 Ticket statuses
open (eligible) · in_progress (agent running) · awaiting_input (parked: completed / question / error / permission / stopped / deps_ready) · done (also what "close" means — there is no closed status) · failed (retries exhausted) · stuck (watchdog) · timeout · skipped (counts as complete) · new / pending (rare). A higher sequence starts only when every lower one is done or skipped.
A.3 Roles and think modes per ticket type (Spec Builder table)
| Ticket type | role | think_mode |
|---|---|---|
| Planning, replan, contracts, architecture, security | master_developer | ultra |
| Verification / peer review / helper / replan | master_developer (different provider for verify, peer and helper) | ultra |
| Feature implementation | senior_developer | balanced |
| Repetitive work, docs formatting | junior_developer | basic |
| Tests and fixtures | senior_developer | balanced |
A.4 The agent's tools
Built-in: Read Write Edit MultiEdit Glob Grep Bash ProcessManager HttpRequest Browser PageAssert LogTail WebFetch GetCached. Platform (MCP): codehero_knowledge_search/store/list/delete · codehero_git_operations · codehero_screenshot · codehero_extract_context · codehero_get_guide · codehero_get_ticket update_ticket (reply, status) create_ticket list_tickets bulk_create_tickets get_project_progress start_ticket · codehero_get_project get_providers_info · codehero_container_operations · codehero_codebase_status.
A.5 The global context, by section
Core: 0 Read this first (glossary, 11 rules) · 1 Language rule · 2 Guides: the trigger table · 3 Hard rules H1–H10 · 4 Decide alone vs ask (4.1 asking, safe defaults, blocked) · 5 The work loop (+ the light loop for a small change) · 6 The SPEC FILE · 7 Knowledge base · 8 When something fails · 9 Verification (9.1 nothing internal downloadable, 9.2 repeatable tests) · 10 Git backup · 11 Code rules · 12 Messages between tickets · 13 Environment & paths · 14 Final checklist. Guides: planning · verify-fix · asking · helper · debugging · frontend · database · build · testing · native.
A.6 Walkie-talkie
Send: codehero_update_ticket(ticket_id=<other numeric id>, reply="...") — the platform signs it 📨 FROM TICKET #<id>. Receive while running: 📨 INCOMING MESSAGE at the next step (own check, MCP result, or CLI hook). Park: end the turn with ⏸ WAITING-FOR-TICKET #<id>[, #<id>] — its reply will wake me + TASK COMPLETED; a reply wakes you; an awaited ticket that ends without replying triggers a 📨 SYSTEM wake-up. Ended with a message unread → re-opened at once. Close a helper you opened: codehero_update_ticket(ticket_id=<helper>, status="closed").
Appendix B — File map
| Purpose | Path |
|---|---|
| Global context (source / installed defaults / daemon+assistant copy) | config/global-context.md / /opt/codehero/config/global-context.md / /etc/codehero/global-context.md |
| Language contexts | config/contexts/*.md → /opt/codehero/config/contexts/ |
Guides (on demand, codehero_get_guide) | config/guides/*.md → /opt/codehero/config/guides/ |
Repeatable-test runner (installed as .tests/run.sh in every project) | libs/tests/run.sh → /opt/codehero/libs/tests/run.sh |
| Walkie-talkie hook (Claude CLI modes) · context refresh | scripts/message_hook.py · scripts/refresh_global_context.py |
| Context checkers | tests/context/check_global_context.py · tests/context/check_test_runner.py |
| Spec Builder knowledge file | docs/CODEHERO_PLANNING_GUIDE.md (served at /docs/CODEHERO_PLANNING_GUIDE.md) |
| Assistant templates | config/assistant-*.md → /etc/codehero/assistant-*.md |
| Provider ↔ role model map, think budgets, sub-agent roles | heroagent/heroagent.conf (synced to /opt/codehero/heroagent/ and /etc/codehero/) |
| Provider API keys | /etc/codehero/api_keys.conf |
| System settings (ports, parallelism, cooldowns, context thresholds) | /etc/codehero/system.conf |
| Daemon / MCP server / permission hook | scripts/claude-daemon.py · scripts/mcp_server.py · scripts/permission_hook.py |
| Agent and tools | heroagent/heroagent.py · heroagent/tools/ · heroagent/providers/ |
| Per-ticket assembled prompt and conversation | <work_path>/.heroagent/context_<ticket>.tmp · <work_path>/.heroagent/conversation_<ticket>.json |
| Project SPEC FILES and docs | <work_path>/.specs/*.md · technologies.md · map.md |
| Web projects / app projects | /var/www/projects/<slug> · /opt/apps/<slug> |
| Local libraries | /opt/codehero/libs/ |
| Logs | journalctl -u codehero-daemon · /var/log/codehero/daemon.log · /var/log/codehero/web.log |
Appendix C — Reading list (in order)
config/global-context.md— read it twice; it is the framework. Thenconfig/guides/planning.md,verify-fix.md,helper.md,asking.md— the situations.docs/CODEHERO_PLANNING_GUIDE.md— Parts 1, 2, 3 and 7 first; Parts 4–6 as reference.config/assistant-planner.md— short; read it before your first import.config/contexts/php.md— the reference language context; then the context of your stack.- User Guide chapters 8 (Execution Modes), 9 (Sequencing), 11 (Lifecycle), 13–16 (providers, roles, think mode, vision), 31 (Containers), 32 (Production).
docs/SMARTCONTEXT.md— how compaction works and why the SPEC FILE exists.CHANGELOG.md— the incident history behind the rules.- The presentation The Domain Expert's Software Factory — the same method told to the client's side; useful before Module 2's interview exercise.
CodeHero Developer Training v1.1 — for CodeHero PRO 4.49+ (Global Context v6.1). The framework files cited here are the source of truth; when this course and a framework file disagree, the framework file wins and this course needs an update.