Task — engineering-spec@1

Platform entry-point identity - thin spine vs explicit dual identity

doneTASK-IMP-138
module improvement · class product · priority p1 · created 2026-07-23 · shipped null
depends on none · blocks none

TASK-IMP-138: Platform entry-point identity - thin spine vs explicit dual identity

Summary

On every consumer repo, install.sh writes root AGENTS.md as a thin workflow spine (task law, gates, HITL, memory pointer). On this platform repo, root AGENTS.md is the full Layer-1 memory protocol, CLAUDE.md duplicates it wholesale, and every pointer file (.cursorrules, GEMINI.md, .windsurfrules, copilot instructions, cursor rules) tells agents that root AGENTS.md is the first half of "canonical instructions". An agent on the platform repo that loads only the most-native file gets memory law and can miss task/HITL law entirely - the inverse of the installer's own documented rationale ("a root protocol file... would bury the workflow every agent needs"). This task resolves the identity - but WHICH resolution is a structural operator decision, presented here as a fork and deliberately not resolved by the author.

Implementation status: Branch A IMPLEMENTED (ship/batch-8f-entrypoint)

Operator chose Branch A (thin spine) on 2026-07-23 — see decision-branch-a.md and source_decisions. The fork block is closed; implementation remains deferred to Batch D on its own branch. Status stays ready_to_implement until that ship starts. Invariant clauses / ACs / test suite still hold under the chosen branch.

Branch A - thin spine everywhere. The platform repo's root AGENTS.md becomes the same thin workflow spine consumers get; the memory protocol's normative source moves to modules/memory/cyberos/data/AGENTS.md (already the vendored source of truth for installs), with .cyberos/memory/AGENTS.md as its installed copy; install.sh's is_platform_repo() exception (:515, :336) is deleted; CLAUDE.md becomes a pointer. Consequence: one identity everywhere, but a structural move of the protocol's normative home - links, tooling, and §0.4-adjacent wording that assume "root AGENTS.md is the protocol" must be swept (the walker cites AGENTS.md §3; memory docs reference sections by bare AGENTS.md).

Branch B - explicit dual identity. Root AGENTS.md stays the protocol on the platform repo, but the identity is declared everywhere it matters: root AGENTS.md gains a first-screen preamble ("on this platform repo this file is the Layer-1 memory protocol; task/HITL law lives at .cyberos/AGENT-ENTRY.md - read that first for work"), every pointer file's wording changes from "Canonical instructions: AGENTS.md (root) and ..." to name the workflow spine FIRST and label root AGENTS.md as the memory protocol, and CLAUDE.md either becomes a pointer or carries a marked-copy banner + a drift check against AGENTS.md. Consequence: no structural move, smaller diff, but the platform keeps a root file whose name means something different than it does on every consumer repo - permanently carried complexity.

Problem

Audit finding H6, verified first-hand 2026-07-23: the five pointer files all present root AGENTS.md as canonical instructions; on this repo that file is the memory protocol (AGENTS.md:1), and CLAUDE.md is a full second copy of it with no divergence guard. The installer itself implements the opposite default for consumers and documents why (install.sh:444-447), keeping the platform as a special case (:515) that nothing at the reading surfaces explains. Concrete failure modes: an agent reading only root AGENTS.md (the file the most tools read natively) learns memory law but not the two HITL gates or the never-push rule from the workflow side; and the AGENTS.md/CLAUDE.md byte-duplication forks silently the first time someone edits one (the protocol has already been amended repeatedly - P19..P22 - so edits are routine).

Proposed Solution

Present the fork (above), and once the operator picks a branch, implement it plus the branch-independent invariants: (1) an agent that reads only root AGENTS.md on this repo encounters, within the first screen of text, where task/HITL law lives; (2) every pointer file names the workflow spine unambiguously and describes root AGENTS.md's actual identity truthfully; (3) the memory protocol has exactly one normative source and every other copy declares itself a copy (pointer or marked duplicate with a drift check); (4) a grep-based test suite (scripts/tests/test_entrypoint_identity.sh) pins all three so the identity cannot silently regress. The suite is written to assert the invariants, not the branch, so it survives the decision.

Alternatives Considered

Success Metrics

Scope

In scope: the operator decision record; root AGENTS.md, CLAUDE.md, and the five pointer files on this repo; install.sh's platform exception (Branch A deletes it; Branch B keeps + documents it); the invariant test suite; CHANGELOG.

Out of scope / Non-Goals

Dependencies

None blocking on other tasks; blocked on the OPERATOR FORK above (this is a decision dependency, not a task dependency - deliberately not encoded in depends_on, which the queue reads as task-graph edges). Related: TASK-MEMORY-303 (memory-side contract hardening in the same wave).

AI Authorship Disclosure

1. Description (normative)

2. Acceptance criteria

3. Edge cases

Audit

§1 — Verdict summary

Seven §1 clauses, six ACs, six edge cases. The unusual shape - a spec that PASSES audit while implementation is BLOCKED on an operator fork - is deliberate and per the plan's approval boundary: the fork is presented to implementable depth on both branches, the acceptance surface is branch-independent, and clause 1.1 makes the halt mechanical for any implementer the queue routes here. The audit focused on whether the fork is genuinely undecided in the text (it must not smuggle a preference), whether the ACs survive either branch, and whether the block marker meets the §9.1-rule-5 discipline.

§2 — Findings (all resolved)

ISS-001 — the block was a prose note in the first draft, not a mechanical halt

"Operator decides" without a normative clause leaves the queue free to hand the task to an implementer who starts Branch A by taste. Resolved: clause 1.1 makes the recorded decision a MUST-precondition and names the halt behavior; AC 1 verifies the decision record precedes any implementation commit; the edge case declares the halt the designed outcome.

ISS-002 — first-draft ACs were Branch-A-shaped

Early ACs asserted "root AGENTS.md is the spine" - deciding the fork through the acceptance surface, which is the same smuggling clause 1.1 forbids. Resolved: ACs 2-6 assert branch-independent invariants (first-screen reachability, truthful pointers, single normative source, branch-consistency) with per-branch arms only where the branches genuinely diverge (AC 5).

ISS-003 — the CLAUDE.md divergence hazard was treated as future-proofing, not a live risk

AGENTS.md and CLAUDE.md are full duplicates TODAY, and the protocol has been amended four times (P19-P22) - a silent fork is one edit away, and unifying the copies during implementation could silently drop an edit one copy never received. Resolved: the edge case makes surfacing any discovered diff to the operator mandatory before unification (protocol-content territory, §0.2), and clause 1.4's drift check covers the marked-duplicate future.

ISS-004 — Branch A's blast radius was understated

Moving the protocol's normative home touches more than three files: walker citation strings ("AGENTS.md §3"), memory docs, and the installer exception all assume the root home. Resolved: the Branch A description names the sweep explicitly; clause 1.5's Branch A arm requires it; AC 5 greps for stale assumptions.

ISS-005 — "decision dependency" vs depends_on needed an explicit convention call

Encoding the fork as depends_on would wedge the task on a nonexistent task id; leaving it out entirely loses the block from the graph view. Resolved: Dependencies states the distinction (decision dependency, deliberately not a task-graph edge) and the body block marker carries it per §9.1 rule 5 - the queue-visible surface.

ISS-006 — verify axis and testability tension (structural docs task with grep ACs)

A verify: I task whose ACs cite a shell suite risks TRACE-friction (inspection claims with test citations). Resolved: the suite is scoped to the mechanically-checkable invariants (line-window greps, marker presence, drift check), while AC 1's decision-record half is explicitly review-time inspection - each AC names its real verification mode and the verify: I axis reflects the task's center of gravity.

§3 — TRACE-006 semantic sufficiency (per clause)

ClauseVerb demandCited test assertsVerdict
1.1 MUST NOT begin until decision recordeddecision entry precedes implementation commitsAC 1: spec-history inspection + t01 asserts the entry existssufficient (inspection-mode, declared)
1.2 MUST surface task law in first 30 lineshead-30 grep for the spine referenceAC 2: asserts the windowsufficient
1.3 MUST name spine + truthful identity in six filesper-file greps incl. Branch-B negative phrasingAC 3: asserts both halvessufficient
1.4 MUST have one normative source; copies declareexactly-one-unmarked census + drift-check pass/failAC 4: asserts census AND mutated-copy failuresufficient
1.5 MUST remove exception + sweep (A) / comment it (B)branch-scoped grepsAC 5: asserts the chosen branch's armsufficient
1.6 MUST assert invariants, glob-registeredsuite green under run_all discoveryAC 6: asserts registrationsufficient
1.7 MUST record branch in CHANGELOGsubstring in top entryAC 6: asserts itsufficient

§4 — Resolution

Six findings - two fork-integrity, four material - all resolved in the audited revision. Score = 10/10.

Status transition draft -> ready_to_implement is authorised by this verdict per STATUS-REFERENCE.md §1.1 - with the explicit note that clause 1.1 blocks implementation on the operator fork; the task sits in the queue as the fork's forcing function, not as buildable-now work. The two human-acceptance gates in /ship-tasks are unchanged.


End of TASK-IMP-138 audit.