
Last episode, the first external signal was “can’t run it” — infrastructure layer failure. This episode’s signal is more interesting: someone not only got it running, they started adding things.
Five PRs, Five New Roles
Within two weeks, five pull requests appeared in OPC’s GitHub repository:
- #24: Performance — performance review specialist. Algorithmic complexity, hidden O(n²), missing memoization
- #25: Technical Writer — documentation specialist. Document structure, progressive disclosure, API reference quality
- #26: Localization — internationalization specialist. i18n readiness, string externalization, cultural adaptation
- #27: Data Engineer — data engineering specialist. Data pipelines, ETL, data quality, schema design
- #28: SRE — site reliability engineering specialist. Availability, alerting, capacity planning, incident response
These five PRs share several characteristics:
Every single one only modified files in the roles/ directory. #24 changed 1 file (roles/performance.md), #28 changed 2 files (roles/sre.md + TODO.md). Not one touched code.
Every single one followed OPC’s four-section role file format — Identity / Expertise / When to Include / Anti-Patterns. CONTRIBUTING.md has a section called “Good role ideas we’d love to see,” and #24’s PR description explicitly referenced it.
Combined: +268 lines, -0 lines. Pure additions, zero modifications to existing code.
That number deserves a pause. “+268/-0” means contributors treated the system as an append-only surface — they found an interface that accepts additions without requiring deletions or modifications to existing content. This isn’t accidental. The role directory’s structure naturally supports this “append-to-contribute” pattern: each role is an independent file, with no imports, no dependencies, no execution order between them. Adding roles/sre.md doesn’t affect a single line in roles/security.md. This isolation lets contributors participate with zero context — they don’t need to understand which roles already exist or how roles relate to each other.
The Silent Core
Now look at the other side.
Scanning all 28 PRs in OPC’s repository history:
- PRs touching
roles/*.md: 5 (#24-28) - PRs touching documentation (README, CONTRIBUTING, CONTRACTS): 5 (#8-11, #18)
- PRs touching test files: 10 (#3, #5, #13-17, #19-20, #22)
- External PRs touching harness core code: 0
- External PRs touching gate logic: 0
- External PRs touching review flow: 0
- External PRs touching the extension system: 0
One PR came closest to the core: #12 attempted to add a guard to flow-transition.mjs’s JSON.parse, preventing unhandled parse exceptions. A reasonable fix — one line of defensive code. It was closed without merging.
Why? Not because the fix was wrong. Wrapping JSON.parse in a try-catch is textbook defensive programming. It was closed because even a one-line fix requires the reviewer to trust that the contributor understands the surrounding state machine. The JSON.parse in flow-transition.mjs isn’t isolated — its return value determines which edge the next node follows. Add a catch block, and what do you return from the catch? Return null? How does the downstream edge-matching logic handle null? The contributor couldn’t demonstrate understanding of these cascading effects in a PR description. The information asymmetry was too large.
Contributors’ choices follow a pattern: they’re willing to add things at the outermost layer, unwilling to touch anything inside. This isn’t one person’s choice — it’s the shared behavior pattern of all external contributors.
Why Roles, Not Core
A role file looks like this:
---
name: performance
title: Performance Specialist
tags: [review]
---
## Identity
You are a performance-focused code reviewer...
## Expertise
- Algorithmic complexity analysis
- Memory allocation patterns
...
## When to Include
- Code touching hot paths or data-intensive loops
...
## Anti-Patterns
- Premature optimization without profiling evidence
...
A markdown file. Four fixed sections. Worst case if you get it wrong: the review pipeline gains one slightly unreliable perspective.
Compare that to core code. flow-transition.mjs handles state transitions between nodes — which edge to follow when the current node completes, PASS or FAIL, whether the loop counter has hit its limit. Get one line wrong and the entire pipeline’s routing breaks. gate-protocol.md defines gate decision rules — emoji counting, severity thresholds, PASS/FAIL logic. Get one condition wrong and S2E08’s discovery of “FAIL never fired” might become “PASS never fires.”
Risk of changing a role file: one extra review perspective, harmless at worst. Risk of changing one line of core code: the entire pipeline’s behavior changes.
Contributors aren’t timid — they’re rational. When you don’t understand a system’s internals, touching the safest layer is the most reasonable choice. They’re using minimum risk to validate their understanding of the system.
Two key properties are at work here: isolation and reversibility.
Role files are isolated — changing one doesn’t affect any other file. They’re also reversible — a badly written role can be deleted with no side effects. Core code has neither property. flow-transition.mjs is coupled to every node in the pipeline; changing one line there affects every path through the entire flow. And such changes aren’t easily reversible — once merged, every test, gate rule, and node transition that depends on that logic needs to be re-validated.
This is why +268/-0 isn’t a coincidence. Contributors independently found the lowest-risk way to participate — an interface that is both isolated and reversible. They didn’t need to be told “please only modify the roles directory.” The interface design itself signaled “it’s safe here.”
Trust Transfers in Layers
EP01 introduced the five-layer trust model. This episode fills in the first three layers with real data:
Layer 1 (Infrastructure): #21 showed Linux users can’t run it. Infrastructure layer not fully passed.
Layer 2 (Pattern): Five role PRs demonstrate that outsiders understood the roles/*.md format. They didn’t need to read source code to grasp the pattern — the four-section structure is self-explanatory. Pattern layer passed.
Layer 3 (Contribution): Five PRs were submitted. Contributors didn’t just understand the pattern — they created new roles following it. Contribution layer passed at the leaf level.
Layer 4 (Core): Zero harness/gate/review flow PRs. Core layer trust hasn’t transferred. Not because nobody wanted to — #12 tried — but because the risk is too high and the reward too low. Without understanding the gate’s internal state machine, even adding a one-line JSON.parse guard might introduce new problems.
What would it take for Layer 4 to transfer? The code needs to become “legible” — not just syntactically readable, but intent-readable. Architecture Decision Records (ADRs), inline comments explaining “why not the obvious approach,” test cases that serve as executable specifications — these are the signals that say “you can follow my reasoning.” Without them, external contributors aren’t facing an open-source project; they’re facing a black box that happens to have visible source code.
EP01 said trust doesn’t transfer all at once. This episode confirms: trust transferred successfully at the leaf layer but stopped at the core layer.
The Real Structure Behind Stars/Forks/PRs
| Layer | Metric | Status |
|---|---|---|
| Interest | 163 stars | Present |
| Curiosity | 39 forks | Present |
| Infrastructure | Linux usability | Unfixed (#21 OPEN) |
| Pattern understanding | Role format reuse | 5/5 compliant |
| Leaf contribution | Role PRs | 5 |
| Core contribution | harness/gate/flow PRs | 0 |
This table is far more informative than just “163 stars.” 163 stars is a number; the table above is a structure. GitHub’s default metrics (stars/forks/contributors) measure surface signals. Trust transfer requires layer-by-layer decomposition to see the real picture.
They Won’t Touch the Core Because the Core Isn’t a Public Asset Yet
Back to this episode’s title: “They Add Roles, But Won’t Touch the Core.”
On the surface, this describes external contributors’ behavior. But the more precise statement is: a usable core mechanism is not the same as a core mechanism that outsiders can trust and maintain.
S1-S2’s harness code, gate logic, review flow — I wrote all of it, I understand all of it, I maintain all of it. There’s a map in my head. What external contributors see is: a bunch of .mjs files with no architecture diagram, no decision records (ADRs), no “here’s why this line is written this way” comments.
The code is public. But the understanding isn’t.
A tool’s “core” isn’t just code — it’s the tradeoffs made while writing it, the alternatives that were abandoned, the context behind historical bugs. That information is locked in the author’s head. When outsiders only touch leaves and won’t touch bones, the problem isn’t that they’re timid. The problem is your core hasn’t signaled “you can change this.”
This is a paradox of open source. Code is the most visible artifact, but for trust transfer, code is precisely the least important piece. What actually transfers trust is the meta-information: why this approach was chosen, what was tried and abandoned, which invariants must hold. When that meta-information is missing, contributors self-select to the layer where they can reason independently — the leaf layer. “Won’t touch the core” isn’t a courage problem. It’s an information problem.
Next episode looks at why the role system could be understood by outsiders — not because the documentation was good, but because the interface design implicitly signaled “breaking this isn’t scary.”
Silicon Team S3: From “I Can Use It” to “Others Can Use It” ← S3E01: The Second User Didn’t Not Show Up — They Got Stuck at the Door | S3E03: Why the Role System Could Be Understood by Outsiders →