Per cycle #117 cross-claw diagnosis (both claws attempted independently):
Both Jobdori (code-yeongyu) and gaebal-gajae (Yeachan-Heo) hit
identical GraphQL FORBIDDEN error on createPullRequest mutation.
Diagnosis: Organization-wide OAuth app restriction on
ultraworkers/claw-code, not per-identity issue.
Reviewer-ready compression (per gaebal-gajae):
'The branch is now remotely visible and PR-ready, but actual PR
creation is blocked by GitHub permissions rather than repository
state.'
Confirmed state:
- Branch on origin: Yes (cycle #115)
- PR creation CLI path: Blocked for both claws
- Manual web UI: Required
- Org admin OAuth grant: Long-term fix
Gate sequence updated:
1. Branch on origin (DONE, cycle #115)
2. PR creation - BLOCKED at OAuth (cycle #116/#117)
3. Manual web UI PR creation (REQUIRED next)
4. Review cycle
5. Merge signal
6. Phase 1 Bundle 1 (#181 + #183)
Doctrine #32 (provisional, pending gaebal-gajae formal acceptance):
'Merge-wait mode actions must be within the agent's capability
envelope. When blocked externally, diagnose + document + escalate,
not retry.'
Cross-claw validation: Both claws blocked, same error pattern.
Mode integrity: Preserved throughout both attempts.
Next blocker: External human action (manual web UI or org admin).
Per gaebal-gajae cycle #115 validation pass:
Authoritative reframe:
'Cycle #115 was not an exception to merge-wait mode; it was the first
turn where merge-wait mode actually did what merge-wait mode is
supposed to do.'
Reviewer-ready compression:
'The branch was frozen but not yet reviewable because it had never
been pushed; this cycle converted merge-wait from a declared state
into a remotely visible one.'
Mode semantic correction:
- Merge-wait mode is NOT 'do nothing'
- Merge-wait mode IS 'block discovery + enable merge-readiness'
- Push to origin = merge-readiness action (fits mode, not violation)
Doctrine #31 (formalized):
'Merge-wait mode requires remote visibility.'
Protocol: git ls-remote origin <branch> must return commit hash.
If empty: push before claiming review-ready.
Self-process pinpoint #193 (formalized):
'Dogfood process hygiene gap — declared review-ready claims lacked
remote visibility check for 40+ minutes (cycles #109-#114).'
Applies to dogfood methodology, not claw-code binary.
Gate sequence (per gaebal-gajae):
1. Branch on origin (cycle #115, DONE)
2. PR creation (next concrete action)
3. Review cycle
4. Merge signal
5. Phase 1 Bundle 1 kickoff
Doctrine count: 31 total.
Per gaebal-gajae cycle #110 state designation:
'Phase 0 is no longer in discovery mode; it is in merge-wait mode
with Phase 1 already precommitted.'
Mode distinction formalized:
- Discovery mode: probe + file + refine (previous state)
- Merge-wait mode: hold state, await signal (CURRENT)
- Execution mode: land bundles (post-merge state)
Doctrine #30: 'Modes are state, not suggestions.'
Once closure is declared, mode label acts as operational guard.
Future cycles must respect state designation:
- No new probes (that's discovery)
- No new pinpoints (branch frozen)
- No new branches (Phase 0 must merge first)
- Maintain readiness; respond to signal
Mode history for Phase 0:
- Cycle #97: Discovery begins
- Cycle #108: Exhaustion criteria met
- Cycle #109: Closure declared
- Cycle #110: Merge-wait mode formally entered
Current state: MERGE-WAIT MODE. Awaiting signal.
Per gaebal-gajae 11:58 Seoul closure validation.
Authoritative closure statement:
'Phase 0 has finished discovery. Phase 1 should start by landing
the locked contract foundation bundle, not by opening new
exploratory cycles.'
All four exhaustion criteria met:
1. Unaudited surfaces: 9 probed (full coverage)
2. Probe hypothesis: Fully validated (multi-flag 3-4, simple 0-1)
3. Phase 1 docs: PHASE_1_KICKOFF.md + review guide + priority queue
4. Branch hygiene: 39 commits, 564 tests, 0 regressions, freeze held
Doctrine #29 (final): 'Discovery termination is itself a deliverable.'
- Criteria: surfaces probed, hypothesis validated, plan documented,
branch review-ready
- Anti-pattern: infinite probe continuation
- Correct: explicit closure + pivot to execution
Phase 0 / dogfood cycles formally closed. No more probe filings
on this branch. Next work unit is Phase 1 execution, not discovery.
Pending: Phase 0 merge approval → Phase 1 branch creation in
priority order → bundle-by-bundle execution (~10 min per bundle).
Cycle #108 probe of claw skills install/enable/disable yielded 3 pinpoints:
#190: Design decision needed
skills install (no args) routes to help (action: help, kind: skills).
May be intentional (like agents pattern) or design inconsistency.
Requires verification against agents canonical reference.
#191: Classifier gap (filesystem family extension)
skills install /bad/path emits kind=unknown.
Should be kind=filesystem or filesystem_io_error.
Extends #177/#178/#179 install-surface taxonomy.
#192: Classifier gap (unknown-option family extension)
skills install --bogus-flag emits kind=unknown.
Should be kind=cli_parse (like sandbox).
Now 4 members in unknown-option sub-lineage: #186, #187, #189, #192.
Pinpoint count: 82 filed, 67 genuinely open.
Classifier family: 19 members (+2).
All unaudited surfaces now probed:
- Cycles #104-#108: plugins, agents, init, bootstrap-plan, system-prompt,
export, sandbox, dump-manifests, skills
- Hypothesis fully validated: Multi-flag verbs have 3-4 classifier gaps;
simple verbs have 0-1 gaps.
Per freeze doctrine, no code changes. Doc-only filing.
Per gaebal-gajae cycle #107 validation pass. Three refinements:
1. Framings locked (both verb-specific):
#188: 'dump-manifests --help omits the prerequisite that runtime
behavior actually requires.'
#189: 'dump-manifests unknown-option errors still fall through to
unknown instead of the existing CLI-parse path.'
2. Doc-truthfulness family formally split into 2 sub-axes:
- Audit-flow (5 members: #76, #79, #82, #172, #180) — reading one
file vs another declared source of truth
- Probe-flow (NEW, 1 member: #188) — running verb vs observing
--help text
3. Priority refinement:
- #189 → bundled in feat/jobdori-186-189-classifier-sweep (3 verbs)
- #188 → post-#180 (doc parity sequence: USAGE gap → help-text gap)
- Full sequence: #180 (audit-flow doc-truth) → #188 (probe-flow doc-truth)
4. Key cycle #107 outcome (per gaebal-gajae):
'behavior bug처럼 보이던 걸 help-text truthfulness gap으로 정확히 재분류'
This is the reclassification skill that earned the filing.
Doctrine #28: First observation is hypothesis, not filing. Verify
against SCHEMAS/USAGE/--help before classifying axis. Cost: 30-60s
per probe. Benefit: avoid filing not-a-bug pinpoints.
Priority queue now 6 bundles + 3+ independent, all reviewer-blessed.
Cycle #107 probe of claw dump-manifests yielded 2 pinpoints:
#188: Doc-truthfulness gap (NEW sub-axis)
claw dump-manifests --help describes usage as optional flags, but
the verb fails without --manifests-dir or CLAUDE_CODE_UPSTREAM.
USAGE.md is correct; CLI --help output lies by omission.
This is the first doc-truth pinpoint from probe flow (vs audit flow).
New sub-axis: help text vs behavior (prior doc-truth: SCHEMAS/USAGE/README).
#189: Classifier gap (same pattern as #186/#187)
dump-manifests --bogus-flag falls through to kind=unknown.
Should be cli_parse (like sandbox).
Now at 3 verbs in same pattern: system-prompt (#186), export (#187),
dump-manifests (#189). Rename bundle to feat/jobdori-186-189-classifier-sweep.
Pinpoint count: 79 filed, 65 genuinely open.
Doc-truthfulness family: 6 members (was 5).
Classifier unknown-option sub-lineage: 3 members (was 2).
Per freeze doctrine, no code changes. Doc-only filing.
Per gaebal-gajae cycle #106 validation pass. Two refinements:
1. #187 framing locked:
'export unknown-option errors still fall through to unknown,
unlike the already-canonical sandbox CLI-parse path.'
Surgical parallel to #186 framing (cycle #105):
'system-prompt unknown-option errors still fall through to unknown
instead of the existing CLI-parse classification path.'
Same pattern: verb + drift + reference path.
2. #186 and #187 bundled into feat/jobdori-186-187-classifier-sweep.
Rationale: identical fix pattern, identical test pattern, same
source file, 2x review overhead if separated.
Updated merge priority queue (gaebal-gajae reviewer-blessed):
1. feat/jobdori-181-error-envelope-contract-drift (#181 + #183)
2. feat/jobdori-184-cli-contract-hygiene-sweep (#184 + #185)
3. feat/jobdori-186-187-classifier-sweep (#186 + #187)
Doctrine #27: Same-pattern pinpoints should bundle into one classifier
sweep PR. One-pinpoint = one-branch is not universal; batching
same-pattern fixes halves review/merge overhead.
Cycle #106 probe of export and sandbox verbs. Found:
- export --bogus-flag: kind=unknown (should be cli_parse)
- sandbox --bogus-flag: kind=cli_parse (canonical correct)
#187 is direct sibling of #186 (system-prompt classifier gap).
Both unknown-option, both should use cli_parse classifier.
Observation: sandbox has no gaps. export has 1 classifier gap.
Suggests classifier coverage improving on newer verbs, not consistent
regression across unaudited surfaces.
Hypothesis (#104) partially validated: unaudited surfaces yield
pinpoints, but not uniformly. Single-issue verbs (sandbox) may be
cleaner than multi-flag verbs (export, init, bootstrap-plan).
Pinpoint count: 77 filed, 63 genuinely open.
Per freeze doctrine, no code changes. Doc-only filing.
Per gaebal-gajae cycle #105 review pass. Three corrections:
1. #184/#185 belong to #171 lineage (CLI contract hygiene sub-family),
NOT a new family. Same enforcement hole pattern on unaudited verbs.
2. #186 locked as member of #169/#170 classifier lineage. Framing:
'system-prompt unknown-option errors still fall through to unknown
instead of the existing CLI-parse classification path.'
3. agents is the #183 reference implementation. Fix path reframed from
'design new contract' to 'align outliers to existing reference'.
Much smaller scope for feat/jobdori-181-error-envelope-contract-drift.
Canonical reference shape locked:
{action: 'help', kind: <verb>, unexpected: <bad-name>, usage: {...}}
Doctrine #24: Pinpoint lineage continuity. Check existing family
before creating new. Reviewers follow pattern lineages.
Family tree corrected: CLI contract hygiene moved from 'NEW' to
'#171 sub-lineage within classifier family'.
Cycle #105 probe of agents/init/bootstrap-plan/system-prompt verbs
(unaudited per cycle #104 hypothesis) yielded 3 pinpoints:
#184: claw init silently accepts unknown positional arguments. Inconsistent
with #171 CLI contract hygiene pattern.
#185: claw bootstrap-plan silently accepts unknown flags. Same family as
#184, different verb, different surface.
#186: claw system-prompt --<unknown> classified as 'unknown' instead of
'cli_parse'. Classifier family member (#182-style).
Bonus observation (not filed): claw agents bogus-action emits the
canonical mcp-style {action: help, unexpected, usage} shape. This is
the shape that #183 wants as canonical, NOT the plugins-style success
envelope. agents is the reference implementation.
Hypothesis validated: unaudited verb surfaces have 2-3x higher pinpoint
yield. Predicted cycle #104-#105 pattern holds.
Pinpoint count: 76 filed, 62 genuinely open.
Final framing pass for cycle #104 plugin lifecycle pinpoints. Three
one-liner framings captured for reviewer consumption:
#181 (HIGH): 'plugins unknown-subcommand errors currently emit on the
success path instead of the JSON error path.'
#183 (HIGH): 'Invalid subcommand handling is not normalized across
plugins and mcp JSON surfaces.'
#182 (MEDIUM): 'Plugin lifecycle failures still fall through to unknown
instead of canonical error kinds.'
Branch sequencing locked:
1. feat/jobdori-181-error-envelope-contract-drift (bundles #181+#183)
2. feat/jobdori-182-plugin-classifier-alignment (#182, post-merge)
Rationale: #181 is root bug, #183 is sibling symptom, #182 is cleanup
that benefits from clean error envelope landing first.
Branch at 27 commits, 227/227 tests, review-ready.
Cycle #104 probe of plugin lifecycle axis (claw plugins + mcp subcommands)
yielded 3 related gaps:
#181: plugins bogus-subcommand returns SUCCESS-shaped envelope with
error buried in 'message' text field. Consumer parsing via
type=='error' check treats it as success. Severe.
#182: plugins install/enable not-found errors classified as 'unknown'
instead of 'plugin_not_found' or 'not_found'. Classifier family member.
#183: plugins and mcp emit DIFFERENT shapes on unknown subcommand.
plugins has reload_runtime+target+message, mcp has unexpected+usage.
Shape parity gap.
All three filed only per freeze doctrine. Proposed separate branches:
- feat/jobdori-181-unknown-subcommand-error-routing (#181 + #183 bundled)
- feat/jobdori-182-plugin-not-found-classifier (#182 standalone)
Pinpoint count: 73 filed, 59 genuinely open. Typed-error family: 14
members. Emission routing family: 1 new member (#181).
Cycle #103 doc-truthfulness audit found USAGE.md incomplete.
Actual CLI has 14 standalone verbs (status, doctor, mcp, skills, agents,
export, init, sandbox, system-prompt, bootstrap-plan, dump-manifests,
help, version, acp).
USAGE.md covers only 3 entry modes (claw REPL, claw prompt TEXT,
claw --resume). Other verbs absent or underdocumented.
Example: USAGE.md says 'start claw, then /doctor' but doesn't explain
that 'claw doctor' is also a standalone entry point (no REPL needed).
Fix: Add 'Standalone commands' section to USAGE.md with all 14 verbs
documented. Include regression test (grep USAGE.md for each verb).
Doc-truthfulness family: #76, #79, #82, #172, #180.
Pinpoint count: 70 filed, 56 genuinely open.
#175 numbering collision between:
- gaebal-gajae's CI framing (filed at ~10:00 via Discord verbally)
- my filesystem classifier filing (#175 per cycle #102 10:02)
Resolution:
- gaebal-gajae's framing reclaims #175 (higher-level workflow gap)
- My filesystem classifier renumbered to #177
- My export enum naming renumbered to #178
All three pinpoints now filed with correct non-colliding numbers:
- #175: CI fmt/test signal decoupling (gaebal-gajae)
- #177: skills install filesystem classifier (Jobdori, was #175)
- #178: export kind naming consistency (Jobdori, was #176)
Typed-error family membership updated accordingly.
Cycle #102 probe of model/skills/export axis found two related gaps:
#175: skills install filesystem errors classified as 'unknown' instead of
'filesystem' (which is in v1.5 enum).
#176: export uses 'filesystem_io_error' kind but this is NOT in v1.5
declared enum (which only lists 'filesystem'). Inconsistent naming.
Both filed only per freeze doctrine. Proposed bundling as
feat/jobdori-175-filesystem-error-family branch.
Family observation: classifier + enum-naming gaps found simultaneously
in filesystem-error axis. Indicates broader unaudited surface.
Pinpoint count: 68 filed, 54 genuinely-open.
Per gaebal-gajae cycle #101 framing pass. Adds stable framing that
captures scope + root cause + visible effect + surface in one line.
Locks branch name: feat/jobdori-174-resume-trailing-cli-parse
Next-branch prep steps documented so post-168c-merge execution is
zero-friction (classifier branch + regression test pattern already
established by #169/#170/#171).
Cycle #101 probe of session-boot axis (prompt misdelivery / resume
lifecycle) found another typed-error classifier gap.
Filed only, not fixed. Per freeze doctrine (cycles #98-#100), no new
code axis added to feat/jobdori-168c-emission-routing.
Pattern: `--resume trailing arguments must be slash commands` classified
as 'unknown' instead of 'cli_parse'. Side effect: #247 hint synthesizer
doesn't trigger, so hint is null.
Same family as #169, #170, #171 (classifier coverage gaps).
Proposed fix: add `--resume trailing arguments` pattern to
classify_error_kind as cli_parse.
Pinpoint count: 66 filed, 52 genuinely-open + #174 new.
Cycle #100 probe of non-classifier axes (event/log opacity) found new
consumer parity gap: JSON mode missing 'hint' field that text mode
provides for config_load_error scenarios.
Filed only, not fixed. Per freeze doctrine (cycles #98-#99), no new axis
added to feat/jobdori-168c-emission-routing. This pinpoint is a Phase 1
scope candidate for a separate branch.
Affects: claw mcp, claw status, claw doctor (JSON mode).
Text mode shows: Hint `claw doctor` classifies config parse errors...
JSON mode shows: no hint field at all.
Consumer impact: claws parsing JSON output can't programmatically route
errors to recovery paths the way text-mode users can with human guidance.
Family: Consumer parity. Related: #247 (hint synthesizer), #169-#172
(classifier family), #172 (doc-truthfulness).
Proposed fix: add 'hint' field to JSON envelope when config_load_error
is present, with hint taxonomy for typed dispatch.
Pinpoint count: 65 filed, 51 genuinely-open + #173 new.
Cycle #96 dogfood found practical install-experience gap in USAGE.md.
#153 closed by commit 6212f17 (same branch, same cycle).
Part of discoverability family (#155, help/USAGE parity).
Pinpoint count: 62 filed, 51 genuinely-open + #153 closed this cycle.
Fresh dogfood validation (cycle #84) revealed the binary v1.0 envelope is NOT
consistent across commands:
- list-sessions: {command, sessions}
- doctor: {checks, kind, message, ...}
- bootstrap: (no JSON output at all)
- mcp: {action, kind, status, ...}
Each command has a custom JSON shape. Bootstrap's JSON path is completely broken
(exit 0 but no output). This is not 'v1.0 vs v2.0 design difference' — it's
'no consistent v1.0 ever existed'.
This explains why #164 (envelope migration) is blocked on design: the 'v1.0 from'
was never coherent. The real task is not 'migrate v1.0 to v2.0' but 'migrate
incoherent-per-command shapes to coherent-common-envelope'.
Implications for cycles #76–#82: The P0 doc fixes were correct to mark SCHEMAS.md
as 'aspirational' because the binary never had a consistent contract to document.
The deeper issue: each verb renderer was written independently with no envelope
coordination.
Three options proposed:
- A: accept per-command shapes (status quo + documentation)
- B: enforce common wrapper (FIX_LOCUS_164 full approach)
- C: hybrid (document current incoherence, then migrate 3 pilot verbs)
Recommendation: Option C. Documents truth immediately, enables phased migration.
This filing resolves the #164 design blocker: now we understand what we're
migrating from.
SCHEMAS.md locks JSON envelope contract for all 14 clawable commands.
No corresponding contract for text output (--output-format text).
Text output is ad hoc per-command: no documented format, no column ordering
guarantee, no stability contract. Claws parsing text output have no safety.
Filed as discovery gap from systematic doc audit (cycle #83). Design options:
- Option A: Document text contracts (parallel to JSON) — 4 dev-days
- Option B: Declare text unstable, point to JSON — 1 dev-day (recommended)
- Option C: Defer until post-#164 JSON migration
Related to #164 (JSON migration) and #250 (surface parity audit).
The aspirational SCHEMAS.md doc (v2.0 target) was the source of truth misdocumentation.
Three downstream docs (USAGE, ERROR_HANDLING, CLAUDE) inherited the false claim that
v1.0 binary emits common fields it doesn't actually emit.
Fixing SCHEMAS.md at the source eliminates the root cause for all four P0 instances.
Doc-truthfulness P0 family now complete: 4/4 closed, root cause identified + fixed.
All fixes shipped within 6 cycles (#76 audit → #82 execution).
CLAUDE.md Option A implemented. P0 doc-truthfulness family now at 3 closed +
0 open (all 3 fixed within the same dogfood session).
Taxonomy refinement added: P0 doc-truthfulness has three distinct subclasses:
- active misdocumentation (false sentence) — USAGE.md cycle #78
- copy-paste trap (broken example code) — ERROR_HANDLING.md cycle #79
- target/current boundary collapse (v2.0 as v1.0) — CLAUDE.md cycle #81
All three related to #164 (envelope divergence). Root cause consistent across
family; remedies differ per subclass.
CLAUDE.md claims 'Common fields (all envelopes): timestamp, command, exit_code,
output_format, schema_version' but the actual binary v1.0 doesn't emit these.
This is aspirational (v2.0 target from SCHEMAS.md) documented as current behavior
in a file that's supposed to describe the Python reference harness.
Filed as 3rd member of doc-truthfulness P0 family (joins #78, #79).
Both options documented: update CLAUDE.md for v1.0 OR clarify it's v2.0 aspirational.
Recommendation: Option A (keep CLAUDE.md truthful about actual validation).
Part of broader #164 family (envelope schema divergence across all docs).
Formalizes a 4-level severity scale for documentation-vs-implementation divergence:
- P0: Active misdocumentation (consumer code breaks) — immediate fix
- P1: Stale docs (consumer confused) — high priority
- P2: Incomplete docs (friction, eventual success) — medium
- P3: Terminology drift (confusion but survivable) — low
Parallel to diagnostic-strictness scale (cycles #57–#69). Both are
'truth-over-convenience' constraints.
Evidence: cycles #78–#79 found 2 P0 instances in USAGE.md and ERROR_HANDLING.md,
both related to JSON envelope shape. Root cause: SCHEMAS.md is aspirational (v2.0),
binary still emits v1.0, docs needed to be empirical not aspirational.
Going forward: doc audits compare against actual binary, flag P0 violations
immediately, link forward to migration plans (FIX_LOCUS_164.md).
Binary emits different envelope shape than SCHEMAS.md documents:
- Missing: timestamp, command, exit_code, output_format, schema_version
- Wrong placement: kind is top-level, not nested under error
- Extra: type:error field not in schema
- Wrong type: error is string, not object with operation/target/retryable
Additional issue: 'kind' field is semantically overloaded (verb-id in
success envelopes, error-kind in error envelopes) — violates typed contract.
Filed as 7th member of typed-error family (joins #102, #121, #127, #129, #130, #245).
Recommended fix: Option A — update binary to match schema (principled design).
Attempted cherry-pick of #248 (1 commit) onto main. Encountered 2 conflict zones
in main.rs (test definitions + error classification). Manual regex cleanup left
orphaned diff markers that Rust compiler rejected.
Decision: Rebase-bridge works for 1-conflict branches, but 2+ conflicts in 12K+-line
files require author context. Revised strategy: push main to origin, request branch
authors rebase locally with IDE support, then merge from updated origin branches.
Estimated timeline: 30 min for branch authors to rebase 8 branches in parallel.
Fresh dogfood found no new pinpoints. All core verbs working correctly.
Blocker: 8 remaining review-ready branches on origin have conflicts with
cycle #72's 4 merges. Root cause: remote branches predated the merge chain.
Example: feat/jobdori-127-verb-suffix-flags rebase fails on commit 3/3
because cycle #72 added 15+ new LocalHelpTopic variants.
Recommend: coordinate with branch authors to rebase against new main.
Cycle #74 will post integration checkpoint + queue status.
Backlog-truthfulness (cycle #60) validated: fresh dogfood on current main confirmed
#163 was closed by cycle #72's help-parity chain merge. Zero duplicate work.
Cleanup: removed /tmp/jobdori-163 worktree and fix/jobdori-163-help-help-selfref branch.