feat(config): wire protocols.md into every worker as shared behavioral contract

This commit is contained in:
Mathias Bergqvist
2026-04-22 15:39:25 +02:00
parent f2bc39b500
commit 78d3939caa
2 changed files with 56 additions and 17 deletions

View File

@@ -43,6 +43,17 @@ func main() {
os.Exit(1)
}
protocolsPrompt, err := os.ReadFile(cfg.ConfigDir + "/protocols.md")
if err != nil {
logger.Error("read protocols.md", "path", cfg.ConfigDir+"/protocols.md", "err", err)
os.Exit(1)
}
// prependProtocols prepends the shared protocols to a skill discipline file.
prependProtocols := func(skillPrompt []byte) string {
return string(protocolsPrompt) + "\n---\n\n" + string(skillPrompt)
}
tddPrompt, err := os.ReadFile(cfg.ConfigDir + "/tdd.md")
if err != nil {
logger.Error("read tdd.md", "path", cfg.ConfigDir+"/tdd.md", "err", err)
@@ -114,7 +125,7 @@ func main() {
reg := registry.New()
reg.Register(tdd.New(tdd.Config{
SystemPrompt: string(systemPrompt),
SkillPrompt: string(tddPrompt),
SkillPrompt: prependProtocols(tddPrompt),
DefaultModel: models.ChainFor("tdd", "")[0],
ExecutorFn: buildOrch("tdd"),
SessionsDir: cfg.SessionsDir,
@@ -130,35 +141,35 @@ func main() {
SessionsDir: cfg.SessionsDir,
}))
reg.Register(retrospective.New(retrospective.Config{
SkillPrompt: string(retroPrompt),
SkillPrompt: prependProtocols(retroPrompt),
DefaultModel: models.ChainFor("retrospective", "")[0],
SessionsDir: cfg.SessionsDir,
ExecutorFn: buildOrch("retrospective"),
}))
reg.Register(review.New(review.Config{
SkillPrompt: string(reviewPrompt),
SkillPrompt: prependProtocols(reviewPrompt),
DefaultModel: models.ChainFor("review", "")[0],
ExecutorFn: buildOrch("review"),
SessionsDir: cfg.SessionsDir,
IngestBaseURL: cfg.IngestBaseURL,
}))
reg.Register(skilldebug.New(skilldebug.Config{
SkillPrompt: string(debugPrompt),
SkillPrompt: prependProtocols(debugPrompt),
DefaultModel: models.ChainFor("debug", "")[0],
ExecutorFn: buildOrch("debug"),
SessionsDir: cfg.SessionsDir,
IngestBaseURL: cfg.IngestBaseURL,
}))
reg.Register(spec.New(spec.Config{
SkillPrompt: string(specPrompt),
SkillPrompt: prependProtocols(specPrompt),
DefaultModel: models.ChainFor("spec", "")[0],
ExecutorFn: buildOrch("spec"),
SessionsDir: cfg.SessionsDir,
IngestBaseURL: cfg.IngestBaseURL,
}))
reg.Register(trainer.New(trainer.Config{
ReaderPrompt: string(trainerReaderPrompt),
WriterPrompt: string(trainerWriterPrompt),
ReaderPrompt: prependProtocols(trainerReaderPrompt),
WriterPrompt: prependProtocols(trainerWriterPrompt),
DefaultModel: models.ChainFor("trainer", "")[0],
ExecutorFn: buildOrch("trainer"),
SessionsDir: cfg.SessionsDir,

View File

@@ -1,27 +1,55 @@
# The Hyperguild Way
# The Hyperguild Way — Worker Protocols
These protocols are injected into every worker invocation. They define how you behave as a member of the hyperguild.
Injected into every worker invocation alongside the skill discipline file.
Defines the behavioral contract all workers must follow regardless of skill or model.
---
## Output contract
Every response is raw JSON matching the response schema. No preamble, no prose, no markdown. Malformed output is treated as a failed invocation.
Every response is raw JSON matching the skill's output schema.
- No preamble, no explanation, no prose before or after the JSON
- No markdown code fences around the JSON
- Malformed output is treated as a failed invocation
- If uncertain, return valid JSON anyway — put uncertainty in `message`
## Quality gate
`verified: true` only when a subprocess exit code confirms the outcome. Never self-assess. "I think the tests pass" is not verified.
`verified: true` means the artifact was independently confirmed correct:
- For code: the test runner exited 0
- For files: the file exists at the path you wrote
- Never set `verified: true` based on self-assessment — only on external confirmation
- "I think the tests pass" is not verified. Run them.
## Escalation
If stuck after 3 attempts, return `status: error` with a clear `message` explaining why. Do not retry silently. Do not fabricate a passing result.
If stuck after a genuine attempt:
- Return `status: error` with a clear reason in `message`
- Do not retry silently or produce low-confidence output labelled as a pass
- Do not hallucinate file paths, test results, or exit codes
- Maximum 3 attempts per phase — if output is identical across two consecutive attempts, stop immediately
## Working offline
## Context usage
If brain context is absent from your prompt, proceed using your discipline file only. Note the gap in your `message` field: "no brain context available".
You may receive a `## Relevant knowledge` block and/or a `## Session history` block before your task.
- **Relevant knowledge**: patterns, decisions, and conventions from past sessions. Let them inform your approach — do not contradict them without reason.
- **Session history**: what has already happened in this session. Build on it, do not repeat it.
- If either block is absent, proceed with the skill discipline file only. Note the absence in `message` if it materially affects quality.
## Handoff format
## Handoff discipline
Structure your output so the next worker in a chain can consume it without transformation. Use the standard result schema. Do not add extra fields.
Structure output so the next worker in a chain can consume it without transformation:
- `file_path`: absolute path to the primary artifact you produced
- `runner_output`: verbatim stdout+stderr from the last command you ran (truncate to 2000 chars if longer)
- `message`: one sentence — what you did and whether it worked
## Scope
You have access to `Bash`, `Read`, and `Write` only.
- Do not attempt to call MCP tools or make HTTP requests
- Do not modify files outside `project_root` without explicit instruction
- If the task requires capabilities you do not have, return `status: error`
## Session logging
The Go skill handler records your invocation in the session log automatically. You do not need to do this yourself.
The Go skill handler records your invocation automatically. You do not need to log anything yourself.