Skip to content

chore: rolling promotion dev -> main - #2539

Merged
namastex888 merged 9 commits into
mainfrom
dev
Jul 10, 2026
Merged

namastex888 merged 9 commits into
mainfrom
dev

Conversation

@namastex888

@namastex888 namastex888 commented Jul 10, 2026 •

Copy link
Copy Markdown
Contributor

Rolling Promotion PR

Auto-maintained rolling promotion PR from dev to main.

Process:

  • This PR is automatically created and kept open
  • Human reviews and merges when ready
  • Label ready-to-merge added when all checks pass

IMPORTANT: Merge with "Create a merge commit" — NEVER squash.
Squash merging breaks history sync between dev and main,
causing the next rolling PR to show all commits again.

Human approval required for merge to production.

Summary by CodeRabbit

  • New Features

    • Added the native /council workflow with deliberation and repository-audit modes.
    • Added shared expert lenses to provide focused perspectives during council sessions, reviews, and brainstorms.
    • Added automatic workflow setup and updating when the plugin starts or is updated.
    • Added new review lanes for architecture, quality, documentation, performance, testing, repository hygiene, and supply-chain concerns.
  • Documentation

    • Updated usage guidance for /council, /review, and /brainstorm.
  • Chores

    • Updated the release version to 5.260710.2.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR replaces the legacy council skill with a native two-mode workflow, adds a shared lens corpus and lane skills, rewires council consumers, introduces workflow linting and validation gates, updates release metadata, and documents hook-injection hardening work.

Changes

Council workflow migration

Layer / File(s) Summary
Workflow design and rollout contract
.genie/INDEX.md, .genie/brainstorms/..., .genie/wishes/council-workflow/WISH.md
Defines the native /council workflow, deliberation and audit modes, lens library, installation model, consumer wiring, cutover, and staged gates.
Workflow engine and lens corpus
plugins/genie/workflows/council.js, plugins/genie/references/lenses/*
Adds routing, lens resolution, parallel rounds, synthesis, audit persistence, report rendering, and six deliberation lens cards.
Lane skills and consumer routing
skills/*/SKILL.md, skills/genie/**, skills/review/SKILL.md, skills/brainstorm/SKILL.md
Adds review lane guides and routes explicit council requests, lens panels, and brainstorm domain experts through the shared lens library.
Distribution, linting, and rollout gates
package.json, plugins/genie/**, scripts/council-workflow-lint.ts, .genie/wishes/council-workflow/validate/*, src/lib/council-workflow-stamp.test.ts
Adds workflow packaging documentation, lint integration, staged validation scripts, metadata version bumps, and stamping behavior tests.

Hook hardening record

Layer / File(s) Summary
Hook hardening implementation record
.genie/wishes/hook-injection-hardening/WISH.md
Documents argument-safe git execution, hostile-filename tests, removal of the core.bare startup probe, and associated acceptance criteria.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.58% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the PR’s purpose as a rolling promotion from dev to main, though it is broad and not specific to the workflow changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 SkillSpector (2.3.7)
skills/architecture/SKILL.md

SkillSpector returned invalid JSON output

skills/brainstorm/SKILL.md

SkillSpector returned invalid JSON output

skills/code-quality/SKILL.md

SkillSpector returned invalid JSON output

  • 7 others

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request implements the /council native workflow engine, replacing the old council skill with a unified dynamic workflow that supports both deliberation and repository auditing. It introduces seven standalone lane skills, six deliberation lens cards, an install-time stamping mechanism, and a structural linter. It also integrates the new lens library into the /review and /brainstorm skills. The reviewer's feedback focuses on improving runtime safety and robustness, suggesting the use of defensive guards, optional chaining, and fallback arrays in the workflow script to handle potentially malformed or falsy outputs, as well as using fileURLToPath in the linter script for cross-platform path resolution.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +272 to +273
const ups = entry.response && Array.isArray(entry.response.profileUpdates) ? entry.response.profileUpdates : [];
for (const u of ups) out.push({ lane: entry.member, anchor: u.anchor, change: u.change, note: u.note });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

To prevent potential runtime errors, add a defensive check to ensure that each element u in ups is a valid object before accessing its properties.

    const ups = entry.response && Array.isArray(entry.response.profileUpdates) ? entry.response.profileUpdates : [];
    for (const u of ups) {
      if (u && typeof u === 'object') {
        out.push({ lane: entry.member, anchor: u.anchor, change: u.change, note: u.note });
      }
    }

Comment on lines +456 to +460
const consensus = synth.consensus.length ? synth.consensus.map((c) => `- ${c}`).join('\n') : '- (none recorded)';
const tensions = synth.tensions.length ? synth.tensions.map((t) => `- ${t}`).join('\n') : '- (none recorded)';
const recs = synth.recommendations
.map((r) => `| ${r.priority} | ${r.recommendation} | ${r.rationale} | ${r.risk} |`)
.join('\n');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Use optional chaining and fallback arrays to safely handle cases where synth.consensus, synth.tensions, or synth.recommendations might be undefined or null.

  const consensus = synth.consensus?.length ? synth.consensus.map((c) => "- " + c).join("\n") : "- (none recorded)";
  const tensions = synth.tensions?.length ? synth.tensions.map((t) => "- " + t).join("\n") : "- (none recorded)";
  const recs = (synth.recommendations || [])
    .map((r) => "| " + r.priority + " | " + r.recommendation + " | " + r.rationale + " | " + r.risk + " |")
    .join("\n");

Comment on lines +493 to +507
const laneVerdicts = synth.laneVerdicts.map((l) => `- **${l.lane}** — ${l.verdict}`).join('\n');
const findings = synth.topFindings
.map(
(f, i) =>
`${i + 1}. **[${f.severity}]** (${f.lanes.join(', ')}) ${f.summary}\n - Evidence: ${f.evidence}\n - Action: ${f.action}`,
)
.join('\n');
// A lane that returned nothing, or a lens that never convened, is reported "not audited" here —
// never silently dropped and never averaged in. Merge the synthesizer's partial-coverage list
// with the code-known silent lanes and unresolved lenses.
const notAuditedEntries = [
...synth.notFullyAudited,
...silentRound1.map((n) => `${n} (resolved but returned nothing)`),
...notConvened.map((n) => `${n} (lens file missing)`),
];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Add defensive guards and optional chaining when mapping over synth.laneVerdicts, synth.topFindings, and synth.notFullyAudited to prevent runtime crashes if the synthesizer output is partially malformed.

  const laneVerdicts = (synth.laneVerdicts || []).map((l) => "- **" + l.lane + "** — " + l.verdict).join("\n");
  const findings = (synth.topFindings || [])
    .map(
      (f, i) =>
        (i + 1) + ". **[" + f.severity + "]** (" + (f.lanes?.join(", ") || "") + ") " + f.summary + "\n   - Evidence: " + f.evidence + "\n   - Action: " + f.action,
    )
    .join("\n");
  // A lane that returned nothing, or a lens that never convened, is reported "not audited" here —
  // never silently dropped and never averaged in. Merge the synthesizer's partial-coverage list
  // with the code-known silent lanes and unresolved lenses.
  const notAuditedEntries = [
    ...(synth.notFullyAudited || []),
    ...silentRound1.map((n) => n + " (resolved but returned nothing)"),
    ...notConvened.map((n) => n + " (lens file missing)"),
  ];

Comment on lines +584 to +588
const round1 = convened.map((member, i) => ({
member: member.name,
absPath: member.absPath,
response: round1Raw[i],
}));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Use optional chaining on round1Raw to safely handle potential failures or unexpected falsy returns from the parallel execution.

const round1 = convened.map((member, i) => ({
  member: member.name,
  absPath: member.absPath,
  response: round1Raw?.[i],
}));

),
),
);
round2 = responded.map((self, i) => ({ member: self.member, response: round2Raw[i] }));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Use optional chaining on round2Raw to safely handle potential failures or unexpected falsy returns from the parallel execution.

  round2 = responded.map((self, i) => ({ member: self.member, response: round2Raw?.[i] }));

Comment on lines +28 to +31
import { existsSync, readFileSync, readdirSync } from 'node:fs';
import { join } from 'node:path';

const REPO_ROOT = new URL('..', import.meta.url).pathname.replace(/\/$/, '');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Use fileURLToPath from node:url for robust, cross-platform resolution of import.meta.url to avoid issues with percent-encoded characters or Windows path prefixes.

Suggested change
import { existsSync, readFileSync, readdirSync } from 'node:fs';
import { join } from 'node:path';
const REPO_ROOT = new URL('..', import.meta.url).pathname.replace(/\/$/, '');
import { existsSync, readFileSync, readdirSync } from 'node:fs';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
const REPO_ROOT = fileURLToPath(new URL('..', import.meta.url));

@namastex888
namastex888 merged commit fd8e7ff into main Jul 10, 2026
25 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6e94cbd1a4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}

const template = fs.readFileSync(templatePath, 'utf8');
const stamped = template.split(PLACEHOLDER).join(pluginRoot);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Escape the stamped plugin root as JavaScript

When this hook runs on Windows, pluginRoot contains backslashes (for example C:\Users\Alice\.claude\plugins\genie), but the raw replacement lands inside the workflow’s single-quoted LENS_ROOT string. JavaScript then treats those backslashes as escapes, so the resolver sees C:UsersAlice.claudepluginsgenie and cannot find any lens files; a username or install path containing ' would also make the stamped workflow syntactically invalid. Serialize the path into the template as a JS string literal rather than doing a raw text substitution.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 12

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.genie/brainstorms/council-workflow/DESIGN.md:
- Line 100: Update the acceptance criterion for council.js to require the
runtime-shape parser contract—an async body containing only export const meta,
top-level await/return, and no export default—instead of the contradictory “ESM
parses” requirement; preserve the existing structural checks for meta.name and
forbidden constructs.

In @.genie/brainstorms/council-workflow/DRAFT.md:
- Around line 24-29: Remove the “Plugin-shipped workflows: UNVERIFIED” qualifier
from the Native workflow facts section, replacing it with wording consistent
with the verified distribution and stamp/copy mechanism documented later in the
draft.

In @.genie/wishes/council-workflow/validate/g5-gate.sh:
- Around line 5-9: Replace the incidental output grep in the validation script
with structural parsing of package.json to verify that the check script
explicitly invokes lint:council-workflow. Retain the direct
lint:council-workflow execution as the behavioral check, and report clear
failures for missing wiring or lint errors. Update the relevant assertions in
the gate script around its package.json and bun run check checks.

In @.genie/wishes/council-workflow/WISH.md:
- Around line 174-178: Keep Group 5 marked PARTIAL and do not present the
rollout as merge-ready while the live-QA gate is unmet. Before promotion, add
both required QA evidence files containing real post-release output from
Felipe’s /council runs and verify validate/g5-gate.sh passes; otherwise
explicitly revise the merge objective and documentation to state that this
post-release QA work is non-blocking.

In @.genie/wishes/hook-injection-hardening/WISH.md:
- Around line 73-74: The plan places tests under a __tests__ directory despite
the repository’s colocated-test convention. Update the referenced audit-context
and freshness test deliverables to use colocated *.test.ts files beside their
source modules, or explicitly document an approved exception if the existing
__tests__ structure must be retained.
- Line 49: Update the acceptance criterion in the wish document to distinguish
wish-scoped validation from the overall check: state that the wish-scoped gates
pass, while the full check remains blocked by the unrelated concurrently created
file. Remove the contradictory wording that claims all gates pass while noting
bun run check exits 1.

In `@skills/architecture/SKILL.md`:
- Line 16: Update the architecture audit instructions to remain read-only by
removing the directive to persist repo-profile changes. Align them with the
audit prompt in council.js: return proposed updates as data, and leave the
single write to the workflow’s dedicated synthesis/persist stage.

In `@skills/code-quality/SKILL.md`:
- Line 16: The quality audit lane must remain read-only and must not mutate
repository state or persist .genie/repo-profile.md. Update the guidance around
“When you have enough information to act” and the persistence instruction near
the referenced profile update so it only assesses and returns proposed changes;
leave all writes to the workflow persist stage used by council.js.

In `@skills/dx-docs/SKILL.md`:
- Line 16: Keep the documentation audit lane side-effect free: update the
relevant audit logic associated with the documented default assessment behavior
so it returns repo-profile changes as data rather than persisting them. Move any
profile persistence into the dedicated single-writer stage required by the
council workflow, and ensure both referenced locations follow this contract.

In `@skills/repo-hygiene/SKILL.md`:
- Around line 16-24: Clarify the write policy in the repo-hygiene instructions:
default audits must remain read-only, with persistence as the only permitted
state change unless the invocation explicitly requests broader changes. Update
the “Recall, verify, persist” section to gate updating or deleting
`.genie/repo-profile.md` behind an explicit “persist” or “fix” request, and
replace any unqualified instruction to “act” with this boundary.

In `@skills/supply-chain/SKILL.md`:
- Around line 16-22: Clarify the default persistence behavior in the
supply-chain audit instructions: either explicitly authorize only the required
repo-profile update and cleanup as a narrowly scoped exception, or require an
explicit “persist”/“harden” request before modifying repository state. Update
the sections “Assess and report by default” and “Repo profile — recall, verify,
persist” consistently.

In `@src/lib/council-workflow-stamp.test.ts`:
- Around line 1-10: Move the test currently in council-workflow-stamp.test.ts
from src/lib to plugins/genie/scripts/council-stamp.test.ts so it is colocated
with the council-stamp.cjs implementation and discovered by directory-based test
runs; preserve the existing test contents and imports, updating only any
relative paths that become invalid.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: bad9d911-4ceb-48bf-bbff-79877099d63d

📥 Commits

Reviewing files that changed from the base of the PR and between 7e7d133 and 6e94cbd.

⛔ Files ignored due to path filters (2)
  • plugins/genie/scripts/council-stamp.cjs is excluded by !plugins/genie/scripts/**
  • plugins/genie/scripts/smart-install.js is excluded by !plugins/genie/scripts/**
📒 Files selected for processing (42)
  • .claude-plugin/marketplace.json
  • .genie/INDEX.md
  • .genie/brainstorms/council-workflow/DESIGN.md
  • .genie/brainstorms/council-workflow/DRAFT.md
  • .genie/brainstorms/skill-absorbs/DRAFT.md
  • .genie/wishes/council-workflow/WISH.md
  • .genie/wishes/council-workflow/validate/g1-lane-skills.sh
  • .genie/wishes/council-workflow/validate/g2-engine.sh
  • .genie/wishes/council-workflow/validate/g3-cutover.sh
  • .genie/wishes/council-workflow/validate/g4-consumers.sh
  • .genie/wishes/council-workflow/validate/g5-gate.sh
  • .genie/wishes/hook-injection-hardening/WISH.md
  • biome.json
  • package.json
  • plugins/genie/.claude-plugin/plugin.json
  • plugins/genie/README.md
  • plugins/genie/package.json
  • plugins/genie/references/lenses/deployer.md
  • plugins/genie/references/lenses/measurer.md
  • plugins/genie/references/lenses/operator.md
  • plugins/genie/references/lenses/questioner.md
  • plugins/genie/references/lenses/simplifier.md
  • plugins/genie/references/lenses/tracer.md
  • plugins/genie/workflows/council.js
  • scripts/council-workflow-lint.ts
  • skills/README.md
  • skills/architecture/SKILL.md
  • skills/brainstorm/SKILL.md
  • skills/code-quality/SKILL.md
  • skills/council/SKILL.md
  • skills/council/members/config.md
  • skills/council/members/routing.md
  • skills/council/templates/report.md
  • skills/dx-docs/SKILL.md
  • skills/genie/SKILL.md
  • skills/genie/reference/lifecycle.md
  • skills/perf/SKILL.md
  • skills/qa/SKILL.md
  • skills/repo-hygiene/SKILL.md
  • skills/review/SKILL.md
  • skills/supply-chain/SKILL.md
  • src/lib/council-workflow-stamp.test.ts
💤 Files with no reviewable changes (4)
  • skills/council/members/routing.md
  • skills/council/templates/report.md
  • skills/council/members/config.md
  • skills/council/SKILL.md


## Success Criteria

- [ ] `council.js` structural lint passes: `meta.name === 'council'`, ESM parses, zero `Date.now`/`Math.random`/`new Date()`/`require`/`import`/`fs` occurrences

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Align the acceptance criterion with the runtime-shape parser.

Line 100 still requires “ESM parses”, but the workflow contract is an async body with only export const meta, top-level await/return, and no export default. Replace this with the runtime-shape parse requirement to avoid contradictory validation gates.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.genie/brainstorms/council-workflow/DESIGN.md at line 100, Update the
acceptance criterion for council.js to require the runtime-shape parser
contract—an async body containing only export const meta, top-level
await/return, and no export default—instead of the contradictory “ESM parses”
requirement; preserve the existing structural checks for meta.name and forbidden
constructs.

Comment on lines +24 to +29
### Native workflow facts (docs fetched 2026-07-09)
- Script = `export const meta {...}` + JS body; `agent()/pipeline()/parallel()/phase()`; schema-validated structured outputs; per-agent model/effort overrides.
- Saved workflows: `.claude/workflows/` (project) or `~/.claude/workflows/` (personal) → become `/<name>` commands; accept `args` (structured, no parsing). **Plugin-shipped workflows: UNVERIFIED — background check dispatched.**
- Script has NO fs/shell access — agents do all IO. No mid-run user input. Background, resumable (same session), `/workflows` progress view, per-agent token visibility.
- Skill-instructed Workflow launch counts as explicit user opt-in (skill = thin route calling Workflow tool = legit pattern).
- No SendMessage inside workflows → Socratic round 2 must be fresh agents fed round-1 transcripts via prompt (arguably better: no continuation flakiness, resumable, parallel).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the stale “UNVERIFIED” claim.

Lines 67–73 later state that plugin workflow distribution was verified and specify the stamp/copy mechanism. Leaving line 26 unresolved makes the rollout contract contradictory.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.genie/brainstorms/council-workflow/DRAFT.md around lines 24 - 29, Remove
the “Plugin-shipped workflows: UNVERIFIED” qualifier from the Native workflow
facts section, replacing it with wording consistent with the verified
distribution and stamp/copy mechanism documented later in the draft.

Comment on lines +5 to +9
grep -q '"lint:council-workflow"' package.json || { echo "FAIL: lint:council-workflow script missing from package.json"; exit 1; }

# Behavioral wiring proof: check must actually RUN the council lint, not merely coexist with it.
out="$(bun run check 2>&1)" || { echo "$out"; echo "FAIL: bun run check failed"; exit 1; }
echo "$out" | grep -q 'council-workflow' || { echo "FAIL: lint:council-workflow did not run as part of bun run check"; exit 1; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Verify lint wiring structurally instead of grepping incidental output.

The output check can false-fail when nested script names are not printed and false-pass when another command merely logs council-workflow; it does not prove that check invokes lint:council-workflow. Parse package.json to assert the dependency, then execute the lint script explicitly for behavioral coverage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.genie/wishes/council-workflow/validate/g5-gate.sh around lines 5 - 9,
Replace the incidental output grep in the validation script with structural
parsing of package.json to verify that the check script explicitly invokes
lint:council-workflow. Retain the direct lint:council-workflow execution as the
behavioral check, and report clear failures for missing wiring or lint errors.
Update the relevant assertions in the gate script around its package.json and
bun run check checks.

Comment on lines +174 to +178
**Acceptance Criteria:**
- [x] `bun run check` green AND its output proves `lint:council-workflow` actually ran (behavioral wiring check, not just script existence)
- [ ] Both QA evidence files present with real run output — post-release, from Felipe's own `/council` runs

**Status:** PARTIAL (2026-07-10) — engineering half DONE by the orchestrator inline (Felipe stopped agent dispatch for this wave): `lint:council-workflow` wired into `check` after `wishes:lint` (behavioral proof: check output shows it running, exit 0, 725 pass / 1 skip), plugin README gained the `/council` workflow section (ships/distribution/modes/requirements/override) + `workflows/` in the tree. Live-QA half USER-GATED post-release per Felipe's ruling — `validate/g5-gate.sh` correctly halts at the qa/ assertions until his `/council` runs land. Stamp path pre-validated: the shipped `council-stamp.cjs` stamped a scratchpad copy (placeholder → absolute `LENS_ROOT`, action "written").

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Do not treat this rollout as merge-ready while the required QA gate fails.

Group 5 is still PARTIAL, its live-QA criterion is unchecked, and validate/g5-gate.sh is documented to fail. Either commit both real QA artifacts before promotion or explicitly change the merge objective so this post-release work is non-blocking.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.genie/wishes/council-workflow/WISH.md around lines 174 - 178, Keep Group 5
marked PARTIAL and do not present the rollout as merge-ready while the live-QA
gate is unmet. Before promotion, add both required QA evidence files containing
real post-release output from Felipe’s /council runs and verify
validate/g5-gate.sh passes; otherwise explicitly revise the merge objective and
documentation to state that this post-release QA work is non-blocking.

- [x] `freshness` still emits a stale-read warning for a genuinely recent file authored by another agent (proves the `--format` parse survived the de-shell).
- [x] No `execSync(` call remains in `audit-context.ts` or `freshness.ts`; both import and use `execFileSync`.
- [x] The `core.bare` startup probe no longer appears anywhere in `src/genie.ts`.
- [ ] `bun run check` fully green — **all gates PASS for this wish**: typecheck, biome lint, knip dead-code, skills:lint, wishes:lint (this wish conforms), and `bun test` = 729 pass / 1 skip / 0 fail. Box left unchecked because `bun run check` overall still exits 1 for ONE out-of-scope reason: a concurrently-created file, `.genie/wishes/council-workflow/WISH.md`, is missing the same Complexity/Model columns. Not a regression from these changes; owned by another session.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Keep the acceptance status internally consistent.

This criterion is unchecked and explicitly says bun run check exits 1, so “all gates PASS for this wish” is contradictory. Reword it as “wish-scoped gates pass; the full check remains blocked by the unrelated file” to avoid recording a failing gate as passed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.genie/wishes/hook-injection-hardening/WISH.md at line 49, Update the
acceptance criterion in the wish document to distinguish wish-scoped validation
from the overall check: state that the wish-scoped gates pass, while the full
check remains blocked by the unrelated concurrently created file. Remove the
contradictory wording that claims all gates pass while noting bun run check
exits 1.


## Mandate

Assess and report by default. Apply changes only when the invocation explicitly asks. Never assess from reading alone when a gate exists — run it and report its actual output. Findings outside this lane (architecture judgment, test gaps, performance) get a one-line handoff to the relevant lane skill under `skills/`. When you have enough information to act, act.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Do not mutate state during a quality audit.

“Act” is ambiguous against the preceding read-only mandate, and line 24 explicitly persists .genie/repo-profile.md. This conflicts with plugins/genie/workflows/council.js, whose audit prompt forbids edits and direct profile writes. Restrict the lane to returning proposed updates; the workflow persist stage should own writes.

Also applies to: 24-24

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/code-quality/SKILL.md` at line 16, The quality audit lane must remain
read-only and must not mutate repository state or persist
.genie/repo-profile.md. Update the guidance around “When you have enough
information to act” and the persistence instruction near the referenced profile
update so it only assesses and returns proposed changes; leave all writes to the
workflow persist stage used by council.js.

Comment thread skills/dx-docs/SKILL.md

## Mandate

Assess and report by default. Apply doc fixes only when the invocation explicitly asks — and only through the repo's documented docs workflow if it has one (submodules, docs repos, review gates). Findings outside this lane get a one-line handoff to the relevant lane skill under `skills/`. Judgments come from *using* the docs and the product, never from reading them approvingly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Keep documentation audits side-effect free.

Persisting repo-profile changes here contradicts plugins/genie/workflows/council.js, which requires audit lanes to make no edits and return profile updates as data. Move persistence to the workflow’s dedicated single-writer stage.

Also applies to: 24-24

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/dx-docs/SKILL.md` at line 16, Keep the documentation audit lane
side-effect free: update the relevant audit logic associated with the documented
default assessment behavior so it returns repo-profile changes as data rather
than persisting them. Move any profile persistence into the dedicated
single-writer stage required by the council workflow, and ensure both referenced
locations follow this contract.

Comment on lines +16 to +24
Assess and report by default. Apply changes only when the invocation explicitly asks (e.g. "fix", "clean up", "apply"). When you spot a finding outside this lane (architecture, security, tests), name it in one line as a handoff to the relevant lane skill under `skills/` — do not investigate it yourself. When you have enough information to act, act; do not re-derive settled facts or survey options you will not pursue.

## Discover the Ground Truth First

Never judge against generic convention when the repo states its own. Before any verdict, read what exists of: `CLAUDE.md` / `AGENTS.md`, `README`, `CONTRIBUTING`, the package manifest, `.gitignore`, git hook tooling (husky, pre-commit, commitlint or equivalents), and CI config. These define the repo's *intended* contracts — your job is to find where reality has drifted from them, and where a contract is missing entirely. Deliberate tradeoffs documented there (bot commits, generated files kept on purpose, submodule workflows) are design, not defects.

**Genie-framework repos**: if `.genie/` exists, its contract is: `wishes/`, `brainstorms/`, and `INDEX.md` are git-tracked; `genie.db` (and WAL/SHM siblings) must be ignored. Verify with `git check-ignore` and `git ls-files .genie/`.

**Repo profile — recall, verify, persist.** Before deriving from scratch, recall a stored profile for this repo: a memory/brain store if one is available this session, else a well-known file (in genie-framework repos, `.genie/repo-profile.md`). For this lane the profile records the ignore contracts, config-to-enforcement map, commit conventions, and documented tradeoffs. Recalled anchors are hypotheses, not truth — spot-check them against current code and report drift as a finding. After the audit, persist what discovery learned back to the store: update rather than duplicate, delete what proved wrong.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Make the audit write boundary explicit.

The lane says changes require an explicit request, but then tells the agent to “act” and update/delete .genie/repo-profile.md after every audit. Clarify that persistence is the sole permitted state write, or gate it behind an explicit persist/fix request; otherwise a default review can mutate tracked repository state.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/repo-hygiene/SKILL.md` around lines 16 - 24, Clarify the write policy
in the repo-hygiene instructions: default audits must remain read-only, with
persistence as the only permitted state change unless the invocation explicitly
requests broader changes. Update the “Recall, verify, persist” section to gate
updating or deleting `.genie/repo-profile.md` behind an explicit “persist” or
“fix” request, and replace any unqualified instruction to “act” with this
boundary.

Comment on lines +16 to +22
Assess and report by default; this is a defensive audit of the user's own repo. Apply hardening only when the invocation explicitly asks. Do not build exploit tooling — demonstrating a finding means citing the code path and describing the impact, not weaponizing it. Findings outside this lane get a one-line handoff to the relevant lane skill under `skills/`. When the evidence supports a conclusion, state it.

## Discover the Ground Truth First

Enumerate before auditing. From the code, CI config, and `CLAUDE.md`/`AGENTS.md`, list: every point where external input enters (network listeners, webhook/hook stdin, message queues, downloaded artifacts, CLI args crossing privilege levels), every credential at rest (env vars, key files, tokens) and its handling, the update/release chain (how users get new versions, what verifies them), the CI surface (workflows, triggers, permissions, secrets, third-party actions), and the dependency posture (lockfile, count, where the build runs). Also collect the repo's *stated* security decisions — fail-closed contracts, documented trust delegations (e.g. "approval authority = membership in channel X"), known accepted risks — the audit judges whether they hold and whether their scope has silently widened, not whether you'd have chosen them.

**Repo profile — recall, verify, persist.** Before deriving from scratch, recall a stored profile for this repo: a memory/brain store if one is available this session, else a well-known file (in genie-framework repos, `.genie/repo-profile.md`). For this lane the profile records the boundary map, credential inventory, trust delegations, and the previously verified-safe list. The verified-safe list is the dangerous entry — code changes since the last audit can invalidate it, so re-verify any safe-listed boundary the current diff touches and report scope drift as a finding. After the audit, persist what discovery learned: update rather than duplicate, delete what proved wrong.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Make default audit persistence explicit.

The lane promises “assess and report by default” while requiring profile updates and deletion after every audit. Define profile persistence as an explicit, narrowly scoped exception or require an explicit persist/harden request; otherwise a security audit can modify repository state without user authorization.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/supply-chain/SKILL.md` around lines 16 - 22, Clarify the default
persistence behavior in the supply-chain audit instructions: either explicitly
authorize only the required repo-profile update and cleanup as a narrowly scoped
exception, or require an explicit “persist”/“harden” request before modifying
repository state. Update the sections “Assess and report by default” and “Repo
profile — recall, verify, persist” consistently.

Comment on lines +1 to +10
/**
* Tests for council-stamp.cjs: the install-time stamp that writes the /council
* workflow template into ~/.claude/workflows with LENS_ROOT resolved.
*
* The implementation is CommonJS (it is required from the ESM SessionStart
* hook), so we load it through createRequire. Everything runs inside a tmpdir;
* afterEach removes it, so no global state is touched.
*
* Run with: bun test src/lib/council-workflow-stamp.test.ts
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Colocate this test with council-stamp.cjs.

This test targets plugins/genie/scripts/council-stamp.cjs but lives under src/lib, violating the repository’s test convention and risking omission from directory-based discovery. Move it beside the implementation, for example to plugins/genie/scripts/council-stamp.test.ts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/council-workflow-stamp.test.ts` around lines 1 - 10, Move the test
currently in council-workflow-stamp.test.ts from src/lib to
plugins/genie/scripts/council-stamp.test.ts so it is colocated with the
council-stamp.cjs implementation and discovered by directory-based test runs;
preserve the existing test contents and imports, updating only any relative
paths that become invalid.

Source: Coding guidelines

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.

1 participant