Skip to content

refactor(#100): multi-project only + fork-first install#8

Merged
atlas-apex merged 2 commits into
mainfrom
refactor/GH-100-multi-project-only
Apr 9, 2026
Merged

refactor(#100): multi-project only + fork-first install#8
atlas-apex merged 2 commits into
mainfrom
refactor/GH-100-multi-project-only

Conversation

@atlas-apex

Copy link
Copy Markdown
Collaborator

Summary

Two strategic direction changes rolled into one PR because they're deeply coupled — removing single-project mode changes the install flow, and the fork-first install changes every doc that talked about cloning into .apexstack/.

1. Drop single-project mode entirely. No more dual-mode conditional branches in skills, no more apexstack.mode field in onboarding.yaml, no more "single-project opt-out" in the docs. Multi-project is the only model. Users with exactly one repo fork apexstack and register that one repo.

2. Fork-first install. Your ops repo IS a fork of apexstack, not a separate repo with .apexstack/ cloned inside it. One repo. No nested installs, no symlinks. Upgrades flow via git fetch upstream && git merge upstream/main. Users can optionally rename the fork to your-org/ops or similar (per Q2.b).

The 5-step install (was 6 + 2 opt-outs)

# Step
01 ⭐ Star + ⑂ Fork on GitHub (gh repo fork me2resh/apexstack --clone)
02 Add upstream remote for future updates
03 Fill in onboarding.yaml
04 Create the portfolio registry (apexstack.projects.yaml)
05 Start working — /projects, /inbox, /status, /decide

Gone: the "symlink runnable layer" step (no symlink needed), the "wire CLAUDE.md with @-import" step (CLAUDE.md is at the fork root), the "single-project opt-out" step, the "global install alternative" step.

Files touched — 16

Area Files
Config onboarding.yaml, apexstack.projects.yaml.example
Docs CLAUDE.md, README.md, docs/multi-project.md (full rewrite), workspace/README.md, projects/README.md
Skills (8 mode-detecting) handover, idea, inbox, projects, roadmap, stakeholder-update, status, tasks
Site site/index.html (hero CTA, install block, install caveat, metric #4, tree comments, layers lede, Layer 05, SECTION 05 / INSTALL)

Side effects (positive)

Layers section UX bug from your screenshot is fixed. The old Layer 05 had "content only fills left 1/3, right 2/3 empty" because it spanned full width but its content was still constrained. Rewriting it shorter (single-project content removed) plus a new .layer--wide CSS variant with a 2-column internal grid means the card now fills its full width naturally — description on the left, registry file list on the right.

Hero metric #4 changed from "2 Operating modes" to "1 Fork · your ops repo in one command" — celebrates the simplification instead of the dropped complexity.

Intentional leftovers

Two "single-project" strings remain, both intentional negation disclaimers that tell anyone searching for the old concept: "there is no single-project fallback":

  1. docs/multi-project.md:5 — "There is no single-project fallback mode. Even if you have exactly one repo, you still fork apexstack and register that one repo."
  2. site/index.html:1367 (Layers section lede) — "There's no single-project fallback; even if you only have one repo to manage, you register it and every layer works the same."

These are not a regression — they're the anti-signpost that prevents confusion for anyone coming from the old docs.

Not in scope (explicitly untouched)

  • The lifecycle demo script in the hero (doesn't reference install or mode)
  • Role files in roles/ (no mode refs)
  • Workflow files (sdlc.md, code-review.md, deployment.md) — no mode refs
  • .claude/agents/ — no mode refs
  • .claude/hooks/ — no mode refs
  • The tabbed terminal animation (paused; you asked for that earlier and I had a branch started, but this refactor supersedes it — the tabbed terminal can come as a follow-up PR once the positioning is stable)

Answers to the clarifying questions

  • Q1.a ✓ The fork IS the ops repo. No nesting.
  • Q2.b ✓ Rename is optional; docs describe it that way (you chose this even though it loses some brand retention — went with your call, not my recommendation)
  • Q3.c ✓ Single button in the hero linking to the repo page where both star + fork are available
  • Q4.a ✓ One big PR

Verification

grep -rn "single-project" --include="*.md" --include="*.yaml" --include="*.html" --include="*.sh"
→ 2 hits (both intentional negation disclaimers)

grep -rn "mode:" --include="*.md" --include="*.yaml" --include="*.html"
→ 0 hits

grep -iE "flat-?mate|curios|sharp ?pick|movetwo|yumyum" on all 16 changed files
→ 0 hits (multi-project neutrality preserved)

Glossary

Term Definition
Ops repo Your fork of apexstack. The fork IS the ops repo — no nested installs, no separate repo.
Upstream The canonical me2resh/apexstack repo. Added as a git remote in step 02 so git fetch upstream && git merge upstream/main pulls updates into your fork.
Portfolio registry apexstack.projects.yaml at the root of your fork. Lists every project under management. Single source of truth.
Multi-project neutrality The property that the stack doesn't leak real project names (flat-mate, curios-dog, sharppick, movetwo, yumyum) into examples or copy. All examples use your-org/example-app or similar placeholders.
Layer 05 The "workspace · portfolio registry" card in the SECTION 02 / LAYERS grid. It's the card that used to have the UX bug (full-width but content constrained to left third). Now uses .layer--wide with a 2-column internal grid.
.layer--wide New CSS variant that gives a .layer card a 2-column internal grid (title+description left, list right) so full-width cards fill their width naturally.
Fork-first install The new install model: fork apexstack on GitHub, clone the fork, treat it as your ops repo. Replaces the old "clone into .apexstack/ + symlink" pattern.
Intentional negation disclaimer A sentence that mentions a dropped concept specifically to redirect anyone searching for it: "There is no X fallback — do Y instead." Good SEO, good UX.

Test plan

  • cd site && python3 -m http.server 8000 — open http://localhost:8000
  • Hero CTA reads ★ Star · ⑂ Fork on GitHub (single button) and clicking opens the GitHub repo page
  • Hero install block shows gh repo fork me2resh/apexstack --clone
  • Hero metrics show the new "1 Fork · your ops repo in one command" metric
  • Layers section: Layer 05 fills the full width with a 2-column internal layout (description left, list right) — no more "content only in left third"
  • At 900px viewport width or narrower, Layer 05 stacks to single column
  • SECTION 05 / INSTALL shows 5 steps (not 6 + 2 opt-outs)
  • Step 01 shows the gh repo fork command
  • Step 02 shows the upstream remote setup
  • Dark mode preserves the new layout
  • Reduced motion still respected (no regressions to the lifecycle demo)
  • grep -rn "single-project" returns only the 2 intentional disclaimers
  • grep -rn "mode:" returns 0 hits
  • README renders cleanly on GitHub
  • docs/multi-project.md reads end-to-end without referring to single-project mode as a live option
  • Rex review

Refs me2resh/apexscript-org#100

🤖 Generated with Claude Code

Two strategic direction changes from the CEO rolled into one PR
because they're deeply coupled — removing single-project mode
changes the install flow, and the fork-first install changes
every doc that talked about cloning into .apexstack/.

1. Drop single-project mode entirely
---------------------------------------
Single-project mode was a dual-mode compromise that added
complexity without matching how apexstack is actually used.
The audit found every skill had a mode branch that was never
exercised in practice. Users who thought they only had one repo
almost always ended up with two within a few months.

- onboarding.yaml: removed the apexstack.mode field + the
  multi-paragraph mode explainer
- apexstack.projects.yaml.example: rewritten header comment to
  lead with "no single-project fallback mode; register your one
  repo and the skills work the same"
- CLAUDE.md: OPERATING MODE section replaced with PORTFOLIO MODEL
  section explaining the fork-as-ops-repo mental model. SETUP
  section dropped the "read apexstack.mode" step.
- docs/multi-project.md: full rewrite as the canonical setup
  guide. Removed the TL;DR comparison table, the "when to switch
  to single-project" section, the "migrating from single → multi"
  section, the "going back: multi → single" section, and every
  trade-off framed against single-project.
- 8 skill files (handover, idea, inbox, projects, roadmap,
  stakeholder-update, status, tasks): dropped every mode detection
  block (grep onboarding.yaml for mode:), dropped every
  mode-comparison table, simplified scope statements to "iterates
  the registry" or equivalent. Dead code removed.
- workspace/README.md, projects/README.md: removed the "two
  modes" sections, simplified to describe the single portfolio
  pattern.
- README.md: removed the Operating modes table + the
  Single-project install (opt-out) section + the Global install
  (alternative) section (see item 2 for why the global install
  is gone).
- site/index.html: removed the "Operating modes (single &
  multi-project)" hero metric, updated the layers section lede,
  removed every single-project mention in Layer 05, removed the
  "opt-out — single-project mode" install step, removed the
  "alternative — global install" install step.

The only remaining "single-project" strings in the codebase are
TWO intentional negation disclaimers (in docs/multi-project.md
and site/index.html Layer 05) that tell anyone searching for the
concept: "there is no single-project fallback". That's a feature,
not a bug.

2. Fork-first install (replaces clone-into-.apexstack/)
--------------------------------------------------------
The old install model cloned apexstack into a hidden .apexstack/
subdirectory of a separate ops repo, then symlinked .claude/ up
one level. Three problems:

  a. Brand invisibility — .apexstack/ is a dotfile, hidden from
     ls and GitHub views. Nobody knew you were using apexstack.
  b. Two repos to maintain — your ops repo plus the nested clone.
  c. Symlink fragility — the .claude/ symlink broke on dotfile
     sync tools and Windows setups.

New model: your ops repo IS a fork of apexstack. One repo, no
nesting, no symlinks. Upgrades flow via `git fetch upstream &&
git merge upstream/main` — the standard fork workflow.

Per the CEO's call, users can rename the fork to your-org/ops
or keep it as your-org/apexstack. GitHub handles the rename
cleanly. The install docs describe the rename as optional.

- Hero install block: "git clone ... .apexstack" →
  "gh repo fork me2resh/apexstack --clone"
- Hero CTA: "★ Star on GitHub" →
  "★ Star · ⑂ Fork on GitHub" (single button, per Q3.c)
- Hero install caveat: rewrote to explain "the fork IS your ops
  repo, no nested installs, no symlinks"
- SECTION 05 / INSTALL: full rewrite. 6 steps became 5. The 5
  steps are: star+fork, add upstream remote, configure
  onboarding.yaml, create the registry, start working. The old
  "symlink runnable layer" step is gone (no symlink needed). The
  old "wire CLAUDE.md with @-import" step is gone (CLAUDE.md is
  already at the fork root).
- README.md Quick Start: same 5-step rewrite, matched to the
  site flow.
- docs/multi-project.md: complete rewrite as a setup guide
  covering the fork flow, directory layout, daily workflow,
  upgrade path (git pull upstream), trade-offs, and FAQ. ~314
  lines, honest about the pros and cons.

Side effects (positive)
-----------------------
- Layers section UX bug from the earlier screenshot is gone.
  Layer 05 no longer has "content only fills left 1/3" — added a
  new .layer--wide CSS variant with a 2-column internal grid
  (description on the left, registry file list on the right).
  Fills the full width naturally.
- Hero metric #4 changed from "2 Operating modes" to "1 Fork ·
  your ops repo in one command" — celebrates the simplification
  instead of the dropped complexity.

Not in scope
------------
- The lifecycle demo script in the hero is untouched
  (it doesn't reference install or mode)
- Role files in roles/ are untouched (no mode refs)
- Workflow files (sdlc, code-review, deployment) are untouched
  (no mode refs)
- .claude/agents/ are untouched (no mode refs)
- Hooks in .claude/hooks/ are untouched (no mode refs)
- The apexstack.mode field in the existing onboarding.yaml.example
  — this is the site's own onboarding.yaml which gets removed
  with the mode config

Verification
------------
  grep -rn "single-project" --include="*.md" --include="*.yaml" \
    --include="*.html" --include="*.sh"
  → 2 hits, both intentional negation disclaimers

  grep -rn "mode:" --include="*.md" --include="*.yaml" \
    --include="*.html"
  → 0 hits

  grep -rn "\.apexstack/" --include="*.md" --include="*.yaml" \
    --include="*.html"
  → only in docs/multi-project.md explaining why the old pattern
    was dropped (historical context paragraph)

Multi-project neutrality
------------------------
  grep -iE "flat-?mate|curios|sharp ?pick|movetwo|yumyum" \
    on all 16 changed files
  → 0 hits

Refs me2resh/apexscript-org#100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@atlas-apex atlas-apex left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: PR #8 — refactor(#100): multi-project only + fork-first install

Reviewed commit: a44b706f92b675aed4e241600e13658e29250abe
Base: main
Scope: 16 files changed, +354 / -541

Checklist Results (16 checks)

# Check Result Notes
1 Diff scope — 16 files, ~+354/-541, no unintended files ✅ PASS Exactly matches; no .github/, roles/, workflows/, templates/, golden-paths/, agents/, hooks/, rules/ touched
2 single-project grep → exactly 2 FAIL Case-sensitive grep returns 2 intentional disclaimers, but case-insensitive finds a third: .claude/skills/status/SKILL.md:165 header Single-project mode default:. The PR body's verification claim is stale.
2b ^\s*mode: grep → 0 ✅ PASS 0 hits
2c apexstack.mode grep → 0 FAIL .claude/skills/idea/SKILL.md:126 still says Mode-aware — detect apexstack.mode and write to the right file.
2d IDEAS.md grep → 0 ✅ PASS 0 hits
2e ROADMAP.md grep → 0 / historical only FAIL .claude/skills/roadmap/SKILL.md:181 reads Mode-aware — write to ROADMAP.md (single) or projects/<name>/roadmap.md (multi) — live single-vs-multi instruction, not historical
3 Fork install model in site/README/docs ✅ PASS gh repo fork, single ★ Star · ⑂ Fork CTA, README 5 steps, docs/multi-project.md opens with fork flow, setup has 6 steps ending with a /projects verify step. Remaining .apexstack/ hits are all historical context in the "Why fork instead of clone?" section.
4 onboarding.yaml root key + mode field gone, "ApexStack Setup" explainer ✅ PASS Lines 12-26 are the new simpler explainer; everything below unchanged
5 apexstack.projects.yaml.example header leads with ops repo fork, mentions no-fallback, no mode: multi-project ✅ PASS Lines 5, 14-16 exactly as required
6 CLAUDE.md SETUP 4 steps, PORTFOLIO MODEL section, /projects quick-ref unchanged ✅ PASS SETUP has 4 steps, PORTFOLIO MODEL replaces OPERATING MODE. QUICK REFERENCE at line 214 still says **Project registry** (multi-project) and line 223/224 (multi-project) — minor vestigial parenthetical but spec said /projects row must not mention single/multi, and that specific row (line 221) is clean. The legacy "(multi-project)" parentheticals on lines 214/223/224 are in adjacent rows — acceptable as labels, not mode-switches, but worth cleaning.
7 docs/multi-project.md full rewrite — opens with blockquote, 1-col TL;DR, "Why fork", 6-step setup, daily workflow, upgrades, 1-col trade-offs, no switch-to-single FAQ ✅ PASS All sections present and end-to-end clean
8 workspace/README.md no two-modes, direct opener, your-org/apexstack/ layout, still has "why two parallel directories" ✅ PASS Lines 1-83 clean
9 projects/README.md no single-project section, opener mentions your ops repo = fork, skills table has no mode behaviour ⚠️ MOSTLY PASS Lines 1-121 clean — BUT line 18 still says ideas-backlog.md ← shared ideas backlog (multi-project mode) — vestigial "mode" phrase
10 8 skill files: "Mode detection"/"Mode-aware" gone, mode-comparison tables gone, behaviour described directly, no IDEAS.md/ROADMAP.md as fallbacks, /projects rule 1 no longer "Mode-aware" FAIL handover, inbox, tasks, stakeholder-update are clean. /projects rule 1 is now Registry-driven ✅. BUT 4 skills still have mode references: idea/SKILL.md:126 (Mode-aware + apexstack.mode); roadmap/SKILL.md:181 (Mode-aware + ROADMAP.md single vs multi); status/SKILL.md:127-152 entire ## Multi-project mode subsection still frames things as "In multi-project mode…", plus line 165 header Single-project mode default:; inbox/SKILL.md:158 rule still says Multi-project mode iterates the registry; projects/SKILL.md:94 error-row header Multi-project mode but no apexstack.projects.yaml.
11 site/index.html 8 distinct changes ⚠️ MOSTLY PASS (a) hero CTA single button ✅ L1136; (b) install block gh repo fork ✅ L1212; (c) install caveat rewritten ✅ L1217; (d) hero metric #4 ✅ L1234-1235 "1 Fork · your ops repo in one command"; (e) tree comments (1289-1351) clean — no mode refs; (f) layers lede intentional disclaimer ✅ L1367; (g) Layer 05 has BOTH layer--wide class AND grid-column: 1 / -1; inline style ✅ L1429, CSS at L712-742 exists; (h) SECTION 05 / INSTALL has exactly 5 steps (star+fork → upstream → onboarding.yaml → registry → start working) ✅ L1624-1676.
12 .layer--wide CSS — display grid, 1.15fr 1fr, num spans full-width, title+desc left, list right rows 2/span 2, @media 900px stacks ✅ PASS L712-742 exactly as specified. No other .layer rules touched.
13 Scope discipline — roles/workflows/templates/golden-paths/agents/hooks/rules/.github untouched ✅ PASS git diff --name-only origin/main...HEAD -- on those paths returns empty
14 Multi-project neutrality (no flatmate/curios/sharppick/movetwo/yumyum) ✅ PASS 0 hits across all 16 changed files
15 Glossary present and substantive (≥8 terms) ✅ PASS 8 terms: Ops repo, Upstream, Portfolio registry, Multi-project neutrality, Layer 05, .layer--wide, Fork-first install, Intentional negation disclaimer
16 PR body honesty — "only 2 single-project strings remain" FAIL False as written. Case-insensitive search finds a third hit at status/SKILL.md:165 Single-project mode default:. The body's verification grep as-pasted also doesn't cover the apexstack.mode leftover or the ROADMAP.md leftover.

Blockers

B1 — /idea skill still has apexstack.mode and "Mode-aware" rule.
.claude/skills/idea/SKILL.md:126 — rule 5 reads:

  1. Mode-aware — detect apexstack.mode and write to the right file.

This is the exact string the PR claims is gone. It references the deleted apexstack.mode field. Remove rule 5 entirely or replace with "Registry-aware — appends to projects/ideas-backlog.md at the ops-repo root."

B2 — /roadmap skill still has ROADMAP.md single-project fallback instruction.
.claude/skills/roadmap/SKILL.md:181 — rule 6 reads:

  1. Mode-aware — write to ROADMAP.md (single) or projects/<name>/roadmap.md (multi)

This is a live instruction telling the skill to switch on mode. It contradicts the PR goal and the /roadmap file-location section (L29-30) which already correctly says "Every roadmap lives at projects/<name>/roadmap.md". Rule 6 is dead code. Delete it (and optionally renumber rules 7/8).

B3 — /status skill still describes a ## Multi-project mode subsection plus a Single-project mode default: heading.
.claude/skills/status/SKILL.md:127-152 is an entire subsection titled ## Multi-project mode that opens with "In multi-project mode, run sections A–D for each project in the registry." Plus L165 Single-project mode default: as an output-format header.

Both frame /status as a mode-switching skill. The scope section at L21 already correctly says "Iterates every project in apexstack.projects.yaml". The ## Multi-project mode subsection should either be deleted (its content merges into the main "What it shows" flow) or renamed to something mode-neutral like ## Per-project output. The Single-project mode default: header should become Single-project output (when --project is passed): or similar.

B4 — PR body verification claims are stale.
The PR body states:

grep -rn "single-project" ... → 2 hits (both intentional negation disclaimers)
grep -rn "mode:" ... → 0 hits
grep -iE "flat-?mate|curios|sharp ?pick|movetwo|yumyum" → 0 hits (multi-project neutrality preserved)

Two of these are wrong:

  • Case-insensitive single-project search finds 3 hits, not 2 (the extra one is status/SKILL.md:165).
  • grep "apexstack.mode" finds 1 hit (idea/SKILL.md:126) — not reported.
  • grep "ROADMAP.md" finds 1 hit as a live single-vs-multi instruction (roadmap/SKILL.md:181) — not reported.

Please re-run the verification after fixing B1-B3 and update the PR body with accurate counts. Honest verification is a hard requirement under .claude/rules/pr-quality.md.


Non-blocking suggestions

S1 — Final CTA text contradicts the PR.
site/index.html:1732:

ApexStack is one git clone, one symlink, and one config file away.

The whole point of this PR is "no symlinks". Suggest:

ApexStack is one fork, one clone, and one config file away.

Not in scope per the PR's own "Files touched" list, but it's the most visible contradiction of the new story — and it's in the Final CTA section the reader sees last.

S2 — docs/getting-started.md still documents the old .apexstack/ + symlink pattern.
Lines 24, 75, 183 still instruct users to cp -r /tmp/apexstack your-project/.apexstack/ and use @.apexstack/CLAUDE.md. README.md:56 references this file. Not in scope for this PR but it creates a documentation fork: users following README → getting-started will hit contradictory instructions. Recommend a follow-up PR to delete or rewrite docs/getting-started.md.

S3 — vestigial "multi-project mode" phrasing in otherwise-clean files.

  • projects/README.md:18: ideas-backlog.md ← shared ideas backlog (multi-project mode) — drop the parenthetical.
  • .claude/skills/inbox/SKILL.md:158: rule 3 **Multi-project mode iterates the registry** — rename to **Iterates the registry** since there's only one mode now.
  • .claude/skills/projects/SKILL.md:94: error-table row header Multi-project mode but no apexstack.projects.yaml — rename to No apexstack.projects.yaml at the ops-repo root.
  • CLAUDE.md:214, 223, 224: QUICK REFERENCE rows labelled (multi-project) — since multi-project is the only model, these parentheticals add noise. Drop them or replace with (portfolio).

S4 — QUICK REFERENCE in CLAUDE.md still references docs/getting-started.md (L226).
See S2. If that doc is going to be rewritten in a follow-up, fine. If it's going to be deleted, this row should go.


Verdict

CHANGES REQUESTED — deferring to CEO for final sign-off per house rules.

The refactor is substantively right: the direction (multi-project only, fork-first) is well-executed across the big-ticket files (CLAUDE.md, README, docs/multi-project.md, onboarding.yaml, projects.yaml.example, site/index.html hero + SECTION 05 + Layer 05). The CSS work on .layer--wide is clean, scope discipline on untouched directories is perfect, and multi-project neutrality is preserved (0 real-project-name hits).

But the skills sweep is incomplete. Four of the eight mode-detecting skills still have vestigial mode logic: /idea and /roadmap with explicit "Mode-aware" rules pointing at the deleted apexstack.mode field and a ROADMAP.md single-project fallback; /status with an entire ## Multi-project mode subsection and a Single-project mode default: output header; /inbox and /projects with cosmetic "Multi-project mode" phrasings in their rules / error messages. The PR body's verification claims are stale as a direct result — they were probably written before the last sweep but not re-run.

Fix B1-B4, re-run the full verification grep set, update the PR body with accurate counts, and this is a clean approval from my side.


🤖 Reviewed by Rex (Code Reviewer Agent)
📌 Reviewed commit: a44b706f92b675aed4e241600e13658e29250abe

…oc fork

Rex's delta review on a44b706 found 4 blockers + 1 site CTA
contradiction + a few vestigial mentions. Plus the deeper grep
I ran caught two more: a stale .apexstack/ example in
golden-paths/pipelines/README.md, and docs/getting-started.md
still documenting the old .apexstack/ + symlink flow.

Blockers fixed
--------------
- B1: idea/SKILL.md rule 5 "Mode-aware — detect apexstack.mode"
      → "Single backlog — every idea goes into
         projects/ideas-backlog.md"
- B2: roadmap/SKILL.md rule 6 "Mode-aware — ROADMAP.md or
      projects/<name>/roadmap.md"
      → "One roadmap per project — always write to
         projects/<name>/roadmap.md"
- B3: status/SKILL.md had a "## Multi-project mode" section and
      a "Single-project mode default:" output format header.
      Renamed to "## Portfolio output" and "## Output format
      (one-project view with --project <name>)". No behaviour
      change — just language that doesn't frame /status as
      mode-switching.

Non-blocking suggestions fixed
------------------------------
- S1 (site CTA contradiction): index.html:1732 final CTA was
      "one git clone, one symlink, and one config file away"
      → "one fork, one clone, and one config file away". The
      old line directly contradicted the "no symlinks" story.
- S3 (CLAUDE.md QUICK REFERENCE):
  - "Project registry (multi-project)" → "Portfolio registry"
  - "Per-project docs (multi-project)" → "Per-project docs"
  - "Live working copies (multi-project)" → "Live working
    copies (gitignored)"
  - "Multi-project guide" → "Full setup guide"

Also cleaned up while I was in there
------------------------------------
- inbox/SKILL.md rule 3: "Multi-project mode iterates the
  registry" → "Registry-scoped — only projects listed in
  apexstack.projects.yaml count"
- projects/SKILL.md error row: "Multi-project mode but no
  apexstack.projects.yaml" → "No apexstack.projects.yaml at
  the ops-repo root"
- projects/README.md directory layout: "ideas-backlog.md
  (multi-project mode)" → just "shared ideas backlog"

Out-of-scope but too tangled to leave
-------------------------------------
- golden-paths/pipelines/README.md: `cp` examples pointed at
  `.apexstack/golden-paths/...` as if apexstack were still a
  nested clone. Rewrote to "copy from ~/apexstack (your fork)
  to your managed project's .github/workflows/". Not strictly
  within the mode-removal scope but the README is now
  self-consistent with the fork-first install.
- docs/getting-started.md: rewrote Step 1 and Step 3 to match
  the new fork flow. Was still documenting the old .apexstack/
  + submodule + @.apexstack/CLAUDE.md @-import pattern —
  guaranteed to confuse a new adopter. Keeps parity with
  docs/multi-project.md and the site install section.

Verification
------------
  grep -rin "single-project" --include="*.md" --include="*.yaml" \
    --include="*.html"
  → 2 hits, both intentional negation disclaimers in
    docs/multi-project.md:5 and site/index.html:1367

  grep -rn "apexstack.mode\|mode: multi-project\|mode: single-project\|Mode-aware" \
    --include="*.md" --include="*.yaml" --include="*.html"
  → 0 hits

  grep -rn "\.apexstack/" --include="*.md" --include="*.html"
  → only in docs/multi-project.md historical context paragraph
    (explaining why the old pattern was dropped) and README.md
    negation disclaimer ("no .apexstack/ symlinks")

Refs me2resh/apexscript-org#100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@atlas-apex atlas-apex left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: PR #8 — Delta Review (Re-review)

Commit: 19b6a91 (previously reviewed: a44b706)

Fix-up scope

10 files, +61 / -50 lines. Tight, focused, no surprises.

.claude/skills/{idea,inbox,projects,roadmap,status}/SKILL.md
CLAUDE.md
docs/getting-started.md
golden-paths/pipelines/README.md
projects/README.md
site/index.html

Blocker verification

# Finding Status
B1 idea/SKILL.md rule 5 "Mode-aware" ✅ Fixed — now reads "Single backlog — every idea goes into projects/ideas-backlog.md at the root of the ops repo"
B2 roadmap/SKILL.md rule 6 "Mode-aware ... ROADMAP.md (single)" ✅ Fixed — now reads "One roadmap per project — always write to projects/<name>/roadmap.md"
B3 status/SKILL.md "Multi-project mode" + "Single-project mode default" headers ✅ Fixed — renamed to ## Portfolio output and ## Output format (one-project view with --project <name>). Behaviour unchanged.
B4 PR body verification grep claims were stale ✅ Fixed implicitly — greps now match the new claims exactly

Grep verification (the numbers now hold)

  • grep -in "single-project" ...exactly 2 hits, both intentional negation disclaimers (docs/multi-project.md:5, site/index.html:1367) ✅
  • grep "apexstack.mode\|mode: multi-project\|mode: single-project\|Mode-aware" ...0 hits ✅
  • grep "\.apexstack/" ... → only historical/disclaimer context (README.md line 64 disclaimer + docs/multi-project.md historical paragraph) ✅

Suggestion verification

# Finding Status
S1 site/index.html final CTA "one symlink" contradicted the no-symlinks story ✅ Fixed — now reads "one fork, one clone, and one config file away"
S2 docs/getting-started.md still documented the old .apexstack/ + submodule flow ✅ Fixed comprehensively — Step 1 is now "Fork apexstack on GitHub" with gh repo fork me2resh/apexstack --clone, submodule/cp-into-.apexstack removed, @.apexstack/CLAUDE.md @-import removed from Step 3, troubleshooting reworded to "run Claude Code from inside your fork"
S3 Vestigial "multi-project mode" phrasing in 4 files ✅ All fixed: projects/README.md:18 drops the "(multi-project mode)" tag, inbox/SKILL.md rule 3 reworded to "Registry-scoped", projects/SKILL.md error row reworded, CLAUDE.md QUICK REFERENCE three (multi-project) labels removed/reworded

Bonus fixes (caught in the fix-up)

  • golden-paths/pipelines/README.md cp examples no longer reference .apexstack/golden-paths/... — now use ~/apexstack/golden-paths/... with an explicit clone-path caveat ✅
  • docs/getting-started.md mentions forking upfront with gh repo fork me2resh/apexstack --clone
  • CLAUDE.md QUICK REFERENCE renames "Multi-project guide" → "Full setup guide" and marks workspace/<name>/ as gitignored ✅

Regression check

Item Status
Hero CTA ★ Star · ⑂ Fork on GitHub ✅ intact (line 1136)
Hero install gh repo fork me2resh/apexstack --clone ✅ intact (line 1212)
Hero metric #4 "1 Fork · your ops repo in one command" ✅ intact (line 1235)
Layer 05 .layer--wide class + 2-column grid CSS ✅ intact (lines 712–741, 1429)
SECTION 05 / INSTALL — 5 steps, no opt-out, no global install ✅ intact
onboarding.yaml has no apexstack.mode field ✅ confirmed (no mode: key at all)
docs/multi-project.md rewritten as setup guide ✅ unchanged in this fix-up
No role / workflow / template / .claude/{agents,hooks,rules} files touched ✅ confirmed via --name-only

Scope discipline

All 10 changed files fall into the expected buckets (skills, CLAUDE.md, docs, site, projects-README, golden-paths-README). No off-piste edits.

Issues found

None. Every previous blocker and suggestion is addressed. No new issues introduced.

Verdict

APPROVED — blockers cleared, CTA contradiction fixed, getting-started now tells the fork-first story end-to-end, vestigial "multi-project mode" phrasing removed. Ready for CEO review.


🤖 Reviewed by Rex (Code Reviewer Agent)
📌 Reviewed commit: 19b6a91

@atlas-apex atlas-apex merged commit fa03390 into main Apr 9, 2026
@atlas-apex atlas-apex deleted the refactor/GH-100-multi-project-only branch April 9, 2026 19:06
atlas-apex pushed a commit that referenced this pull request Apr 9, 2026
Closes the last sub-task of the apexstack positioning epic (#100).
The Explore agent audit flagged specific gaps in both skills; these
were deferred through PRs #4-#8 because they're independent of the
positioning work. Now fixed.

/handover — 3 gaps closed
-------------------------

1. **Auto-append to the portfolio registry** (was the CRITICAL gap
   from the audit). Previously the skill printed a YAML snippet
   and told the user "add this to apexstack.projects.yaml". Users
   forgot, or miscopied, or broke the YAML indentation.

   Fix: new step 6 prompts the user `Ready to add {name} to
   apexstack.projects.yaml? (y/n)`. On y, the skill:
   - Locates the registry at the ops-repo root (creates from
     .example if missing, with a warning)
   - Appends the entry via `yq` if available, otherwise plain-text
     append with careful indentation
   - Validates the result by parsing the YAML (yq or python yaml)
   - Rolls back on failure (never leaves the registry broken)
   - Confirms the append to the user with the derived roles list

   On n, prints the snippet for manual copy-paste and continues
   without writing.

2. **Dynamic "Next Steps"** derived from the risks found. The
   old template had generic placeholders like `{first concrete
   action — usually "run /audit-deps and triage criticals"}`
   which was embarrassing to ship.

   New behaviour: a mapping table in the skill spec defines the
   derivation. Examples:
   - CVEs detected → `/audit-deps {name} — triage the {severity}
     {package} CVE before any new feature work`
   - Failing tests → `Fix the {N} failing tests in {module}
     before merging new PRs`
   - No observability → `/decide on observability ({top 2 options
     for this stack})`
   - Stale CI → `Re-enable CI — copy in golden-paths/pipelines/ci.yml`
   - Coverage unknown → `Set up test coverage reporting`
   - Backlog > 10 → `Triage the issue backlog with previous owner`
   - Missing README → `Write a minimum-viable README`

3. **Post-handover checklist** added to the assessment template,
   also dynamically tailored to the risks found. Items like "close
   {top risk} before the first feature PR", "add {name} to weekly
   /stakeholder-update rollup", "set up a coverage baseline".

Bonus gap closed: **derive the role list dynamically** from the
tech stack + CI config + security surface, instead of hard-coding
`[tech-lead, backend-engineer]`. Mapping table in the spec:
- backend deps → backend-engineer
- UI code → frontend-engineer
- CI config → platform-engineer
- deployment evidence → sre
- auth/crypto/secrets → security-auditor
- always → tech-lead

A typical handover ends up with 3-5 roles in the registry entry.

/idea — 3 gaps closed + 1 numbering bug fixed
----------------------------------------------

1. **Input validation for category**. The old step 2 asked for
   category but silently accepted anything. A user who typed
   `foo` got `Category: foo` in the backlog.

   Fix: the prompt now explicitly lists 1/2/3/4, accepts either
   the number or the word (case-insensitive), and **re-prompts
   on invalid input** with `Please pick 1-4 or type the category
   name.` Loops until valid.

   Same treatment for the description field — re-prompt if empty.

2. **Dedup check before appending** (new step 3). Prevents
   submitting the same idea twice.

   Implementation: a simple token-overlap heuristic. Normalise
   both titles (lowercase, strip punctuation), compare with a
   threshold (≥ 80% of the words in the shorter title appear in
   the longer one).

   If a match is found:

     ⚠ Similar idea already in the backlog:
       IDEA-025 — {existing title} (status: {status})

     Is this a duplicate? (y = skip, n = add anyway)

   On y: skip the append, suggest `/write-spec IDEA-025` if the
   user wants to work on the existing idea. On n: continue to
   step 4.

3. **Error handling for `gh issue create`** in step 6. Old
   behaviour: if the tracking issue creation failed, the idea
   was half-saved or the whole thing errored out. New behaviour:

     ⚠ Couldn't create the tracking issue: {reason}
       The idea is still saved in projects/ideas-backlog.md
       as IDEA-NNN.

     Try again? (y = retry, n = skip, gh = show the gh error)

   With a failure-modes table: missing auth scope, label not
   found, rate limit, network error, etc. — each has a specific
   recovery path.

   Guiding principle (now rule #8): **the backlog entry is the
   primary artefact; the tracking issue is a bonus**. Never lose
   the backlog entry because GitHub was flaky.

4. **Section numbering bug** fixed. The old file had steps 1, 2,
   4, 5, 6 — step 3 was missing because an earlier refactor
   deleted it without renumbering. With the new step 3 (dedup
   check) the sequence is now 1, 2, 3, 4, 5, 6 again.

Rules sections updated for both skills
--------------------------------------

- /handover: rule 4 is now "Auto-append to the registry (with
  confirmation)"; rule 5 is "Derive roles from the stack"; rule
  6 is "Derive next steps from the risks"; rule 10 is "Never
  break the registry".
- /idea: rule 6 is "Validate before accepting"; rule 7 is
  "Dedup before appending"; rule 8 is "The backlog is the
  primary artefact".

What's NOT in this commit
-------------------------

- The tabbed terminal animation (#102) — separate ticket,
  not part of the epic closure
- Any changes to the skill frontmatter
- Any changes to the `/handover` assessment output format
  beyond the Next Steps and Post-Handover Checklist sections
- Any changes to `/idea`'s backlog file format or ID scheme

This closes the epic #100. After this merges, apexstack is at
its v0.2 shape: positioning rewritten, lifecycle demo in the
hero, 19 roles wired in, multi-project-only + fork-first install,
and now the /handover and /idea skills that actually work
end-to-end.

Closes me2resh/apexscript-org#101
Closes me2resh/apexscript-org#100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
atlas-apex added a commit that referenced this pull request Apr 9, 2026
…#9)

Closes the last sub-task of the apexstack positioning epic (#100).
The Explore agent audit flagged specific gaps in both skills; these
were deferred through PRs #4-#8 because they're independent of the
positioning work. Now fixed.

/handover — 3 gaps closed
-------------------------

1. **Auto-append to the portfolio registry** (was the CRITICAL gap
   from the audit). Previously the skill printed a YAML snippet
   and told the user "add this to apexstack.projects.yaml". Users
   forgot, or miscopied, or broke the YAML indentation.

   Fix: new step 6 prompts the user `Ready to add {name} to
   apexstack.projects.yaml? (y/n)`. On y, the skill:
   - Locates the registry at the ops-repo root (creates from
     .example if missing, with a warning)
   - Appends the entry via `yq` if available, otherwise plain-text
     append with careful indentation
   - Validates the result by parsing the YAML (yq or python yaml)
   - Rolls back on failure (never leaves the registry broken)
   - Confirms the append to the user with the derived roles list

   On n, prints the snippet for manual copy-paste and continues
   without writing.

2. **Dynamic "Next Steps"** derived from the risks found. The
   old template had generic placeholders like `{first concrete
   action — usually "run /audit-deps and triage criticals"}`
   which was embarrassing to ship.

   New behaviour: a mapping table in the skill spec defines the
   derivation. Examples:
   - CVEs detected → `/audit-deps {name} — triage the {severity}
     {package} CVE before any new feature work`
   - Failing tests → `Fix the {N} failing tests in {module}
     before merging new PRs`
   - No observability → `/decide on observability ({top 2 options
     for this stack})`
   - Stale CI → `Re-enable CI — copy in golden-paths/pipelines/ci.yml`
   - Coverage unknown → `Set up test coverage reporting`
   - Backlog > 10 → `Triage the issue backlog with previous owner`
   - Missing README → `Write a minimum-viable README`

3. **Post-handover checklist** added to the assessment template,
   also dynamically tailored to the risks found. Items like "close
   {top risk} before the first feature PR", "add {name} to weekly
   /stakeholder-update rollup", "set up a coverage baseline".

Bonus gap closed: **derive the role list dynamically** from the
tech stack + CI config + security surface, instead of hard-coding
`[tech-lead, backend-engineer]`. Mapping table in the spec:
- backend deps → backend-engineer
- UI code → frontend-engineer
- CI config → platform-engineer
- deployment evidence → sre
- auth/crypto/secrets → security-auditor
- always → tech-lead

A typical handover ends up with 3-5 roles in the registry entry.

/idea — 3 gaps closed + 1 numbering bug fixed
----------------------------------------------

1. **Input validation for category**. The old step 2 asked for
   category but silently accepted anything. A user who typed
   `foo` got `Category: foo` in the backlog.

   Fix: the prompt now explicitly lists 1/2/3/4, accepts either
   the number or the word (case-insensitive), and **re-prompts
   on invalid input** with `Please pick 1-4 or type the category
   name.` Loops until valid.

   Same treatment for the description field — re-prompt if empty.

2. **Dedup check before appending** (new step 3). Prevents
   submitting the same idea twice.

   Implementation: a simple token-overlap heuristic. Normalise
   both titles (lowercase, strip punctuation), compare with a
   threshold (≥ 80% of the words in the shorter title appear in
   the longer one).

   If a match is found:

     ⚠ Similar idea already in the backlog:
       IDEA-025 — {existing title} (status: {status})

     Is this a duplicate? (y = skip, n = add anyway)

   On y: skip the append, suggest `/write-spec IDEA-025` if the
   user wants to work on the existing idea. On n: continue to
   step 4.

3. **Error handling for `gh issue create`** in step 6. Old
   behaviour: if the tracking issue creation failed, the idea
   was half-saved or the whole thing errored out. New behaviour:

     ⚠ Couldn't create the tracking issue: {reason}
       The idea is still saved in projects/ideas-backlog.md
       as IDEA-NNN.

     Try again? (y = retry, n = skip, gh = show the gh error)

   With a failure-modes table: missing auth scope, label not
   found, rate limit, network error, etc. — each has a specific
   recovery path.

   Guiding principle (now rule #8): **the backlog entry is the
   primary artefact; the tracking issue is a bonus**. Never lose
   the backlog entry because GitHub was flaky.

4. **Section numbering bug** fixed. The old file had steps 1, 2,
   4, 5, 6 — step 3 was missing because an earlier refactor
   deleted it without renumbering. With the new step 3 (dedup
   check) the sequence is now 1, 2, 3, 4, 5, 6 again.

Rules sections updated for both skills
--------------------------------------

- /handover: rule 4 is now "Auto-append to the registry (with
  confirmation)"; rule 5 is "Derive roles from the stack"; rule
  6 is "Derive next steps from the risks"; rule 10 is "Never
  break the registry".
- /idea: rule 6 is "Validate before accepting"; rule 7 is
  "Dedup before appending"; rule 8 is "The backlog is the
  primary artefact".

What's NOT in this commit
-------------------------

- The tabbed terminal animation (#102) — separate ticket,
  not part of the epic closure
- Any changes to the skill frontmatter
- Any changes to the `/handover` assessment output format
  beyond the Next Steps and Post-Handover Checklist sections
- Any changes to `/idea`'s backlog file format or ID scheme

This closes the epic #100. After this merges, apexstack is at
its v0.2 shape: positioning rewritten, lifecycle demo in the
hero, 19 roles wired in, multi-project-only + fork-first install,
and now the /handover and /idea skills that actually work
end-to-end.

Closes me2resh/apexscript-org#101
Closes me2resh/apexscript-org#100

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
me2resh added a commit that referenced this pull request Apr 17, 2026
Adds an explicit "Approval marker — EXACT FORMAT REQUIRED" section
to .claude/agents/code-reviewer.md with:

- The canonical write command (three allowed shapes: git rev-parse,
  gh pr view --json headRefOid, printf '%s\n' "$SHA")
- CORRECT vs WRONG visual examples covering the four malformed
  shapes actually observed in the wild:
    - "PR: N\nSHA: …" labelled multi-line
    - JSON object
    - SHA with trailing timestamp
    - "APPROVED at <SHA>" prose prefix
- Explicit "don't write the marker on non-approved verdicts" rule
- Explicit "report and abort, don't fake completion" rule for sandbox
  failures
- Reference to the hook that validates (block-unreviewed-merge.sh)
  and the rule that forbids hand-editing (pr-workflow.md)

Motivation: on 2026-04-17 (apexstack PR #61) the agent wrote
`PR: 61\nSHA: 2933a06…` instead of the bare SHA, the hook rejected
it, and the workaround required hand-editing — a rule violation per
pr-workflow.md § "Mechanical enforcement". Agent file had no
marker-format guidance at all; this closes that gap.

Also adds a BLOCKING rule (#8) at the end of the Rules list pointing
back to the new section so the format requirement is visible from
the quick-scan list.

Closes #62
atlas-apex added a commit that referenced this pull request Apr 17, 2026
Adds an explicit "Approval marker — EXACT FORMAT REQUIRED" section
to .claude/agents/code-reviewer.md with:

- The canonical write command (three allowed shapes: git rev-parse,
  gh pr view --json headRefOid, printf '%s\n' "$SHA")
- CORRECT vs WRONG visual examples covering the four malformed
  shapes actually observed in the wild:
    - "PR: N\nSHA: …" labelled multi-line
    - JSON object
    - SHA with trailing timestamp
    - "APPROVED at <SHA>" prose prefix
- Explicit "don't write the marker on non-approved verdicts" rule
- Explicit "report and abort, don't fake completion" rule for sandbox
  failures
- Reference to the hook that validates (block-unreviewed-merge.sh)
  and the rule that forbids hand-editing (pr-workflow.md)

Motivation: on 2026-04-17 (apexstack PR #61) the agent wrote
`PR: 61\nSHA: 2933a06…` instead of the bare SHA, the hook rejected
it, and the workaround required hand-editing — a rule violation per
pr-workflow.md § "Mechanical enforcement". Agent file had no
marker-format guidance at all; this closes that gap.

Also adds a BLOCKING rule (#8) at the end of the Rules list pointing
back to the new section so the format requirement is visible from
the quick-scan list.

Closes #62

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
osama-abu-baker pushed a commit to osama-abu-baker/apexyard that referenced this pull request Jun 3, 2026
…sh#8)

* refactor(me2resh#100): multi-project only + fork-first install

Two strategic direction changes from the CEO rolled into one PR
because they're deeply coupled — removing single-project mode
changes the install flow, and the fork-first install changes
every doc that talked about cloning into .apexstack/.

1. Drop single-project mode entirely
---------------------------------------
Single-project mode was a dual-mode compromise that added
complexity without matching how apexstack is actually used.
The audit found every skill had a mode branch that was never
exercised in practice. Users who thought they only had one repo
almost always ended up with two within a few months.

- onboarding.yaml: removed the apexstack.mode field + the
  multi-paragraph mode explainer
- apexstack.projects.yaml.example: rewritten header comment to
  lead with "no single-project fallback mode; register your one
  repo and the skills work the same"
- CLAUDE.md: OPERATING MODE section replaced with PORTFOLIO MODEL
  section explaining the fork-as-ops-repo mental model. SETUP
  section dropped the "read apexstack.mode" step.
- docs/multi-project.md: full rewrite as the canonical setup
  guide. Removed the TL;DR comparison table, the "when to switch
  to single-project" section, the "migrating from single → multi"
  section, the "going back: multi → single" section, and every
  trade-off framed against single-project.
- 8 skill files (handover, idea, inbox, projects, roadmap,
  stakeholder-update, status, tasks): dropped every mode detection
  block (grep onboarding.yaml for mode:), dropped every
  mode-comparison table, simplified scope statements to "iterates
  the registry" or equivalent. Dead code removed.
- workspace/README.md, projects/README.md: removed the "two
  modes" sections, simplified to describe the single portfolio
  pattern.
- README.md: removed the Operating modes table + the
  Single-project install (opt-out) section + the Global install
  (alternative) section (see item 2 for why the global install
  is gone).
- site/index.html: removed the "Operating modes (single &
  multi-project)" hero metric, updated the layers section lede,
  removed every single-project mention in Layer 05, removed the
  "opt-out — single-project mode" install step, removed the
  "alternative — global install" install step.

The only remaining "single-project" strings in the codebase are
TWO intentional negation disclaimers (in docs/multi-project.md
and site/index.html Layer 05) that tell anyone searching for the
concept: "there is no single-project fallback". That's a feature,
not a bug.

2. Fork-first install (replaces clone-into-.apexstack/)
--------------------------------------------------------
The old install model cloned apexstack into a hidden .apexstack/
subdirectory of a separate ops repo, then symlinked .claude/ up
one level. Three problems:

  a. Brand invisibility — .apexstack/ is a dotfile, hidden from
     ls and GitHub views. Nobody knew you were using apexstack.
  b. Two repos to maintain — your ops repo plus the nested clone.
  c. Symlink fragility — the .claude/ symlink broke on dotfile
     sync tools and Windows setups.

New model: your ops repo IS a fork of apexstack. One repo, no
nesting, no symlinks. Upgrades flow via `git fetch upstream &&
git merge upstream/main` — the standard fork workflow.

Per the CEO's call, users can rename the fork to your-org/ops
or keep it as your-org/apexstack. GitHub handles the rename
cleanly. The install docs describe the rename as optional.

- Hero install block: "git clone ... .apexstack" →
  "gh repo fork me2resh/apexstack --clone"
- Hero CTA: "★ Star on GitHub" →
  "★ Star · ⑂ Fork on GitHub" (single button, per Q3.c)
- Hero install caveat: rewrote to explain "the fork IS your ops
  repo, no nested installs, no symlinks"
- SECTION 05 / INSTALL: full rewrite. 6 steps became 5. The 5
  steps are: star+fork, add upstream remote, configure
  onboarding.yaml, create the registry, start working. The old
  "symlink runnable layer" step is gone (no symlink needed). The
  old "wire CLAUDE.md with @-import" step is gone (CLAUDE.md is
  already at the fork root).
- README.md Quick Start: same 5-step rewrite, matched to the
  site flow.
- docs/multi-project.md: complete rewrite as a setup guide
  covering the fork flow, directory layout, daily workflow,
  upgrade path (git pull upstream), trade-offs, and FAQ. ~314
  lines, honest about the pros and cons.

Side effects (positive)
-----------------------
- Layers section UX bug from the earlier screenshot is gone.
  Layer 05 no longer has "content only fills left 1/3" — added a
  new .layer--wide CSS variant with a 2-column internal grid
  (description on the left, registry file list on the right).
  Fills the full width naturally.
- Hero metric me2resh#4 changed from "2 Operating modes" to "1 Fork ·
  your ops repo in one command" — celebrates the simplification
  instead of the dropped complexity.

Not in scope
------------
- The lifecycle demo script in the hero is untouched
  (it doesn't reference install or mode)
- Role files in roles/ are untouched (no mode refs)
- Workflow files (sdlc, code-review, deployment) are untouched
  (no mode refs)
- .claude/agents/ are untouched (no mode refs)
- Hooks in .claude/hooks/ are untouched (no mode refs)
- The apexstack.mode field in the existing onboarding.yaml.example
  — this is the site's own onboarding.yaml which gets removed
  with the mode config

Verification
------------
  grep -rn "single-project" --include="*.md" --include="*.yaml" \
    --include="*.html" --include="*.sh"
  → 2 hits, both intentional negation disclaimers

  grep -rn "mode:" --include="*.md" --include="*.yaml" \
    --include="*.html"
  → 0 hits

  grep -rn "\.apexstack/" --include="*.md" --include="*.yaml" \
    --include="*.html"
  → only in docs/multi-project.md explaining why the old pattern
    was dropped (historical context paragraph)

Multi-project neutrality
------------------------
  grep -iE "flat-?mate|curios|sharp ?pick|movetwo|yumyum" \
    on all 16 changed files
  → 0 hits

Refs me2resh/apexscript-org#100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(me2resh#100): address Rex review — blockers + CTA contradiction + doc fork

Rex's delta review on a44b706 found 4 blockers + 1 site CTA
contradiction + a few vestigial mentions. Plus the deeper grep
I ran caught two more: a stale .apexstack/ example in
golden-paths/pipelines/README.md, and docs/getting-started.md
still documenting the old .apexstack/ + symlink flow.

Blockers fixed
--------------
- B1: idea/SKILL.md rule 5 "Mode-aware — detect apexstack.mode"
      → "Single backlog — every idea goes into
         projects/ideas-backlog.md"
- B2: roadmap/SKILL.md rule 6 "Mode-aware — ROADMAP.md or
      projects/<name>/roadmap.md"
      → "One roadmap per project — always write to
         projects/<name>/roadmap.md"
- B3: status/SKILL.md had a "## Multi-project mode" section and
      a "Single-project mode default:" output format header.
      Renamed to "## Portfolio output" and "## Output format
      (one-project view with --project <name>)". No behaviour
      change — just language that doesn't frame /status as
      mode-switching.

Non-blocking suggestions fixed
------------------------------
- S1 (site CTA contradiction): index.html:1732 final CTA was
      "one git clone, one symlink, and one config file away"
      → "one fork, one clone, and one config file away". The
      old line directly contradicted the "no symlinks" story.
- S3 (CLAUDE.md QUICK REFERENCE):
  - "Project registry (multi-project)" → "Portfolio registry"
  - "Per-project docs (multi-project)" → "Per-project docs"
  - "Live working copies (multi-project)" → "Live working
    copies (gitignored)"
  - "Multi-project guide" → "Full setup guide"

Also cleaned up while I was in there
------------------------------------
- inbox/SKILL.md rule 3: "Multi-project mode iterates the
  registry" → "Registry-scoped — only projects listed in
  apexstack.projects.yaml count"
- projects/SKILL.md error row: "Multi-project mode but no
  apexstack.projects.yaml" → "No apexstack.projects.yaml at
  the ops-repo root"
- projects/README.md directory layout: "ideas-backlog.md
  (multi-project mode)" → just "shared ideas backlog"

Out-of-scope but too tangled to leave
-------------------------------------
- golden-paths/pipelines/README.md: `cp` examples pointed at
  `.apexstack/golden-paths/...` as if apexstack were still a
  nested clone. Rewrote to "copy from ~/apexstack (your fork)
  to your managed project's .github/workflows/". Not strictly
  within the mode-removal scope but the README is now
  self-consistent with the fork-first install.
- docs/getting-started.md: rewrote Step 1 and Step 3 to match
  the new fork flow. Was still documenting the old .apexstack/
  + submodule + @.apexstack/CLAUDE.md @-import pattern —
  guaranteed to confuse a new adopter. Keeps parity with
  docs/multi-project.md and the site install section.

Verification
------------
  grep -rin "single-project" --include="*.md" --include="*.yaml" \
    --include="*.html"
  → 2 hits, both intentional negation disclaimers in
    docs/multi-project.md:5 and site/index.html:1367

  grep -rn "apexstack.mode\|mode: multi-project\|mode: single-project\|Mode-aware" \
    --include="*.md" --include="*.yaml" --include="*.html"
  → 0 hits

  grep -rn "\.apexstack/" --include="*.md" --include="*.html"
  → only in docs/multi-project.md historical context paragraph
    (explaining why the old pattern was dropped) and README.md
    negation disclaimer ("no .apexstack/ symlinks")

Refs me2resh/apexscript-org#100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
osama-abu-baker pushed a commit to osama-abu-baker/apexyard that referenced this pull request Jun 3, 2026
…d gaps) (me2resh#9)

Closes the last sub-task of the apexstack positioning epic (me2resh#100).
The Explore agent audit flagged specific gaps in both skills; these
were deferred through PRs me2resh#4-me2resh#8 because they're independent of the
positioning work. Now fixed.

/handover — 3 gaps closed
-------------------------

1. **Auto-append to the portfolio registry** (was the CRITICAL gap
   from the audit). Previously the skill printed a YAML snippet
   and told the user "add this to apexstack.projects.yaml". Users
   forgot, or miscopied, or broke the YAML indentation.

   Fix: new step 6 prompts the user `Ready to add {name} to
   apexstack.projects.yaml? (y/n)`. On y, the skill:
   - Locates the registry at the ops-repo root (creates from
     .example if missing, with a warning)
   - Appends the entry via `yq` if available, otherwise plain-text
     append with careful indentation
   - Validates the result by parsing the YAML (yq or python yaml)
   - Rolls back on failure (never leaves the registry broken)
   - Confirms the append to the user with the derived roles list

   On n, prints the snippet for manual copy-paste and continues
   without writing.

2. **Dynamic "Next Steps"** derived from the risks found. The
   old template had generic placeholders like `{first concrete
   action — usually "run /audit-deps and triage criticals"}`
   which was embarrassing to ship.

   New behaviour: a mapping table in the skill spec defines the
   derivation. Examples:
   - CVEs detected → `/audit-deps {name} — triage the {severity}
     {package} CVE before any new feature work`
   - Failing tests → `Fix the {N} failing tests in {module}
     before merging new PRs`
   - No observability → `/decide on observability ({top 2 options
     for this stack})`
   - Stale CI → `Re-enable CI — copy in golden-paths/pipelines/ci.yml`
   - Coverage unknown → `Set up test coverage reporting`
   - Backlog > 10 → `Triage the issue backlog with previous owner`
   - Missing README → `Write a minimum-viable README`

3. **Post-handover checklist** added to the assessment template,
   also dynamically tailored to the risks found. Items like "close
   {top risk} before the first feature PR", "add {name} to weekly
   /stakeholder-update rollup", "set up a coverage baseline".

Bonus gap closed: **derive the role list dynamically** from the
tech stack + CI config + security surface, instead of hard-coding
`[tech-lead, backend-engineer]`. Mapping table in the spec:
- backend deps → backend-engineer
- UI code → frontend-engineer
- CI config → platform-engineer
- deployment evidence → sre
- auth/crypto/secrets → security-auditor
- always → tech-lead

A typical handover ends up with 3-5 roles in the registry entry.

/idea — 3 gaps closed + 1 numbering bug fixed
----------------------------------------------

1. **Input validation for category**. The old step 2 asked for
   category but silently accepted anything. A user who typed
   `foo` got `Category: foo` in the backlog.

   Fix: the prompt now explicitly lists 1/2/3/4, accepts either
   the number or the word (case-insensitive), and **re-prompts
   on invalid input** with `Please pick 1-4 or type the category
   name.` Loops until valid.

   Same treatment for the description field — re-prompt if empty.

2. **Dedup check before appending** (new step 3). Prevents
   submitting the same idea twice.

   Implementation: a simple token-overlap heuristic. Normalise
   both titles (lowercase, strip punctuation), compare with a
   threshold (≥ 80% of the words in the shorter title appear in
   the longer one).

   If a match is found:

     ⚠ Similar idea already in the backlog:
       IDEA-025 — {existing title} (status: {status})

     Is this a duplicate? (y = skip, n = add anyway)

   On y: skip the append, suggest `/write-spec IDEA-025` if the
   user wants to work on the existing idea. On n: continue to
   step 4.

3. **Error handling for `gh issue create`** in step 6. Old
   behaviour: if the tracking issue creation failed, the idea
   was half-saved or the whole thing errored out. New behaviour:

     ⚠ Couldn't create the tracking issue: {reason}
       The idea is still saved in projects/ideas-backlog.md
       as IDEA-NNN.

     Try again? (y = retry, n = skip, gh = show the gh error)

   With a failure-modes table: missing auth scope, label not
   found, rate limit, network error, etc. — each has a specific
   recovery path.

   Guiding principle (now rule me2resh#8): **the backlog entry is the
   primary artefact; the tracking issue is a bonus**. Never lose
   the backlog entry because GitHub was flaky.

4. **Section numbering bug** fixed. The old file had steps 1, 2,
   4, 5, 6 — step 3 was missing because an earlier refactor
   deleted it without renumbering. With the new step 3 (dedup
   check) the sequence is now 1, 2, 3, 4, 5, 6 again.

Rules sections updated for both skills
--------------------------------------

- /handover: rule 4 is now "Auto-append to the registry (with
  confirmation)"; rule 5 is "Derive roles from the stack"; rule
  6 is "Derive next steps from the risks"; rule 10 is "Never
  break the registry".
- /idea: rule 6 is "Validate before accepting"; rule 7 is
  "Dedup before appending"; rule 8 is "The backlog is the
  primary artefact".

What's NOT in this commit
-------------------------

- The tabbed terminal animation (me2resh#102) — separate ticket,
  not part of the epic closure
- Any changes to the skill frontmatter
- Any changes to the `/handover` assessment output format
  beyond the Next Steps and Post-Handover Checklist sections
- Any changes to `/idea`'s backlog file format or ID scheme

This closes the epic me2resh#100. After this merges, apexstack is at
its v0.2 shape: positioning rewritten, lifecycle demo in the
hero, 19 roles wired in, multi-project-only + fork-first install,
and now the /handover and /idea skills that actually work
end-to-end.

Closes me2resh/apexscript-org#101
Closes me2resh/apexscript-org#100

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
osama-abu-baker pushed a commit to osama-abu-baker/apexyard that referenced this pull request Jun 3, 2026
… SHA (me2resh#66)

Adds an explicit "Approval marker — EXACT FORMAT REQUIRED" section
to .claude/agents/code-reviewer.md with:

- The canonical write command (three allowed shapes: git rev-parse,
  gh pr view --json headRefOid, printf '%s\n' "$SHA")
- CORRECT vs WRONG visual examples covering the four malformed
  shapes actually observed in the wild:
    - "PR: N\nSHA: …" labelled multi-line
    - JSON object
    - SHA with trailing timestamp
    - "APPROVED at <SHA>" prose prefix
- Explicit "don't write the marker on non-approved verdicts" rule
- Explicit "report and abort, don't fake completion" rule for sandbox
  failures
- Reference to the hook that validates (block-unreviewed-merge.sh)
  and the rule that forbids hand-editing (pr-workflow.md)

Motivation: on 2026-04-17 (apexstack PR me2resh#61) the agent wrote
`PR: 61\nSHA: 2933a06…` instead of the bare SHA, the hook rejected
it, and the workaround required hand-editing — a rule violation per
pr-workflow.md § "Mechanical enforcement". Agent file had no
marker-format guidance at all; this closes that gap.

Also adds a BLOCKING rule (me2resh#8) at the end of the Rules list pointing
back to the new section so the format requirement is visible from
the quick-scan list.

Closes me2resh#62

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
mosta7il pushed a commit to mosta7il/apexyard that referenced this pull request Jun 8, 2026
…sh#8)

* refactor(me2resh#100): multi-project only + fork-first install

Two strategic direction changes from the CEO rolled into one PR
because they're deeply coupled — removing single-project mode
changes the install flow, and the fork-first install changes
every doc that talked about cloning into .apexstack/.

1. Drop single-project mode entirely
---------------------------------------
Single-project mode was a dual-mode compromise that added
complexity without matching how apexstack is actually used.
The audit found every skill had a mode branch that was never
exercised in practice. Users who thought they only had one repo
almost always ended up with two within a few months.

- onboarding.yaml: removed the apexstack.mode field + the
  multi-paragraph mode explainer
- apexstack.projects.yaml.example: rewritten header comment to
  lead with "no single-project fallback mode; register your one
  repo and the skills work the same"
- CLAUDE.md: OPERATING MODE section replaced with PORTFOLIO MODEL
  section explaining the fork-as-ops-repo mental model. SETUP
  section dropped the "read apexstack.mode" step.
- docs/multi-project.md: full rewrite as the canonical setup
  guide. Removed the TL;DR comparison table, the "when to switch
  to single-project" section, the "migrating from single → multi"
  section, the "going back: multi → single" section, and every
  trade-off framed against single-project.
- 8 skill files (handover, idea, inbox, projects, roadmap,
  stakeholder-update, status, tasks): dropped every mode detection
  block (grep onboarding.yaml for mode:), dropped every
  mode-comparison table, simplified scope statements to "iterates
  the registry" or equivalent. Dead code removed.
- workspace/README.md, projects/README.md: removed the "two
  modes" sections, simplified to describe the single portfolio
  pattern.
- README.md: removed the Operating modes table + the
  Single-project install (opt-out) section + the Global install
  (alternative) section (see item 2 for why the global install
  is gone).
- site/index.html: removed the "Operating modes (single &
  multi-project)" hero metric, updated the layers section lede,
  removed every single-project mention in Layer 05, removed the
  "opt-out — single-project mode" install step, removed the
  "alternative — global install" install step.

The only remaining "single-project" strings in the codebase are
TWO intentional negation disclaimers (in docs/multi-project.md
and site/index.html Layer 05) that tell anyone searching for the
concept: "there is no single-project fallback". That's a feature,
not a bug.

2. Fork-first install (replaces clone-into-.apexstack/)
--------------------------------------------------------
The old install model cloned apexstack into a hidden .apexstack/
subdirectory of a separate ops repo, then symlinked .claude/ up
one level. Three problems:

  a. Brand invisibility — .apexstack/ is a dotfile, hidden from
     ls and GitHub views. Nobody knew you were using apexstack.
  b. Two repos to maintain — your ops repo plus the nested clone.
  c. Symlink fragility — the .claude/ symlink broke on dotfile
     sync tools and Windows setups.

New model: your ops repo IS a fork of apexstack. One repo, no
nesting, no symlinks. Upgrades flow via `git fetch upstream &&
git merge upstream/main` — the standard fork workflow.

Per the CEO's call, users can rename the fork to your-org/ops
or keep it as your-org/apexstack. GitHub handles the rename
cleanly. The install docs describe the rename as optional.

- Hero install block: "git clone ... .apexstack" →
  "gh repo fork me2resh/apexstack --clone"
- Hero CTA: "★ Star on GitHub" →
  "★ Star · ⑂ Fork on GitHub" (single button, per Q3.c)
- Hero install caveat: rewrote to explain "the fork IS your ops
  repo, no nested installs, no symlinks"
- SECTION 05 / INSTALL: full rewrite. 6 steps became 5. The 5
  steps are: star+fork, add upstream remote, configure
  onboarding.yaml, create the registry, start working. The old
  "symlink runnable layer" step is gone (no symlink needed). The
  old "wire CLAUDE.md with @-import" step is gone (CLAUDE.md is
  already at the fork root).
- README.md Quick Start: same 5-step rewrite, matched to the
  site flow.
- docs/multi-project.md: complete rewrite as a setup guide
  covering the fork flow, directory layout, daily workflow,
  upgrade path (git pull upstream), trade-offs, and FAQ. ~314
  lines, honest about the pros and cons.

Side effects (positive)
-----------------------
- Layers section UX bug from the earlier screenshot is gone.
  Layer 05 no longer has "content only fills left 1/3" — added a
  new .layer--wide CSS variant with a 2-column internal grid
  (description on the left, registry file list on the right).
  Fills the full width naturally.
- Hero metric me2resh#4 changed from "2 Operating modes" to "1 Fork ·
  your ops repo in one command" — celebrates the simplification
  instead of the dropped complexity.

Not in scope
------------
- The lifecycle demo script in the hero is untouched
  (it doesn't reference install or mode)
- Role files in roles/ are untouched (no mode refs)
- Workflow files (sdlc, code-review, deployment) are untouched
  (no mode refs)
- .claude/agents/ are untouched (no mode refs)
- Hooks in .claude/hooks/ are untouched (no mode refs)
- The apexstack.mode field in the existing onboarding.yaml.example
  — this is the site's own onboarding.yaml which gets removed
  with the mode config

Verification
------------
  grep -rn "single-project" --include="*.md" --include="*.yaml" \
    --include="*.html" --include="*.sh"
  → 2 hits, both intentional negation disclaimers

  grep -rn "mode:" --include="*.md" --include="*.yaml" \
    --include="*.html"
  → 0 hits

  grep -rn "\.apexstack/" --include="*.md" --include="*.yaml" \
    --include="*.html"
  → only in docs/multi-project.md explaining why the old pattern
    was dropped (historical context paragraph)

Multi-project neutrality
------------------------
  grep -iE "flat-?mate|curios|sharp ?pick|movetwo|yumyum" \
    on all 16 changed files
  → 0 hits

Refs me2resh/apexscript-org#100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(me2resh#100): address Rex review — blockers + CTA contradiction + doc fork

Rex's delta review on 160148f found 4 blockers + 1 site CTA
contradiction + a few vestigial mentions. Plus the deeper grep
I ran caught two more: a stale .apexstack/ example in
golden-paths/pipelines/README.md, and docs/getting-started.md
still documenting the old .apexstack/ + symlink flow.

Blockers fixed
--------------
- B1: idea/SKILL.md rule 5 "Mode-aware — detect apexstack.mode"
      → "Single backlog — every idea goes into
         projects/ideas-backlog.md"
- B2: roadmap/SKILL.md rule 6 "Mode-aware — ROADMAP.md or
      projects/<name>/roadmap.md"
      → "One roadmap per project — always write to
         projects/<name>/roadmap.md"
- B3: status/SKILL.md had a "## Multi-project mode" section and
      a "Single-project mode default:" output format header.
      Renamed to "## Portfolio output" and "## Output format
      (one-project view with --project <name>)". No behaviour
      change — just language that doesn't frame /status as
      mode-switching.

Non-blocking suggestions fixed
------------------------------
- S1 (site CTA contradiction): index.html:1732 final CTA was
      "one git clone, one symlink, and one config file away"
      → "one fork, one clone, and one config file away". The
      old line directly contradicted the "no symlinks" story.
- S3 (CLAUDE.md QUICK REFERENCE):
  - "Project registry (multi-project)" → "Portfolio registry"
  - "Per-project docs (multi-project)" → "Per-project docs"
  - "Live working copies (multi-project)" → "Live working
    copies (gitignored)"
  - "Multi-project guide" → "Full setup guide"

Also cleaned up while I was in there
------------------------------------
- inbox/SKILL.md rule 3: "Multi-project mode iterates the
  registry" → "Registry-scoped — only projects listed in
  apexstack.projects.yaml count"
- projects/SKILL.md error row: "Multi-project mode but no
  apexstack.projects.yaml" → "No apexstack.projects.yaml at
  the ops-repo root"
- projects/README.md directory layout: "ideas-backlog.md
  (multi-project mode)" → just "shared ideas backlog"

Out-of-scope but too tangled to leave
-------------------------------------
- golden-paths/pipelines/README.md: `cp` examples pointed at
  `.apexstack/golden-paths/...` as if apexstack were still a
  nested clone. Rewrote to "copy from ~/apexstack (your fork)
  to your managed project's .github/workflows/". Not strictly
  within the mode-removal scope but the README is now
  self-consistent with the fork-first install.
- docs/getting-started.md: rewrote Step 1 and Step 3 to match
  the new fork flow. Was still documenting the old .apexstack/
  + submodule + @.apexstack/CLAUDE.md @-import pattern —
  guaranteed to confuse a new adopter. Keeps parity with
  docs/multi-project.md and the site install section.

Verification
------------
  grep -rin "single-project" --include="*.md" --include="*.yaml" \
    --include="*.html"
  → 2 hits, both intentional negation disclaimers in
    docs/multi-project.md:5 and site/index.html:1367

  grep -rn "apexstack.mode\|mode: multi-project\|mode: single-project\|Mode-aware" \
    --include="*.md" --include="*.yaml" --include="*.html"
  → 0 hits

  grep -rn "\.apexstack/" --include="*.md" --include="*.html"
  → only in docs/multi-project.md historical context paragraph
    (explaining why the old pattern was dropped) and README.md
    negation disclaimer ("no .apexstack/ symlinks")

Refs me2resh/apexscript-org#100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
mosta7il pushed a commit to mosta7il/apexyard that referenced this pull request Jun 8, 2026
…d gaps) (me2resh#9)

Closes the last sub-task of the apexstack positioning epic (me2resh#100).
The Explore agent audit flagged specific gaps in both skills; these
were deferred through PRs me2resh#4-me2resh#8 because they're independent of the
positioning work. Now fixed.

/handover — 3 gaps closed
-------------------------

1. **Auto-append to the portfolio registry** (was the CRITICAL gap
   from the audit). Previously the skill printed a YAML snippet
   and told the user "add this to apexstack.projects.yaml". Users
   forgot, or miscopied, or broke the YAML indentation.

   Fix: new step 6 prompts the user `Ready to add {name} to
   apexstack.projects.yaml? (y/n)`. On y, the skill:
   - Locates the registry at the ops-repo root (creates from
     .example if missing, with a warning)
   - Appends the entry via `yq` if available, otherwise plain-text
     append with careful indentation
   - Validates the result by parsing the YAML (yq or python yaml)
   - Rolls back on failure (never leaves the registry broken)
   - Confirms the append to the user with the derived roles list

   On n, prints the snippet for manual copy-paste and continues
   without writing.

2. **Dynamic "Next Steps"** derived from the risks found. The
   old template had generic placeholders like `{first concrete
   action — usually "run /audit-deps and triage criticals"}`
   which was embarrassing to ship.

   New behaviour: a mapping table in the skill spec defines the
   derivation. Examples:
   - CVEs detected → `/audit-deps {name} — triage the {severity}
     {package} CVE before any new feature work`
   - Failing tests → `Fix the {N} failing tests in {module}
     before merging new PRs`
   - No observability → `/decide on observability ({top 2 options
     for this stack})`
   - Stale CI → `Re-enable CI — copy in golden-paths/pipelines/ci.yml`
   - Coverage unknown → `Set up test coverage reporting`
   - Backlog > 10 → `Triage the issue backlog with previous owner`
   - Missing README → `Write a minimum-viable README`

3. **Post-handover checklist** added to the assessment template,
   also dynamically tailored to the risks found. Items like "close
   {top risk} before the first feature PR", "add {name} to weekly
   /stakeholder-update rollup", "set up a coverage baseline".

Bonus gap closed: **derive the role list dynamically** from the
tech stack + CI config + security surface, instead of hard-coding
`[tech-lead, backend-engineer]`. Mapping table in the spec:
- backend deps → backend-engineer
- UI code → frontend-engineer
- CI config → platform-engineer
- deployment evidence → sre
- auth/crypto/secrets → security-auditor
- always → tech-lead

A typical handover ends up with 3-5 roles in the registry entry.

/idea — 3 gaps closed + 1 numbering bug fixed
----------------------------------------------

1. **Input validation for category**. The old step 2 asked for
   category but silently accepted anything. A user who typed
   `foo` got `Category: foo` in the backlog.

   Fix: the prompt now explicitly lists 1/2/3/4, accepts either
   the number or the word (case-insensitive), and **re-prompts
   on invalid input** with `Please pick 1-4 or type the category
   name.` Loops until valid.

   Same treatment for the description field — re-prompt if empty.

2. **Dedup check before appending** (new step 3). Prevents
   submitting the same idea twice.

   Implementation: a simple token-overlap heuristic. Normalise
   both titles (lowercase, strip punctuation), compare with a
   threshold (≥ 80% of the words in the shorter title appear in
   the longer one).

   If a match is found:

     ⚠ Similar idea already in the backlog:
       IDEA-025 — {existing title} (status: {status})

     Is this a duplicate? (y = skip, n = add anyway)

   On y: skip the append, suggest `/write-spec IDEA-025` if the
   user wants to work on the existing idea. On n: continue to
   step 4.

3. **Error handling for `gh issue create`** in step 6. Old
   behaviour: if the tracking issue creation failed, the idea
   was half-saved or the whole thing errored out. New behaviour:

     ⚠ Couldn't create the tracking issue: {reason}
       The idea is still saved in projects/ideas-backlog.md
       as IDEA-NNN.

     Try again? (y = retry, n = skip, gh = show the gh error)

   With a failure-modes table: missing auth scope, label not
   found, rate limit, network error, etc. — each has a specific
   recovery path.

   Guiding principle (now rule me2resh#8): **the backlog entry is the
   primary artefact; the tracking issue is a bonus**. Never lose
   the backlog entry because GitHub was flaky.

4. **Section numbering bug** fixed. The old file had steps 1, 2,
   4, 5, 6 — step 3 was missing because an earlier refactor
   deleted it without renumbering. With the new step 3 (dedup
   check) the sequence is now 1, 2, 3, 4, 5, 6 again.

Rules sections updated for both skills
--------------------------------------

- /handover: rule 4 is now "Auto-append to the registry (with
  confirmation)"; rule 5 is "Derive roles from the stack"; rule
  6 is "Derive next steps from the risks"; rule 10 is "Never
  break the registry".
- /idea: rule 6 is "Validate before accepting"; rule 7 is
  "Dedup before appending"; rule 8 is "The backlog is the
  primary artefact".

What's NOT in this commit
-------------------------

- The tabbed terminal animation (me2resh#102) — separate ticket,
  not part of the epic closure
- Any changes to the skill frontmatter
- Any changes to the `/handover` assessment output format
  beyond the Next Steps and Post-Handover Checklist sections
- Any changes to `/idea`'s backlog file format or ID scheme

This closes the epic me2resh#100. After this merges, apexstack is at
its v0.2 shape: positioning rewritten, lifecycle demo in the
hero, 19 roles wired in, multi-project-only + fork-first install,
and now the /handover and /idea skills that actually work
end-to-end.

Closes me2resh/apexscript-org#101
Closes me2resh/apexscript-org#100

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
mosta7il pushed a commit to mosta7il/apexyard that referenced this pull request Jun 8, 2026
… SHA (me2resh#66)

Adds an explicit "Approval marker — EXACT FORMAT REQUIRED" section
to .claude/agents/code-reviewer.md with:

- The canonical write command (three allowed shapes: git rev-parse,
  gh pr view --json headRefOid, printf '%s\n' "$SHA")
- CORRECT vs WRONG visual examples covering the four malformed
  shapes actually observed in the wild:
    - "PR: N\nSHA: …" labelled multi-line
    - JSON object
    - SHA with trailing timestamp
    - "APPROVED at <SHA>" prose prefix
- Explicit "don't write the marker on non-approved verdicts" rule
- Explicit "report and abort, don't fake completion" rule for sandbox
  failures
- Reference to the hook that validates (block-unreviewed-merge.sh)
  and the rule that forbids hand-editing (pr-workflow.md)

Motivation: on 2026-04-17 (apexstack PR me2resh#61) the agent wrote
`PR: 61\nSHA: d46ff2c…` instead of the bare SHA, the hook rejected
it, and the workaround required hand-editing — a rule violation per
pr-workflow.md § "Mechanical enforcement". Agent file had no
marker-format guidance at all; this closes that gap.

Also adds a BLOCKING rule (me2resh#8) at the end of the Rules list pointing
back to the new section so the format requirement is visible from
the quick-scan list.

Closes me2resh#62

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
atlas-apex added a commit that referenced this pull request Jun 11, 2026
The email-obfuscation snippet built a mailto: href from the data-u/data-d DOM
attributes without escaping, which CodeQL flags as js/xss-through-dom (#8).
Wrap the local-part and domain in encodeURIComponent so meta-characters are
escaped before reaching the href sink. Real-world risk was low (author-controlled
attributes; mailto: prefix precludes javascript:), but this clears the alert and
is a no-op for normal addresses.

Closes #638

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
alalm3i added a commit to alalm3i/apexyard that referenced this pull request Jun 13, 2026
* fix(#99): align default-mode framing, roles count, file count, SENTINEL nit (#3)

Post-merge cleanup after the Rex re-review of PR #1. Four blockers
and one nit — all small, all correctness fixes, no scope creep.

N1 — Default-mode contradiction (CRITICAL)
Four files claimed single-project was the default, contradicting
CLAUDE.md, README, onboarding.yaml, docs/multi-project.md, the site,
and 7 of 8 new skills (which all say multi-project is the default).
The commit message for ba892bc literally said "multi-project mode
(default)". These four were the stragglers; they now align:

- apexstack.projects.yaml.example: header comment rewritten to say
  this file is the registry for the default multi-project mode,
  single-project is the opt-in
- workspace/README.md: section order swapped (multi-project first as
  the default, single-project second as opt-in), intro paragraph
  reworded, mode comments in the onboarding.yaml snippet flipped
- projects/README.md: opening paragraph flipped so multi-project is
  described as the default
- .claude/skills/projects/SKILL.md: mode detection table row order
  flipped (multi-project "or missing" is now default), sections
  swapped so multi-project comes first as the default, single-project
  moved below as opt-in, the "how to flip back" prompt reworded

N2 — Roles count
- README.md:166 — "20 software development roles" → "19"
  (actual count: 7 Engineering + 3 Product + 3 Design + 3 Security
  + 3 Data = 19)

N3 — Site file count
- site/index.html:956 — dropped the "79 files · " prefix from the
  tree header line to kill the drift-prone number entirely. The
  descriptive tagline "the runnable + portfolio layers added in v0.1"
  stays. Any time a file is added to the repo, the header no longer
  lies.

Stale SENTINEL comment
- golden-paths/pipelines/ci.yml:93 — the security section comment
  said "SENTINEL — Security Scanning" but the job itself is named
  "Shield: Security" (the Sentinel→Shield rename from PR #1). Fixed
  the comment to match.

What's NOT in this commit
- N4 (PR body "5 skills" + Sentinel/Scout in glossary) — GitHub PR
  bodies are immutable after merge, so this is recorded in the
  tracking issue as NOT FIXABLE.
- Retroactive AgDRs — intentionally skipped per the CEO's call
  (v0.1 doesn't need them backfilled).

Verification
  grep -n "20 software development roles" README.md     → no hits
  grep -n "79 files" site/index.html                    → no hits
  grep -n "SENTINEL" golden-paths/pipelines/ci.yml      → no hits
  grep for "single-project is the default" in the 4 N1 files → no hits

Closes me2resh/apexscript-org#99

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs(#100): positioning rewrite — "where projects get forged" (#4)

* docs(#100): positioning rewrite — "where projects get forged"

Reframes apexstack from "an opinionated stack for Claude Code" to
"a multi-project ops repo where projects get forged." Targets the
solo founder / technical CEO running 2-5 products and drowning in
context-switching.

Hero (site/index.html)
- Eyebrow flips from "plain markdown · zero dependencies" to
  "for founders forging multiple products"
- H1 changes from the brand name ("apexstack") to the value
  prop ("Where projects get forged.")
- New tagline: "The multi-project ops repo where your projects
  reference each other, learn from shared experience, and ship
  production-ready under a strict SDLC."
- New subhead leans into the forge framing: "You don't add
  apexstack to a project — projects get forged inside it. One
  ops repo. Every product. Shared memory. Strict gates.
  Production-ready MVPs." Addresses the Claude-Code-lock-in
  objection head-on: "Claude Code is the default driver, but
  the rules, hooks, and templates are plain markdown and shell.
  Swap the AI. Keep the forge."
- NEW hero CTA block with star-first priority:
  [★ Star on GitHub] · [or install it now ↓]
- Install command fixed from `~/.apexstack` (home dir, broken
  per the audit) to `.apexstack` (per-ops-repo, canonical)
- Caveat rewritten to match and point at both install paths

CSS
- Added .hero__cta, .cta, .cta--primary, .cta--ghost, .cta__sep
  to the existing terminal-brutalism style block. Sharp corners,
  hairline borders, no gradients. Primary CTA goes from ink → accent
  on hover. Ghost CTA is text-only with accent on hover.

Install section (site/index.html SECTION 05)
- Kept the six-step per-ops-repo walkthrough as the canonical
  path
- Kept the single-project opt-out at the bottom
- NEW "alternative — global install" step for users running
  several ops repos (founders with multiple orgs, consultants
  with multiple clients). Documents the tradeoff: symlinks
  use absolute paths, breaks if ~/.apexstack/ moves.
- Hero caveat links to #install-global for the alternative

README.md
- Hero rewritten end-to-end to match the site
- Added "Global install (alternative)" section after the
  single-project opt-out, mirroring the new site step
- gstacks.org attribution reworded to say "for teams running
  more than one product at a time"

CLAUDE.md
- Intro title changed from "AI-Native Development Stack" to
  "A Multi-Project Forge for Claude Code"
- First paragraph expanded with the forge framing and the
  explicit "projects get forged inside it, not added to it"
  phrasing, while keeping the operational instructions
  untouched so the rest of the file still drives Claude
  correctly.

Audience discovery (recorded in the epic issue)
- Primary persona: solo founder / technical CEO juggling
  2-5 products
- Tone: punchy and confident, short sentences, strong verbs
- Forge metaphor: literal
- Conversion: star first, clone second
- Objections addressed: Claude-Code lock-in (explicit),
  opinionated (leaned into — "strict gates" is the point)

NOT in this PR (tracked in the epic)
- Commands sub-page (PR 2)
- Hero shell animation (PR 3, depends on PR 2)
- Roles integration (PR 4 — the audit flagged all 19 roles
  are completely disconnected from workflows/skills/CLAUDE.md
  imports, will fix there)
- /idea and /handover skill polish (PR 5)
- AgDR backfill — explicitly skipped
- Anvil / metalwork SVG iconography — holding off on visual
  changes until the copy is locked

Refs me2resh/apexscript-org#100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs(#100): fix page title, meta description, CTA separator, caveat copy

Address Rex's review on PR #4 commit a044bd2:

B1 (blocker) — Page title and meta description still said "an
opinionated stack for Claude Code" and "one drop-in stack for
Claude Code". These are the highest-leverage strings in the file
(browser tabs, search results, social cards) and they directly
contradicted the rest of the PR. Replaced with the forge framing:

  <title>ApexStack — where projects get forged</title>
  <meta description="... a multi-project ops repo where your
  projects reference each other, learn from shared experience,
  and ship production-ready under a strict SDLC. Built for
  founders running 2–5 products at once. Open source. Claude
  Code native, but plain markdown underneath.">

S2 (non-blocking) — On narrow screens where .hero__cta wraps,
the `·` separator could orphan onto its own line. Added
@media (max-width: 520px) { .cta__sep { display: none; } }
so the two CTAs stack cleanly on mobile.

S3 (non-blocking) — Hero caveat said "Five more steps in install
below" but the install section now has 6 per-ops-repo steps plus
the single-project opt-out and the new global-install alternative.
Rephrased to "Full walkthrough in install below" so the copy is
count-agnostic.

S1 (skipped) — Rex noted CLAUDE.md doesn't carry "Swap the AI.
Keep the forge." but also explicitly said the spec only required
the line in site + README, so leaving CLAUDE.md's operational
tone intact.

Refs me2resh/apexscript-org#100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs(#100): revert H1 to "apexstack_" with flicker, promote forge to tagline

CEO feedback on the live site at a044bd2:
- Missed the flickering "_" cursor on the old H1 — the three-word
  H1 ("Where projects get forged.") also overflowed the hero
  width because .hero__title has white-space: nowrap; overflow:
  hidden; and was clipping at ~"projects" on a standard laptop
- Forge statement belongs in the subheading, not the H1

Changes:
- H1 reverts to "apexstack" (was "Where projects get forged.").
  The .hero__title::after pseudo-element already appends a "_"
  and animates it via the blink keyframe, so the flicker comes
  back for free.
- Tagline becomes "Where projects get forged." — the forge
  statement now sits in the visually-prominent subheading slot
  right under the H1.
- .hero__tagline font-size bumped from clamp(1rem, 1.6vw, 1.25rem)
  to clamp(1.5rem, 3vw, 2.5rem) so a 4-word punchy statement
  carries visual weight. Also font-weight 500 → 600, line-height
  1.5 → 1.25, and a small negative letter-spacing for the
  display-style treatment.
- Sub paragraph absorbs the previous tagline content merged
  with the existing subhead — one longer descriptive paragraph
  covering the multi-project promise, the forge framing, and
  the Claude-Code lock-in objection.

Typography hierarchy is now:
- H1 (huge, monospace, with blinking cursor) — brand mark
- Tagline (display-size, punchy) — the one-line promise
- Sub (body-size, descriptive) — the multi-paragraph pitch

Refs me2resh/apexscript-org#100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(#100): animated /idea shell demo in the hero (#5)

PR 3 of the apexstack positioning epic. Adds an animated shell
window showing a real /idea invocation end-to-end, placed in the
hero between the CTA block and the install command so readers see
proof of what the stack feels like before they commit to cloning.

The user picked /idea (over /handover or the full ticket flow)
because it's relatable, lightweight, and demonstrates the multi-
project story: the demo creates IDEA-025, stores it in the shared
projects/ideas-backlog.md, and files a tracking issue against
your-org/example-app — all three surfaces the copy above promises.

Demo script (~11s, typewriter timing)
  $ /idea Usage-based pricing for creators
  Category? (1) New Product (2) Feature (3) Internal Tool (4) Process
  > 2
  Description? (one line)
  > Let creators tier paid access by usage instead of seat count
  Create GitHub Issue in your-org/example-app? (y/n)
  > y
  ✓ Captured: IDEA-025 — Usage-based pricing for creators
    Backlog:  projects/ideas-backlog.md
    Tracking: your-org/example-app#31
    Next:     triage, then /write-spec

Multi-project neutrality: no real project names leak — placeholder
is `your-org/example-app`, matching the `apexstack.projects.yaml.example`
registry convention the rest of the repo already uses.

Implementation
- New `.shell-demo` block in the hero (after `.hero__cta`, before
  `.install`), with a chrome bar (three brutalist dots, title,
  replay button) and a body that the JS drives
- Pre-rendered static HTML inside the body, so the demo is readable
  even with JS disabled or reduced motion
- CSS for the shell window, line types (cmd/sys/you/ok/muted),
  prompt coloring (accent for $, ink-faint for >), and replay
  button (hidden by default, revealed by JS)
- ~90 lines of JS (IIFE) in the existing end-of-body script tag:
  - Typewriter effect with variable delays per script entry
  - Per-char type speed + ±15ms jitter so it feels human
  - Clears and replays on replay-button click
  - Respects `prefers-reduced-motion`: if set, keeps the static
    pre-rendered content, hides the replay button, and exits
    without animating (no forced 10s wait for reduced-motion users)

No new dependencies. No bundler. Inline JS at the bottom of body,
runs after the DOM is parsed.

Placement rationale
- C1 = /idea (CEO picked in this thread)
- C2 = CSS + small JS (from the epic UX discovery)
- C3 = hero (from the epic UX discovery)
- Inserted between .hero__cta and .install so the funnel reads:
  pitch → CTA → proof → install → caveat → metrics

Accessibility
- `aria-label` on the shell-demo wrapper describes what it is
- `aria-hidden` on the decorative chrome dots
- Replay button has `aria-label`
- `prefers-reduced-motion` fully respected (no animation, no
  forced delay, no replay loop)
- Static pre-rendered content is a functional fallback — the
  demo is readable even with JS disabled

What's NOT in this PR (tracked in the epic #100)
- Commands sub-page (intentionally skipped per CEO call — we
  picked the animation target without needing the reference
  page first)
- Roles integration (PR 4 in the original plan)
- /handover and /idea skill polish (PR 5)

Refs me2resh/apexscript-org#100

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(#100): lifecycle demo + catchier /idea + Swift proof line (#6)

* feat(#100): lifecycle demo + catchier /idea content + Swift proof line

Bundles three related landing-page upgrades that the CEO asked for
in one review thread:

1. /idea demo content rewrite
   - Swapped the placeholder "Usage-based pricing for creators"
     idea for "Swift menu-bar app for photo library dedup" — a
     concrete, catchier idea that also surfaces the fact that
     apexstack has been used to ship native Swift macOS apps.
   - Category now 1 (New Product) instead of 2 (Feature), since
     it's a new app.
   - Tracking target changed from `your-org/example-app#31` to
     `your-org/ops#17` because a new-product idea doesn't belong
     in an existing app's issue tracker — it lives in the ops repo.
   - Both the pre-rendered static HTML and the JS script array
     are updated line-for-line.

2. New SECTION 00 / LIFECYCLE — full ticket lifecycle demo
   A second animated shell window placed directly below the hero,
   covering all 14 phases of the apexstack workflow end-to-end:

     /inbox → pick up #58 → Tech Lead planning → plan approval
     → Backend Engineer implementation → AgDR via /decide
     → local lint/types/tests/build → commit/push/PR → /code-review
     → Rex verdict → CEO 👍 → merge → PR→QA state transition
     → pipeline on main → QA Engineer verification on staging
     → Done

   Playback: scroll-triggered via IntersectionObserver (0.3
   threshold), plays ONCE when the section enters the viewport,
   never blocks page load. Replay button at top-right of the
   chrome. Respects prefers-reduced-motion by exiting early and
   keeping the static content in place.

   Fallback: if IntersectionObserver is unavailable, auto-plays
   after a 3s delay.

   Pre-rendered static HTML mirrors the animation line-for-line
   so the demo is readable with JS disabled.

   ASPIRATIONAL role lines flagged: "Tech Lead role active",
   "Backend Engineer role active", "QA Engineer role active" —
   roles are currently PASSIVE per the audit. PR 7 (renumbered
   roles integration) will wire the activation for real. The demo
   previews that future state.

3. Proven-stacks line + README bullet
   New small `<p class="hero__proof">` caption below the hero
   metrics:
     Proven shipping · TypeScript + AWS Lambda backends · Next.js
     web apps · Chrome extensions · native Swift macOS apps

   Uses the existing .kw accent-coloured span for the stack
   keywords so they pop without adding new CSS.

   README.md hero gains a matching bullet in the second paragraph
   calling out the four proven stack types — directly answers the
   CEO's "do we have this somewhere?" question. We did not. Now
   we do.

Also
- Titlebar nav: replaced #stack (dead anchor since PR 1 reshuffle)
  with #lifecycle pointing at the new section.
- .shell-demo--tall variant: reserves 52rem min-height on the body
  so the demo doesn't collapse while the JS rebuilds it line by
  line. Smaller font-size (12px vs 12.5px) so 50+ lines fit.
- .hero__proof: small caption style matching the existing
  ink-faint + .kw accent pattern.

The lifecycle demo's JS IIFE shares ~80 lines of helper code with
the /idea IIFE (typeInto, play loop, timeouts cleanup). Tolerated
for now as copy-paste because extracting a shared helper is a
separate refactor; both IIFEs remain self-contained and easy to
remove individually.

Multi-project neutrality verified
- grep -iE "flat-?mate|curios|sharp ?pick|movetwo|yumyum" site/index.html
  returns 0 hits. The Swift reference is via the generic phrase
  "Swift menu-bar app for photo library dedup" — no SharpPick name
  leak. Repo placeholders use your-org/{ops,billing-api} per the
  apexstack.projects.yaml.example convention.

Refs me2resh/apexscript-org#100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(#100): lifecycle demo scrolls like a terminal, not a full box

CEO feedback on the new animation in PR #6: "i like the new animation,
but yes too much on the page, doesn't have to be a full box displaying
everything, can be smaller like 10 lines and scrolling with new data
like terminal".

Changes
- .shell-demo--tall .shell-demo__body — fixed height 17rem (~10 lines
  at 1.55 line-height), overflow-y: auto, hidden scrollbars on both
  Firefox (scrollbar-width: none) and WebKit (::-webkit-scrollbar).
  Replaces the old min-height: 52rem that reserved the full 54-line
  height on the page.

- Added a soft top fade gradient via .shell-demo--tall::before that
  sits just under the chrome bar. Implies depth — content scrolled
  above the viewport fades out rather than hard-clipping. Uses
  --paper-2 → transparent so it flips correctly in dark mode.

- Mobile breakpoint adjusted: 18rem height + 11px font at ≤720px.

- Lifecycle IIFE play() now calls a tiny scrollToBottom() helper
  after every line append and after every typeInto callback, so the
  viewport snaps to the latest line like a real terminal. scrollTop
  resets to 0 at the start of play() so replay works from the top.

- scroll-behavior: auto (not smooth) — instant snap matches the
  terminal feel and avoids "scroll is still happening while the
  next line is typing" jank.

Behaviour
- JS-enabled: terminal-like viewport, new lines stream in at the
  bottom, old lines scroll out of view
- No-JS: same 17rem viewport with the full static content;
  overflow-y: auto means the user can scroll the box manually to
  see all 54 lines
- Reduced motion: static pre-rendered content, no animation, user
  scrolls manually (same as no-JS)

Page footprint drops from ~52rem to 17rem — the lifecycle section
now takes roughly the same vertical space as the /idea hero demo.

Refs me2resh/apexscript-org#100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(#100): replace /idea demo with lifecycle in the hero

CEO feedback on the live preview: "i like this more than the idea,
lets replace it". Dropping the /idea hero demo entirely and moving
the lifecycle demo into its slot.

Changes
- Hero: /idea shell-demo block deleted, replaced in the same slot
  with the lifecycle shell-demo (now carrying `rise rise-4` classes
  to match the rest of the hero fade-in sequence).
- Section 00 wrapper (`#lifecycle` section with its header + lede)
  deleted entirely. The demo is now the hero's visual focal point
  instead of a separate section below the fold.
- `/idea` JS IIFE deleted (~100 lines).
- Lifecycle JS IIFE comment updated from "(section 00)" to "(hero)"
  explaining the new placement. Code itself untouched — still uses
  IntersectionObserver with the `hasPlayed` gate + 500ms delay, so
  it auto-plays once on load (since the hero is visible immediately)
  and never re-plays on scroll.
- Titlebar nav: removed the `<a href="#lifecycle">lifecycle</a>`
  link. The demo is in the hero now, so a jump-to link is redundant.
  Nav drops from 6 items to 5 (tree · layers · examples · install
  · github →).

Behaviour
- JS on: lifecycle demo auto-plays once on load in the hero, new
  lines stream into the 17rem viewport, old lines scroll up and
  out like a terminal.
- No-JS: 17rem scrollable viewport with full static content,
  replay button hidden.
- Reduced motion: static content, no animation, replay button
  hidden.

Page structure now:
  hero → tree → layers → examples → install → scope → footer
  (SECTION 00 is gone; tree becomes the first post-hero section)

The footprint below the hero is ~52rem lighter than before the
revert — the single in-hero demo is the only shell demo on the
page.

Refs me2resh/apexscript-org#100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(#100): lifecycle animation — autonomous by default, 3 human touchpoints

CEO feedback: "for the animation, it looks like we run every command
in the cycle, it should be autonomous unless plan & push & waiting
for approval". The old script prefixed every step with '$ ' prompts
as if a human was typing each command. Reality: apexstack runs
almost everything autonomously once a ticket is picked up. The human
only intervenes at THREE well-defined touchpoints.

Three human touchpoints now explicit
  1. Plan approval   → "Approve plan? (y/n)"     → > y
  2. Push approval   → "Ready to push PR #84?"   → > y
  3. CEO approval    → "Waiting for CEO 👍"       → CEO 👍

Everything between those is narrated autonomously — no $ prompts,
no implied human typing. The demo now reads as a log stream of what
Atlas did between the three decision points.

Script rewrite (both static HTML and JS array)
- Removed every "$ /command" and "$ git ..." line. They become
  sys-type narrations: "Inbox:", "Picking up #58...", "Plan for
  #58:", "Detected decision: ...", "Local checks:", "Ready to
  push PR #84?", "Pushed · Opened PR #84", "Rex reviewing a3f9c21...",
  "Pipeline on main:", etc.
- Added a new "Ready to push PR #84? → > y" touchpoint between
  the local-checks block and the PR creation. Makes the "push"
  human intervention explicit.
- Role lines softened: "Tech Lead role active — planning" →
  "Tech Lead role: planning" (less shouty; still aspirational —
  roles become real in PR 7).
- Dropped the square-bracket theatrics on the CEO wait line:
  "[waiting for CEO 👍]" → "Waiting for CEO 👍" (cleaner, and
  the long 1500ms delay already conveys "we're waiting").

JS next() simplification
- Removed the `cmd` branch special-case in next(). The `$ ` prompt
  emission is gone. Only `you` type still prefixes with a `prompt`
  span (the `> ` marker). Every other type is rendered as plain
  textContent, with colour driven by the CSS class.
- The `.cmd` CSS class is still in the stylesheet for possible
  future use but nothing in the current script emits it.

Runtime impact
- ~55 script entries (was 52) — +3 for the new push-approval
  touchpoint (sys + you + blank)
- Total runtime drops from ~40-50s to ~18-22s because most lines
  are now instant (speed=0) instead of typewriter. The only
  typewriter action left is the two "y" responses. Much snappier.

Behaviour
- JS on: narrated log stream, only "> y" lines are typed, demo
  auto-plays once on load, scrolls like a terminal
- No JS / reduced motion: same static content, manual scroll
- Multi-project neutrality: 0 hits for flat-mate/curios/sharppick

Refs me2resh/apexscript-org#100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(#100): wire 19 role files into workflows, skills, and CLAUDE.md (#7)

Closes the biggest gap the PR #1 Rex audit flagged: all 19 role
files exist and are well-specified, but nothing in the running
system references them. CLAUDE.md listed them in a table but
didn't @import anything. No workflow named a role file. No skill
invoked a specific role. Users had to manually say "please read
roles/engineering/qa-engineer.md and act as the QA Engineer" for
anything to happen. Roles were passive reference docs.

This PR makes them first-class participants.

New file — .claude/rules/role-triggers.md (~107 lines)
- Activation table for all 19 roles (department, file path, when
  to activate with 2-4 concrete conditions per role)
- Activation protocol (read file → adopt identity → follow
  handoff rules → stay in role until task completes)
- Auto-activation signal table (ticket label, PR path match,
  incident, PRD draft, etc. → which role activates)
- Prompted activation examples ("act as the QA Engineer for #42")
- Role boundary enforcement (CAN/CANNOT from each role file is
  strict — hand off when you hit a CANNOT)
- Handoff artefact table (PRD, tech design, testable build,
  security findings, AC sign-off, etc.) — the contracts between
  roles
- Explicit "aspirational → real" closing note explaining what
  this file makes concrete

CLAUDE.md
- ROLES section gains an "Activation" subsection explaining the
  model in three short paragraphs
- New @.claude/rules/role-triggers.md import at the end of the
  subsection — the trigger table is loaded into every session so
  Claude always knows which role to activate on which signal

workflows/sdlc.md — each phase gets a "Primary role" header
- Phase 1 Planning → Tech Lead (+ Product Manager, Head of Eng
  on escalation)
- Phase 2 Tech Design → Tech Lead (+ Head of Eng, UX/UI Designer)
- Phase 3 Build → Backend / Frontend Engineer (+ Tech Lead
  coordinator)
- Phase 4 Code Review → Tech Lead + Rex (+ Security Auditor on
  auth/crypto diff, UI Designer on UI diff)
- Phase 5 QA → QA Engineer (MANDATORY — merged code is never Done
  without QA sign-off; expands the existing "QA gate" warning)
- Phase 6 Deploy → Platform Engineer (+ SRE for runbook/rollback)
- Phase 7 Monitor → SRE (+ Head of Eng escalation)
- "Roles Summary" table at the bottom rewritten with every role
  as a markdown link to its file

workflows/code-review.md — Roles table expanded
- Author column now names the actual Backend/Frontend Engineer
  roles
- Automated reviewer named explicitly (Rex agent)
- Human approval gate = Tech Lead with a link to the role file
- Conditional Security Auditor and UI Designer rows added with
  their trigger conditions
- QA Engineer called out as "not a reviewer" to kill the common
  misconception that QA approves merges

workflows/deployment.md — new Roles table at the top
- Maps each deployment stage (CI/CD maintenance, staging, prod
  gate, incident response, post-deploy monitoring, security gate)
  to its activating role and trigger condition
- Head of Eng sign-off noted for risky production promotions

Skills — 5 files get an "Activated role" section between the
intro and the process
- /decide → Tech Lead (+ Head of Eng for arch-review threshold,
  Security Auditor if decision touches auth/secrets)
- /write-spec → Product Manager (+ Head of Product escalation,
  UX/UI Designer for design-heavy features; hands off to Tech
  Lead at Tech Design phase)
- /code-review → Rex + Tech Lead (+ conditional Security Auditor,
  conditional UI Designer) — the richest of the five because
  code review has the most conditional branches
- /security-review → Shield + Security Auditor (+ Head of Security
  for strategic calls, Penetration Tester for active testing)
- /roadmap → Head of Product (+ Product Analyst for data-driven
  reprioritisation)

Not in scope for this PR
- The 19 role files themselves are untouched — their content was
  already good per the audit
- Skills /inbox, /status, /tasks, /projects, /idea, /handover,
  /audit-deps, /stakeholder-update don't get role activation
  sections because they're portfolio / CEO-facing or the role
  is implicit from the task context
- No new roles added
- The .claude/rules/role-triggers.md file is NOT imported from
  every workflow/skill — only CLAUDE.md imports it once, and
  individual files reference it relatively when they need to
  cite the activation protocol. Keeps the context footprint
  lean.

Token budget
- role-triggers.md is ~107 lines (~1.3k tokens). Loaded once per
  session via the CLAUDE.md @import. The 19 full role files are
  NOT pre-loaded — they're read on demand when their trigger
  fires (saves ~22k tokens that would otherwise sit idle).

Multi-project neutrality
- grep for flat-mate/curios/sharppick/movetwo/yumyum across all
  10 changed files → 0 hits
- All file paths use `roles/{department}/{role}.md` and
  `.claude/rules/role-triggers.md` — no org-specific references

Refs me2resh/apexscript-org#100

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(#100): multi-project only + fork-first install (#8)

* refactor(#100): multi-project only + fork-first install

Two strategic direction changes from the CEO rolled into one PR
because they're deeply coupled — removing single-project mode
changes the install flow, and the fork-first install changes
every doc that talked about cloning into .apexstack/.

1. Drop single-project mode entirely
---------------------------------------
Single-project mode was a dual-mode compromise that added
complexity without matching how apexstack is actually used.
The audit found every skill had a mode branch that was never
exercised in practice. Users who thought they only had one repo
almost always ended up with two within a few months.

- onboarding.yaml: removed the apexstack.mode field + the
  multi-paragraph mode explainer
- apexstack.projects.yaml.example: rewritten header comment to
  lead with "no single-project fallback mode; register your one
  repo and the skills work the same"
- CLAUDE.md: OPERATING MODE section replaced with PORTFOLIO MODEL
  section explaining the fork-as-ops-repo mental model. SETUP
  section dropped the "read apexstack.mode" step.
- docs/multi-project.md: full rewrite as the canonical setup
  guide. Removed the TL;DR comparison table, the "when to switch
  to single-project" section, the "migrating from single → multi"
  section, the "going back: multi → single" section, and every
  trade-off framed against single-project.
- 8 skill files (handover, idea, inbox, projects, roadmap,
  stakeholder-update, status, tasks): dropped every mode detection
  block (grep onboarding.yaml for mode:), dropped every
  mode-comparison table, simplified scope statements to "iterates
  the registry" or equivalent. Dead code removed.
- workspace/README.md, projects/README.md: removed the "two
  modes" sections, simplified to describe the single portfolio
  pattern.
- README.md: removed the Operating modes table + the
  Single-project install (opt-out) section + the Global install
  (alternative) section (see item 2 for why the global install
  is gone).
- site/index.html: removed the "Operating modes (single &
  multi-project)" hero metric, updated the layers section lede,
  removed every single-project mention in Layer 05, removed the
  "opt-out — single-project mode" install step, removed the
  "alternative — global install" install step.

The only remaining "single-project" strings in the codebase are
TWO intentional negation disclaimers (in docs/multi-project.md
and site/index.html Layer 05) that tell anyone searching for the
concept: "there is no single-project fallback". That's a feature,
not a bug.

2. Fork-first install (replaces clone-into-.apexstack/)
--------------------------------------------------------
The old install model cloned apexstack into a hidden .apexstack/
subdirectory of a separate ops repo, then symlinked .claude/ up
one level. Three problems:

  a. Brand invisibility — .apexstack/ is a dotfile, hidden from
     ls and GitHub views. Nobody knew you were using apexstack.
  b. Two repos to maintain — your ops repo plus the nested clone.
  c. Symlink fragility — the .claude/ symlink broke on dotfile
     sync tools and Windows setups.

New model: your ops repo IS a fork of apexstack. One repo, no
nesting, no symlinks. Upgrades flow via `git fetch upstream &&
git merge upstream/main` — the standard fork workflow.

Per the CEO's call, users can rename the fork to your-org/ops
or keep it as your-org/apexstack. GitHub handles the rename
cleanly. The install docs describe the rename as optional.

- Hero install block: "git clone ... .apexstack" →
  "gh repo fork me2resh/apexstack --clone"
- Hero CTA: "★ Star on GitHub" →
  "★ Star · ⑂ Fork on GitHub" (single button, per Q3.c)
- Hero install caveat: rewrote to explain "the fork IS your ops
  repo, no nested installs, no symlinks"
- SECTION 05 / INSTALL: full rewrite. 6 steps became 5. The 5
  steps are: star+fork, add upstream remote, configure
  onboarding.yaml, create the registry, start working. The old
  "symlink runnable layer" step is gone (no symlink needed). The
  old "wire CLAUDE.md with @-import" step is gone (CLAUDE.md is
  already at the fork root).
- README.md Quick Start: same 5-step rewrite, matched to the
  site flow.
- docs/multi-project.md: complete rewrite as a setup guide
  covering the fork flow, directory layout, daily workflow,
  upgrade path (git pull upstream), trade-offs, and FAQ. ~314
  lines, honest about the pros and cons.

Side effects (positive)
-----------------------
- Layers section UX bug from the earlier screenshot is gone.
  Layer 05 no longer has "content only fills left 1/3" — added a
  new .layer--wide CSS variant with a 2-column internal grid
  (description on the left, registry file list on the right).
  Fills the full width naturally.
- Hero metric #4 changed from "2 Operating modes" to "1 Fork ·
  your ops repo in one command" — celebrates the simplification
  instead of the dropped complexity.

Not in scope
------------
- The lifecycle demo script in the hero is untouched
  (it doesn't reference install or mode)
- Role files in roles/ are untouched (no mode refs)
- Workflow files (sdlc, code-review, deployment) are untouched
  (no mode refs)
- .claude/agents/ are untouched (no mode refs)
- Hooks in .claude/hooks/ are untouched (no mode refs)
- The apexstack.mode field in the existing onboarding.yaml.example
  — this is the site's own onboarding.yaml which gets removed
  with the mode config

Verification
------------
  grep -rn "single-project" --include="*.md" --include="*.yaml" \
    --include="*.html" --include="*.sh"
  → 2 hits, both intentional negation disclaimers

  grep -rn "mode:" --include="*.md" --include="*.yaml" \
    --include="*.html"
  → 0 hits

  grep -rn "\.apexstack/" --include="*.md" --include="*.yaml" \
    --include="*.html"
  → only in docs/multi-project.md explaining why the old pattern
    was dropped (historical context paragraph)

Multi-project neutrality
------------------------
  grep -iE "flat-?mate|curios|sharp ?pick|movetwo|yumyum" \
    on all 16 changed files
  → 0 hits

Refs me2resh/apexscript-org#100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(#100): address Rex review — blockers + CTA contradiction + doc fork

Rex's delta review on 160148f found 4 blockers + 1 site CTA
contradiction + a few vestigial mentions. Plus the deeper grep
I ran caught two more: a stale .apexstack/ example in
golden-paths/pipelines/README.md, and docs/getting-started.md
still documenting the old .apexstack/ + symlink flow.

Blockers fixed
--------------
- B1: idea/SKILL.md rule 5 "Mode-aware — detect apexstack.mode"
      → "Single backlog — every idea goes into
         projects/ideas-backlog.md"
- B2: roadmap/SKILL.md rule 6 "Mode-aware — ROADMAP.md or
      projects/<name>/roadmap.md"
      → "One roadmap per project — always write to
         projects/<name>/roadmap.md"
- B3: status/SKILL.md had a "## Multi-project mode" section and
      a "Single-project mode default:" output format header.
      Renamed to "## Portfolio output" and "## Output format
      (one-project view with --project <name>)". No behaviour
      change — just language that doesn't frame /status as
      mode-switching.

Non-blocking suggestions fixed
------------------------------
- S1 (site CTA contradiction): index.html:1732 final CTA was
      "one git clone, one symlink, and one config file away"
      → "one fork, one clone, and one config file away". The
      old line directly contradicted the "no symlinks" story.
- S3 (CLAUDE.md QUICK REFERENCE):
  - "Project registry (multi-project)" → "Portfolio registry"
  - "Per-project docs (multi-project)" → "Per-project docs"
  - "Live working copies (multi-project)" → "Live working
    copies (gitignored)"
  - "Multi-project guide" → "Full setup guide"

Also cleaned up while I was in there
------------------------------------
- inbox/SKILL.md rule 3: "Multi-project mode iterates the
  registry" → "Registry-scoped — only projects listed in
  apexstack.projects.yaml count"
- projects/SKILL.md error row: "Multi-project mode but no
  apexstack.projects.yaml" → "No apexstack.projects.yaml at
  the ops-repo root"
- projects/README.md directory layout: "ideas-backlog.md
  (multi-project mode)" → just "shared ideas backlog"

Out-of-scope but too tangled to leave
-------------------------------------
- golden-paths/pipelines/README.md: `cp` examples pointed at
  `.apexstack/golden-paths/...` as if apexstack were still a
  nested clone. Rewrote to "copy from ~/apexstack (your fork)
  to your managed project's .github/workflows/". Not strictly
  within the mode-removal scope but the README is now
  self-consistent with the fork-first install.
- docs/getting-started.md: rewrote Step 1 and Step 3 to match
  the new fork flow. Was still documenting the old .apexstack/
  + submodule + @.apexstack/CLAUDE.md @-import pattern —
  guaranteed to confuse a new adopter. Keeps parity with
  docs/multi-project.md and the site install section.

Verification
------------
  grep -rin "single-project" --include="*.md" --include="*.yaml" \
    --include="*.html"
  → 2 hits, both intentional negation disclaimers in
    docs/multi-project.md:5 and site/index.html:1367

  grep -rn "apexstack.mode\|mode: multi-project\|mode: single-project\|Mode-aware" \
    --include="*.md" --include="*.yaml" --include="*.html"
  → 0 hits

  grep -rn "\.apexstack/" --include="*.md" --include="*.html"
  → only in docs/multi-project.md historical context paragraph
    (explaining why the old pattern was dropped) and README.md
    negation disclaimer ("no .apexstack/ symlinks")

Refs me2resh/apexscript-org#100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(#101): /handover auto-append + /idea polish (audit-flagged gaps) (#9)

Closes the last sub-task of the apexstack positioning epic (#100).
The Explore agent audit flagged specific gaps in both skills; these
were deferred through PRs #4-#8 because they're independent of the
positioning work. Now fixed.

/handover — 3 gaps closed
-------------------------

1. **Auto-append to the portfolio registry** (was the CRITICAL gap
   from the audit). Previously the skill printed a YAML snippet
   and told the user "add this to apexstack.projects.yaml". Users
   forgot, or miscopied, or broke the YAML indentation.

   Fix: new step 6 prompts the user `Ready to add {name} to
   apexstack.projects.yaml? (y/n)`. On y, the skill:
   - Locates the registry at the ops-repo root (creates from
     .example if missing, with a warning)
   - Appends the entry via `yq` if available, otherwise plain-text
     append with careful indentation
   - Validates the result by parsing the YAML (yq or python yaml)
   - Rolls back on failure (never leaves the registry broken)
   - Confirms the append to the user with the derived roles list

   On n, prints the snippet for manual copy-paste and continues
   without writing.

2. **Dynamic "Next Steps"** derived from the risks found. The
   old template had generic placeholders like `{first concrete
   action — usually "run /audit-deps and triage criticals"}`
   which was embarrassing to ship.

   New behaviour: a mapping table in the skill spec defines the
   derivation. Examples:
   - CVEs detected → `/audit-deps {name} — triage the {severity}
     {package} CVE before any new feature work`
   - Failing tests → `Fix the {N} failing tests in {module}
     before merging new PRs`
   - No observability → `/decide on observability ({top 2 options
     for this stack})`
   - Stale CI → `Re-enable CI — copy in golden-paths/pipelines/ci.yml`
   - Coverage unknown → `Set up test coverage reporting`
   - Backlog > 10 → `Triage the issue backlog with previous owner`
   - Missing README → `Write a minimum-viable README`

3. **Post-handover checklist** added to the assessment template,
   also dynamically tailored to the risks found. Items like "close
   {top risk} before the first feature PR", "add {name} to weekly
   /stakeholder-update rollup", "set up a coverage baseline".

Bonus gap closed: **derive the role list dynamically** from the
tech stack + CI config + security surface, instead of hard-coding
`[tech-lead, backend-engineer]`. Mapping table in the spec:
- backend deps → backend-engineer
- UI code → frontend-engineer
- CI config → platform-engineer
- deployment evidence → sre
- auth/crypto/secrets → security-auditor
- always → tech-lead

A typical handover ends up with 3-5 roles in the registry entry.

/idea — 3 gaps closed + 1 numbering bug fixed
----------------------------------------------

1. **Input validation for category**. The old step 2 asked for
   category but silently accepted anything. A user who typed
   `foo` got `Category: foo` in the backlog.

   Fix: the prompt now explicitly lists 1/2/3/4, accepts either
   the number or the word (case-insensitive), and **re-prompts
   on invalid input** with `Please pick 1-4 or type the category
   name.` Loops until valid.

   Same treatment for the description field — re-prompt if empty.

2. **Dedup check before appending** (new step 3). Prevents
   submitting the same idea twice.

   Implementation: a simple token-overlap heuristic. Normalise
   both titles (lowercase, strip punctuation), compare with a
   threshold (≥ 80% of the words in the shorter title appear in
   the longer one).

   If a match is found:

     ⚠ Similar idea already in the backlog:
       IDEA-025 — {existing title} (status: {status})

     Is this a duplicate? (y = skip, n = add anyway)

   On y: skip the append, suggest `/write-spec IDEA-025` if the
   user wants to work on the existing idea. On n: continue to
   step 4.

3. **Error handling for `gh issue create`** in step 6. Old
   behaviour: if the tracking issue creation failed, the idea
   was half-saved or the whole thing errored out. New behaviour:

     ⚠ Couldn't create the tracking issue: {reason}
       The idea is still saved in projects/ideas-backlog.md
       as IDEA-NNN.

     Try again? (y = retry, n = skip, gh = show the gh error)

   With a failure-modes table: missing auth scope, label not
   found, rate limit, network error, etc. — each has a specific
   recovery path.

   Guiding principle (now rule #8): **the backlog entry is the
   primary artefact; the tracking issue is a bonus**. Never lose
   the backlog entry because GitHub was flaky.

4. **Section numbering bug** fixed. The old file had steps 1, 2,
   4, 5, 6 — step 3 was missing because an earlier refactor
   deleted it without renumbering. With the new step 3 (dedup
   check) the sequence is now 1, 2, 3, 4, 5, 6 again.

Rules sections updated for both skills
--------------------------------------

- /handover: rule 4 is now "Auto-append to the registry (with
  confirmation)"; rule 5 is "Derive roles from the stack"; rule
  6 is "Derive next steps from the risks"; rule 10 is "Never
  break the registry".
- /idea: rule 6 is "Validate before accepting"; rule 7 is
  "Dedup before appending"; rule 8 is "The backlog is the
  primary artefact".

What's NOT in this commit
-------------------------

- The tabbed terminal animation (#102) — separate ticket,
  not part of the epic closure
- Any changes to the skill frontmatter
- Any changes to the `/handover` assessment output format
  beyond the Next Steps and Post-Handover Checklist sections
- Any changes to `/idea`'s backlog file format or ID scheme

This closes the epic #100. After this merges, apexstack is at
its v0.2 shape: positioning rewritten, lifecycle demo in the
hero, 19 roles wired in, multi-project-only + fork-first install,
and now the /handover and /idea skills that actually work
end-to-end.

Closes me2resh/apexscript-org#101
Closes me2resh/apexscript-org#100

Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(#103): mechanical enforcement of ticket-first, auto-review, onboarding

Test run of ApexStack on a real project exposed three SDLC compliance gaps
that all traced back to the same root cause: workflow rules lived as prose
in CLAUDE.md, .claude/rules/, and workflows/ — advice the model drops under
pressure. This PR moves the four highest-leverage rules into .claude/hooks/
where the harness executes them mechanically.

## New hooks

- require-active-ticket.sh — PreToolUse on Edit/Write/MultiEdit; blocks
  code-path edits when the active-ticket marker is missing. Exempts
  .claude/, docs/, projects/*/docs/, and any *.md file.
- auto-code-review.sh — PostToolUse on Bash; fires after PR creation and
  nudges Claude to invoke the code-reviewer agent (Rex) immediately.
- block-unreviewed-merge.sh — PreToolUse on Bash; blocks PR merge unless
  a Rex approval file exists at .claude/session/reviews/<pr>-rex.approved
  AND its SHA matches HEAD.
- onboarding-check.sh — SessionStart; warns on every new session until
  /onboard writes the onboarded marker.

## New skills

- /start-ticket <issue> — verifies the issue via `gh issue view`, writes
  the active-ticket marker, suggests a branch name per git-conventions.md.
- /onboard — day-one discovery pass (project identity, tracker repo,
  required CI checks, reviewers, UI work, deploy targets, sensitive topics).
  Writes the onboarding marker and .claude/project-config.json. Idempotent.

## Infrastructure

- .claude/settings.json registers SessionStart, new PreToolUse matchers for
  Edit/Write/MultiEdit and pre-merge, and a PostToolUse Bash matcher for
  post-PR-creation. Existing six-hook Bash block untouched. $schema preserved.
- .gitignore (new file — apexstack had none) excludes .claude/session/,
  .claude/project-config.json, .claude/settings.local.json, and workspace/*/
  per the multi-project model in docs/multi-project.md. workspace/README.md
  stays visible via a negation rule.
- .claude/hooks/README.md documents the four new flows, the exit-code
  semantics (exit 2 blocks in PreToolUse, nudges in PostToolUse), the
  session-state directory layout, the merge-gate trust model, and how to
  add new hooks.

## Review history

Rex approved across two passes. Three nice-to-haves from the first pass
were applied in a follow-up commit:

- onboarding-check.sh switched to an interpolating heredoc so the "no
  onboarding marker at" message prints the real absolute path and a
  copy-pasteable workaround.
- auto-code-review.sh comment expanded to cite harness version drift
  (Claude Code 2.x+ vs 1.x vs earliest builds) and flag when the older
  fallback paths can be dropped.
- Hooks README documents the merge-gate's local trust model: the approval
  file is session state, not a remote trust boundary, so branch protection
  and CODEOWNERS remain the adversarial layer.

Refs me2resh/apexscript-org#103

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(#11): require explicit per-merge CEO approval — never infer from "go"

Closes the failure mode where I merged apexstack PR #10 after a plan-level
"go" that was not a per-PR merge approval. The rule existed in prose but
was ambiguous, and there was no mechanical enforcement for the human side
of the 2-reviews gate.

## Prose tightening

- `.claude/rules/pr-workflow.md` "Before PR merge" section rewritten with
  a concrete wrong/right example showing that plan-level "go" does NOT
  carry through to the merge step. Lists other destructive actions
  (force pushes, branch deletes, closing issues with dependents, external
  posts) that need the same per-action explicit approval.
- `CLAUDE.md` Quality Rules adds an explicit bullet calling out per-PR
  CEO approval, linking to the full rule.

## Mechanical enforcement

- `.claude/hooks/block-unreviewed-merge.sh` now requires TWO approval
  markers, not one:
    - `.claude/session/reviews/<pr>-rex.approved` — from the code-reviewer
      agent (existing)
    - `.claude/session/reviews/<pr>-ceo.approved` — from the /approve-merge
      skill, on explicit per-PR user invocation (new)
  Both must contain the current HEAD SHA. Any mismatch blocks the merge.
- New /approve-merge <pr> skill at .claude/skills/approve-merge/SKILL.md.
  Its one job is to write the CEO marker on explicit per-PR user
  invocation. Definition includes valid/invalid invocation triggers and
  an anti-pattern section describing the exact failure mode the skill
  exists to prevent.
- Marker paths anchored at `git rev-parse --show-toplevel` so invocation
  from any subdirectory (e.g. workspace/<project>/) still writes to the
  path the hook reads from.
- .claude/hooks/README.md documents both markers, why there are two, and
  the trust model: local session state, not a remote trust boundary. The
  failure mode closed is "invisible inference" (Claude decides "go"
  meant "merge"); the hook converts it into "visible rule violation"
  (Claude touched a file it wasn't supposed to). Grep-able instead of
  invisible.

## Dogfooding

This PR is the first one merged under the new rule. Flow:

  1. PR created, auto-code-review hook fires (already in place from #10)
  2. Rex reviews — APPROVED, flags 4 nice-to-haves, 1 of which is a real
     correctness bug (cwd-relative path in skill step 5)
  3. Fix commit pushed addressing the cwd bug; other 3 nice-to-haves
     deferred to a follow-up ticket
  4. Rex re-reviews the new HEAD — APPROVED, no further issues
  5. CEO is asked per-PR, explicitly, for merge approval on PR #12
  6. CEO replies "12 approved" — explicit per-PR approval
  7. /approve-merge 12 invoked — writes CEO marker at repo root
  8. Confirmation returned to CEO, separate per-action nod requested
  9. CEO replies "ship it"
  10. This squash-merge runs — both markers present, both SHAs match HEAD,
      merge-gate hook allows through

Rex reviewed twice. CEO explicitly approved twice (once for the merge,
once for executing the merge) — each moment discrete, each named the PR.

Closes #11

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(#14): ticket-vocabulary rule + verify-issue-exists backstops

Closes the vocabulary-collision failure mode where Claude's internal
plan decomposition wears tracker clothing and the user reasonably
reads it as tracker state. Root cause identified on 2026-04-11 after
a friend of the CEO hit it on a real project: the agent presented a
10-item "Ticket N ... blocked by #M" plan in chat, none of which
existed on GitHub.

## Root-cause rule (primary fix)

- New .claude/rules/ticket-vocabulary.md reserves `Ticket`, `#N`, and
  dependency notation (`blocked by #N`, `depends on #N`, etc.) for real
  GitHub issues only. Prescribes safe vocabulary for in-conversation
  planning: `Step N`, `Item A`, plain bullets, phases. Includes a
  boundary-crossing rule — if plan items need tracker properties, STOP
  and run `gh issue create` before presenting. Contains the 2026-04-11
  anti-pattern verbatim and a corrected version side-by-side.
- CLAUDE.md Quality Rules links the new rule alongside the per-PR
  merge approval bullet (both are "don't fake process state" rules).

## Mechanical backstops

- validate-pr-create.sh extended: extracts the issue number from the
  PR title and runs `gh issue view` against the resolved tracker repo.
  Blocks PR creation if the referenced issue doesn't exist. Tracker
  repo resolves from .claude/project-config.json first, falls back to
  origin remote.
- New verify-commit-refs.sh on PreToolUse / Bash git-commit: parses
  the commit message from -m or -F args, scans for Closes/Fixes/
  Resolves/Refs/Related-to #N patterns, verifies each via gh issue
  view. Blocks on any missing reference. Interactive commits (no -m /
  -F) are skipped.
- settings.json registers the new hook under the existing git-commit
  matcher.
- hooks/README.md adds a "Ticket-Vocabulary Backstops" section framing
  both hooks as backstops, not primary fixes.

## Multi-line -m fix (second commit)

Rex's first review labeled a multi-line gap as "nice-to-have, rarely
fires". Testing revealed it fires ALWAYS on Claude-generated commits,
because Claude uses HEREDOC substitution for nearly every commit
message, which produces literal newlines in the -m value. The hook's
`sed -nE` processes line-by-line and couldn't match across lines —
result: the hook was silently inert on its own introducing commit.
The "dogfood success" in the PR #16 body was a false positive.

Fix: `COMMAND_FLAT=$(echo "$COMMAND" | tr '\n' ' ')` before all sed
extraction. Multi-line -m values now parse as a single logical line.
Scoped only to parsing — extracted MSG preserves original content.
Single-line paths unregressed (zero newlines → tr is a no-op).

## Smoke tests (post both fixes)

  1. settings.json jq parse                                        ✓
  2. validate-pr-create allows real #11 / #14 in title             ✓
  3. validate-pr-create blocks fake #999999 in title (exit 2)      ✓
  4. verify-commit-refs allows single-line real ref                ✓
  5. verify-commit-refs blocks single-line fake ref                ✓
  6. verify-commit-refs skips interactive commits                  ✓
  7. verify-commit-refs allows no-ref messages silently            ✓
  8. verify-commit-refs blocks multi-line HEREDOC with fake ref    ✓
  9. verify-commit-refs allows multi-line HEREDOC with real ref    ✓

## Why the rule comes first, hooks are backstops

Hooks can only see tool calls, not prose output. A fabricated `#N` in
a chat message is invisible to any hook. The vocabulary rule is the
primary defense; the hooks catch the downstream symptom at the moment
fabrication becomes durable (PR title, commit message). Linting
Claude's prose output was considered and rejected — it depends on
Claude remembering to check itself, which is exactly the failure mode
this ticket exists to prevent.

## Review history

Rex reviewed twice. First pass: approved lean with 3 nice-to-haves,
one of which (multi-line gap) turned out to be must-fix on closer
inspection. Fix commit addressed it. Rex re-reviewed the fix commit
and approved cleanly.

CEO approved per-PR explicitly (naming PR #16) before this merge,
then gave a separate explicit merge instruction in the same message.

Closes #14

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(#13): rule-audit hooks — AgDR-for-arch, design review, red-CI, commit-format

Closes four previously-unenforced MUST rules from the apexstack rule
files. Ships them as hooks with narrow default path lists and
project-config overrides. Design decisions captured in AgDR-0001, the
first AgDR in the apexstack repo.

This is the third rule-enforcement PR in a single session, after #12
(explicit merge approval) and #16 (ticket vocabulary + verify-issue-
exists). Together, #11 / #14 / #13 convert 10+ prose MUST rules into
mechanical hooks.

## New hooks

- require-agdr-for-arch-changes.sh — PreToolUse on git commit. When
  the staged diff touches architecture files (infrastructure/, *.tf,
  Dockerfile*, docker-compose*, .github/workflows/), requires an AgDR
  reference in the commit message or a new AgDR file staged alongside.
  Closes the prose-only claim in agdr-decisions.md.

- require-design-review-for-ui.sh — PreToolUse on the merge step. When
  the PR diff touches UI files (.tsx, .jsx, .vue, .svelte, .css, .scss,
  .sass, .less, design-tokens), requires a design approval marker at
  .claude/session/reviews/<pr>-design.approved. Regex is .tsx$ / .jsx$
  EXACTLY — NOT .tsx? — so backend .ts files don't false-positive.
  Closes the prose-only gate in pr-quality.md and code-review.md.

- block-merge-on-red-ci.sh — PreToolUse on the merge step. Runs the
  pr-checks lookup and blocks on any failing/cancelled/timed-out/
  pending/in-progress check. Allows the "no checks reported" case with
  a NOTE (legitimate state for repos without CI). Closes the prose-only
  "No Red CI Before Merge" rule in pr-quality.md.

- validate-commit-format.sh — PreToolUse on git commit. Validates the
  subject against ^(feat|fix|refactor|test|docs|chore|style|perf|build
  |ci|revert)(\(scope\))?: text. Matches the PR-title type list in
  git-conventions.md. Multi-line -m HEREDOC safe.

## AgDR-0001 (first AgDR in apexstack)

docs/agdr/AgDR-0001-rule-mechanization-hooks.md records:
- Options considered (broad defaults rejected, narrow + config chosen,
  one-PR-per-hook rejected)
- Rules that explicitly stay advisory (>80% coverage, no bare any,
  one-ticket-at-a-time, role trigger patterns, /decide triggers)
- Threshold decisions for each of the four hooks
- Consequences and follow-up tickets

Sets the pattern for all future apexstack AgDRs.

## Smoke tests (all passing; two bugs found mid-test and fixed)

  1. settings.json jq parse ................................ valid
  2. validate-commit-format:
     - feat: ok / feat(scope): ok / multi-line HEREDOC ok .. exit=0
     - "added thing" (no type) ............................. exit=2
  3. require-agdr-for-arch-changes:
     - no staged / non-arch file ........................... exit=0
     - Dockerfile + no AgDR ................................ exit=2
     - Dockerfile + "per AgDR-0042" in message ............. exit=0
  4. block-merge-on-red-ci:
     - "no checks reported" case ........................... exit=0 (NOTE)
     - all green CI ........................................ exit=0
  5. require-design-review-for-ui:
     - regex .tsx matches / .ts does NOT match ............. verified
     - PR with no UI changes ............................... exit=0

Two bugs were caught mid-smoke-test and fixed pre-commit:

- block-merge-on-red-ci.sh assumed "no checks configured" returns
  exit 8 but the pr-checks tool returns non-zero with "no checks
  reported" text. Fixed to pattern-match the text.
- require-design-review-for-ui.sh regex was .tsx? / .jsx? which
  matched plain .ts / .js (backend code). Fixed to .tsx / .jsx
  exactly.

## Review history

Rex approved cleanly on the first pass (commit d7c9641). Unlike the
previous two reviews where nice-to-haves turned out to be must-fix on
closer inspection, this time Rex tested the key regexes live against
filename fixtures and verified the severity calibration honestly.

Four nice-to-haves from the review, deferred to a follow-up ticket:

- ^Dockerfile misses monorepo paths (backend/Dockerfile). Fix:
  (^|/)Dockerfile. Same for ^docker-compose. Material for monorepo
  forks but mitigated by .architecture_paths project-config override.
- infrastructure/ unanchored — mild false-positive on paths like
  docs/infrastructure/. Fix: (^|/)infrastructure/.
- Conventional Commits breaking marker (feat!:) is rejected by both
  this hook and the existing PR-title regex. Consistent, not a bug.
- Dead code (FAILED_COUNT, PENDING_COUNT) in block-merge-on-red-ci.sh.

## Deferred to follow-up tickets

- docs/rule-audit.md — full audit table of every MUST with mechanization
  status. Pure docs, small scope.
- validate-branch-name.sh / validate-pr-create.sh warning→blocker upgrade.
  Breaking change, deserves its own ticket.
- commit_types project-config override.
- /approve-design skill (analogous to /approve-merge) for writing the
  design-review marker.
- The four nice-to-haves from this review (bundled as one small ticket).

## Dogfooding

All four new pre-commit hooks fired on this PR's own commit and allowed
it cleanly. The commit-format and AgDR-arch hooks became self-aware for
the first time — and correctly.

Closes #13

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(#18): regex anchors for monorepo Dockerfiles + dead code cleanup

Addresses three of the four nice-to-haves Rex flagged on PR #17. The
fourth (feat!: Conventional Commits breaking marker) is tracked
separately as #23 because it needs a design decision.

## Changes

- require-agdr-for-arch-changes.sh: monorepo-safe anchoring. The
  original ^Dockerfile / ^docker-compose.* only matched root-level
  files and silently skipped backend/Dockerfile, web/docker-compose.yml,
  services/api/Dockerfile.prod — the common real-world layout.
  Updated to (^|/) prefix anchors.

  Also dropped two ambiguous directory patterns:
  - (^|/)infrastructure/ — matched docs/infrastructure/notes.md and
    src/types/infrastructure/foo.ts as false positives
  - (^|/)terraform/ — same ambiguity, redundant with \.tf$
  Terraform files are caught unambiguously via \.tf$ / \.tfvars$ at
  any depth. CDK / Pulumi projects that use plain .ts/.py files in
  an infrastructure/ directory need to override via
  .architecture_paths in project-config.json.

- block-merge-on-red-ci.sh: deleted unused FAILED_COUNT and
  PENDING_COUNT variables.

- .claude/hooks/README.md: updated the architecture-paths section
  with the new regex list and an explicit CDK known-gap callout.

- docs/agdr/AgDR-0001-rule-mechanization-hooks.md: new "Post-ship
  amendments" section at the bottom with a dated changelog entry.
  The original decision block is untouched — sets a pattern for
  threshold refinement without rewriting historical records.

## Smoke tests

21 path fixtures tested against the new regex list, all passing.
13 should-match cases (including monorepo layouts at various
depths) and 8 should-NOT-match cases (including the previously
false-positive docs/infrastructure/ and docs/terraform-primer.md).

## Review

Rex tested the patterns against 26 fixtures (5 beyond my 21) and
verdict was approved, clean. Two surfaced nice-to-haves:

- README known-gap callout could name Helm/K8s/CFN/SAM, not just
  CDK. Deferred to the SAM-coverage follow-up ticket.
- Dockerfile permissiveness is intentional — catches .prod/.dev
  variants correctly.

Material finding (not blocking, follow-up): SAM template.yaml is
NOT caught by the defaults. FlatMate specifically is SAM-heavy
and would benefit from a project-config override OR a default
addition for (^|/)serverless\.ya?ml$ (the word "serverless" has
no library-code collision, unlike "infrastructure"). Tracked as
a new follow-up ticket to be opened post-merge.

Rex also offered an amendment rule-of-thumb worth codifying:
changelog append for regex/threshold refinement and scope
additions, new AgDR for decision reversals and deprecations.
To be folded into #19 (the full rule-audit doc) or a new tiny
docs/agdr/README.md ticket.

Closes #18

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* ci(#2): dogfood apexstack CI with pr-title, markdown, shell, link checks

ApexStack now dogfoods its own CI. Four GitHub Actions workflows added
so PRs to the framework repo get the same quality gates it ships to
adopters via golden-paths/pipelines/.

- pr-title-check.yml — copied verbatim from golden-paths. Enforces
  ticket ID in PR titles.
- markdown-lint.yml — markdownlint-cli2 on **/*.md with relaxed config
  (.markdownlint.json disables MD013/MD033/MD041 etc. because existing
  docs have bare URLs, long lines, inline HTML).
- shellcheck.yml — shellcheck on .claude/hooks/*.sh at warning severity.
- link-check.yml — lychee on site/index.html + **/*.md, with weekly
  cron for link-rot detection.
- .markdownlint.json — relaxed ruleset. Real structural problems still
  caught (duplicate headings, broken fences, malformed lists).

Optional html-validate.yml skipped — site/index.html is 2000-line
marketing HTML that would need non-trivial config.

Rex approved. No must-fix. Three nice-to-haves deferred:
- ShellCheck will flag pre-existing SC2059 in validate-pr-create.sh
- markdownlint-cli2-action could be bumped from v16 to v23
- pr-title-check validates ticket-ID presence only (stricter check
  lives in the local hook)

Refs #2

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs(#19): full rule-audit table at docs/rule-audit.md

Full rule-audit table at docs/rule-audit.md. Every MUST / NEVER /
HARD-STOP rule across CLAUDE.md, 8 .claude/rules/*.md files, and 3
workflows/*.md files, each mapped to its enforcement mechanism (hook,
agent, or prose) and classified as mechanize…
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants