Skip to content

feat(language-profile): add configurable inference modes and diagnostics#239

Merged
JustAGhosT merged 6 commits intodevfrom
plan/language-aware-generated-hooks
Mar 4, 2026
Merged

feat(language-profile): add configurable inference modes and diagnostics#239
JustAGhosT merged 6 commits intodevfrom
plan/language-aware-generated-hooks

Conversation

@JustAGhosT
Copy link
Collaborator

@JustAGhosT JustAGhosT commented Mar 4, 2026

Summary

  • Add YAML-configurable language profile controls (mode, diagnostics, inferFrom, scaffoldOverrides) and wire them through flattening/mapping/schema.
  • Update generator/template behavior to use effective language flags and diagnostics toggles across Claude/Copilot/Cursor/Windsurf surfaces.
  • Extend doctor diagnostics for configured/heuristic mode edge cases and diagnostics-off behavior.
  • Add documentation for presets and implementation tracking.

Test Plan

  • pnpm test
  • pnpm build
  • pnpm lint:md
  • pnpm -C .agentkit agentkit:sync
  • pnpm -C .agentkit agentkit:validate

Follow-up Tickets

These were created for subsequent rollout phases and are referenced for continuation:

Notes

  • Includes a non-generated docs pointer in docs/08_reference/issue_170_patch_blocks.md and discoverability updates in docs/08_reference/analysis/README.md.
  • Generated docs root index was not edited directly per generated-file policy.

Summary by CodeRabbit

  • New Features

    • Language profile system with detection modes, inference diagnostics, and scaffold override controls.
    • Language-aware conditional execution in hooks and templates.
    • New split-PR tooling and package scripts to create a dedicated sync-generated PR.
  • Documentation

    • Added language profile diagnostics to prompts/templates and published phase-plan docs.
  • Tests

    • Expanded test coverage for language profile validation, inference, and scaffold behavior.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 4, 2026

Warning

Rate limit exceeded

@JustAGhosT has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 4 minutes and 44 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: db4d661e-f8de-4377-901f-6e3e6a6aa7f3

📥 Commits

Reviewing files that changed from the base of the PR and between bcf8536 and 2b74d7e.

📒 Files selected for processing (3)
  • scripts/create-quality-issues.sh
  • scripts/sync-split-pr.ps1
  • scripts/sync-split-pr.sh

Walkthrough

Adds a language-profile system: schema and mapping entries, rich flattenProjectYaml inference, scaffold-once overrides, doctor diagnostics, template/hook conditionals, tests, docs, and CLI scripts to support language-aware generation and diagnostics.

Changes

Cohort / File(s) Summary
Core flattening & utils
.agentkit/engines/node/src/template-utils.mjs, .agentkit/engines/node/src/project-mapping.mjs
Implements language inference/config flags, scaffold override lists, new isScaffoldOnce(relPath, vars) signature, and adds multiple PROJECT_MAPPING entries for languageProfile fields.
Schema & validation
.agentkit/engines/node/src/spec-validator.mjs
Adds PROJECT_ENUMS entries and extends projectSchema with automation.languageProfile (mode, diagnostics, inferFrom, scaffoldOverrides) for enum/schema validation.
Doctor integration & templates
.agentkit/engines/node/src/doctor.mjs, .agentkit/templates/*, .github/prompts/*, template files (copilot, cursor, windsurf, language-instructions, etc.)
Doctor now emits warnings/infos about language profile mode, diagnostics, inference usage, and mismatches; templates and hooks gain conditional rendering based on effective language flags and optional diagnostics output.
Sync/sync-skip logic
.agentkit/engines/node/src/synchronize.mjs
Updated calls to pass vars into isScaffoldOnce to honor per-project scaffold override lists when deciding skip/overwrite behavior.
Tests
.agentkit/engines/node/src/__tests__/doctor.test.mjs, spec-validator.test.mjs, template-utils.test.mjs
Extends test coverage for doctor diagnostics, project.yaml enum validation, isScaffoldOnce behavior with vars, and many flattenProjectYaml inference/effective flag scenarios.
Spec file & examples
.agentkit/spec/project.yaml
Adds automation.languageProfile example block (mode, diagnostics, inferFrom, scaffoldOverrides).
Scripts & docs
scripts/*, docs/08_reference/analysis/language-aware-hooks-phase-plan.md, docs/...
Adds sync-split-pr scripts (sh/ps1), a create-quality-issues helper, extensive phase-plan documentation, and multiple prompt/template docs showing diagnostics.
Minor infra/meta
package.json, .agentkit/.markdownlintignore, .github/copilot-instructions.md
Adds new npm scripts for sync split PR flow, a markdownlint ignore rule, and updates copilot instructions with Language Profile Diagnostics and generator/version bumps.

Sequence Diagram(s)

sequenceDiagram
    participant ProjectYAML as project.yaml
    participant Validator as spec-validator
    participant Flattener as flattenProjectYaml
    participant Doctor as doctor
    participant Templates as Templates/Hooks

    ProjectYAML->>Validator: validate automation.languageProfile (enums/schema)
    Validator-->>ProjectYAML: validation result
    ProjectYAML->>Flattener: flattenProjectYaml(config)
    Flattener->>Flattener: infer languages from frameworks/tests, apply mode (configured/hybrid/heuristic)
    Flattener-->>Doctor: flattened vars (effective/inferred/source/confidence, scaffold lists)
    Doctor->>Doctor: evaluate diagnostics, mismatches, emit findings
    Doctor-->>Templates: pass findings + flattened vars
    Templates->>Templates: conditionally render hooks/prompts and scaffold decisions (hasLanguage*Effective, scaffoldOnce overrides)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Poem

🐰 I hopped through configs, sniffed each file,
JS, Python, dotnet—found them with a smile,
Modes and diagnostics waved a tiny flag,
Scaffolds obeyed the lists in my bag,
Templates danced by the rabbit's light—hooray, code generation's bright!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main feature being added: configurable language profile inference modes and diagnostics.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch plan/language-aware-generated-hooks

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 and usage tips.

@JustAGhosT JustAGhosT changed the base branch from main to dev March 4, 2026 21:10
@github-actions
Copy link

github-actions bot commented Mar 4, 2026

AgentKit Forge Source Change Detected

This PR modifies files in the AgentKit Forge source directories:

  • .agentkit/templates/ — output templates
  • .agentkit/spec/ — YAML specifications
  • .agentkit/engines/ — sync engine code
  • .agentkit/overlays/ — per-repo customizations
  • .agentkit/bin/ — CLI scripts

These are the upstream source-of-truth for all generated AI tool configs.

Review checklist

  • Changes are intentional and not accidental AI agent modifications
  • Spec schema validation passes (pnpm -C .agentkit agentkit:spec-validate)
  • Sync produces expected output (pnpm -C .agentkit agentkit:sync)
  • No secrets or credentials in template variables
  • Breaking changes documented in an ADR

AI agents: Do not modify these files directly. Propose changes in a dedicated PR.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (4)
scripts/create-quality-issues.sh (1)

75-78: Remove unused label constants on lines 75–78.

The constants LABEL_QUALITY, LABEL_DOCS, LABEL_CI, and LABEL_ENHANCEMENT are defined but never used. The subsequent ensure_label() calls on lines 86–89 use hardcoded string values instead. Either remove these constants or refactor to use them throughout the script to avoid unused variable warnings.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/create-quality-issues.sh` around lines 75 - 78, Remove the unused
label constants or use them consistently: either delete the constants
LABEL_QUALITY, LABEL_DOCS, LABEL_CI, and LABEL_ENHANCEMENT since ensure_label()
calls currently use hardcoded strings, or refactor the ensure_label(...)
invocations to reference those constants (e.g., replace literal
"quality"/"documentation"/"ci"/"enhancement" with LABEL_QUALITY, LABEL_DOCS,
LABEL_CI, LABEL_ENHANCEMENT) so the constants are actually used; update all
occurrences to keep the script warning-free and consistent around the
ensure_label function.
.agentkit/engines/node/src/synchronize.mjs (1)

1621-1624: Use normalized path for write-time scaffold checks too.

Line 1623 uses relPath while diff-mode uses normalized normPath at Line 1545. Normalizing here as well avoids cross-platform mismatch between diff vs write behavior.

Suggested patch
-      if (!overwrite && isScaffoldOnce(relPath, vars) && existsSync(destFile)) {
+      const normPath = relPath.replace(/\\/g, '/');
+      if (!overwrite && isScaffoldOnce(normPath, vars) && existsSync(destFile)) {
         skippedScaffold++;
         return;
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agentkit/engines/node/src/synchronize.mjs around lines 1621 - 1624, The
scaffold-once check is using relPath but the diff-mode earlier uses the
normalized normPath, causing inconsistent behavior across platforms; update the
check that calls isScaffoldOnce(...) to pass the normalized path (normPath)
instead of relPath (ensure normPath is in scope where used alongside
existsSync(destFile) and the overwrite flags) so write-time scaffold skips match
diff-mode decisions.
.agentkit/templates/claude/hooks/session-start.sh (1)

66-69: Avoid duplicate Python tool entries when both interpreters exist.

Line 67 and Line 68 both run unconditionally, so environments with both binaries get two “Python” entries. Use python only as fallback.

♻️ Proposed change
 {{`#if` hasLanguagePythonEffective}}
-detect_tool "Python"   "python3"
-detect_tool "Python"   "python"   # fallback if python3 is absent
+if command -v python3 &>/dev/null; then
+  detect_tool "Python" "python3"
+elif command -v python &>/dev/null; then
+  detect_tool "Python" "python"
+fi
 {{/if}}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agentkit/templates/claude/hooks/session-start.sh around lines 66 - 69, The
template currently calls detect_tool twice with the same label "Python" causing
duplicate entries when both python3 and python exist; update the conditional
around the second call so detect_tool "Python" "python" only runs as a fallback
when python3 was not detected (i.e., make the fallback conditional on the
absence of python3), keep the initial detect_tool "Python" "python3" call inside
the existing hasLanguagePythonEffective block and guard or branch the second
detect_tool call accordingly to avoid emitting two "Python" entries.
.agentkit/templates/claude/hooks/session-start.ps1 (1)

65-68: Use python only when python3 is unavailable.

Line 66 and Line 67 currently add duplicate “Python” entries on hosts where both commands exist.

♻️ Proposed change
 {{`#if` hasLanguagePythonEffective}}
-Test-Tool -Name "Python"   -Command "python3"
-Test-Tool -Name "Python"   -Command "python"
+if (Get-Command "python3" -ErrorAction SilentlyContinue) {
+    Test-Tool -Name "Python" -Command "python3"
+} elseif (Get-Command "python" -ErrorAction SilentlyContinue) {
+    Test-Tool -Name "Python" -Command "python"
+}
 {{/if}}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agentkit/templates/claude/hooks/session-start.ps1 around lines 65 - 68, The
template currently registers two identical "Python" tools unconditionally;
change the logic so Test-Tool -Name "Python" -Command "python" is only added if
python3 is not available: keep Test-Tool -Name "Python" -Command "python3" when
hasLanguagePythonEffective is true, then check for the existence of the python3
command (e.g., via Get-Command or similar) and only register the fallback
Test-Tool -Name "Python" -Command "python" when that check fails; update the
block around the hasLanguagePythonEffective conditional and the Test-Tool calls
accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.agentkit/engines/node/src/__tests__/doctor.test.mjs:
- Around line 293-462: Add a new unit test in the doctor.test.mjs suite that
calls runDoctor with a project.yaml containing automation.languageProfile.mode
set to "heuristic" and automation.languageProfile.inferFrom.frameworks: false
and inferFrom.tests: false (i.e., both inference signals disabled) to assert
that doctor.mjs emits the warning branch added around the heuristic handling
(doctor.mjs ~line 160); ensure the test mocks fs.readFileSync/existsSync and
spec-validator like the other tests and checks result.findings contains a
warning whose message references heuristic/inference signals being disabled.

In `@scripts/create-quality-issues.sh`:
- Around line 962-972: The final summary prints a hardcoded "=== All 19 issues
created successfully ===" which is misleading because the script supports
skip-on-existing behavior (the skip logic near the top of the script); change
the summary to reflect processed vs created/skipped instead of asserting all
were created — e.g., compute and display counts (created, skipped, total) and
replace the echo line "=== All 19 issues created successfully ===" with a
dynamic message like "=== Issues processed: X created, Y skipped (Total: Z) ==="
so the output accurately reflects skip behavior.

---

Nitpick comments:
In @.agentkit/engines/node/src/synchronize.mjs:
- Around line 1621-1624: The scaffold-once check is using relPath but the
diff-mode earlier uses the normalized normPath, causing inconsistent behavior
across platforms; update the check that calls isScaffoldOnce(...) to pass the
normalized path (normPath) instead of relPath (ensure normPath is in scope where
used alongside existsSync(destFile) and the overwrite flags) so write-time
scaffold skips match diff-mode decisions.

In @.agentkit/templates/claude/hooks/session-start.ps1:
- Around line 65-68: The template currently registers two identical "Python"
tools unconditionally; change the logic so Test-Tool -Name "Python" -Command
"python" is only added if python3 is not available: keep Test-Tool -Name
"Python" -Command "python3" when hasLanguagePythonEffective is true, then check
for the existence of the python3 command (e.g., via Get-Command or similar) and
only register the fallback Test-Tool -Name "Python" -Command "python" when that
check fails; update the block around the hasLanguagePythonEffective conditional
and the Test-Tool calls accordingly.

In @.agentkit/templates/claude/hooks/session-start.sh:
- Around line 66-69: The template currently calls detect_tool twice with the
same label "Python" causing duplicate entries when both python3 and python
exist; update the conditional around the second call so detect_tool "Python"
"python" only runs as a fallback when python3 was not detected (i.e., make the
fallback conditional on the absence of python3), keep the initial detect_tool
"Python" "python3" call inside the existing hasLanguagePythonEffective block and
guard or branch the second detect_tool call accordingly to avoid emitting two
"Python" entries.

In `@scripts/create-quality-issues.sh`:
- Around line 75-78: Remove the unused label constants or use them consistently:
either delete the constants LABEL_QUALITY, LABEL_DOCS, LABEL_CI, and
LABEL_ENHANCEMENT since ensure_label() calls currently use hardcoded strings, or
refactor the ensure_label(...) invocations to reference those constants (e.g.,
replace literal "quality"/"documentation"/"ci"/"enhancement" with LABEL_QUALITY,
LABEL_DOCS, LABEL_CI, LABEL_ENHANCEMENT) so the constants are actually used;
update all occurrences to keep the script warning-free and consistent around the
ensure_label function.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 420da9d1-fd6c-4d3c-87b6-4ae462266fae

📥 Commits

Reviewing files that changed from the base of the PR and between 830191a and ecb871b.

📒 Files selected for processing (43)
  • .agentkit/engines/node/src/__tests__/doctor.test.mjs
  • .agentkit/engines/node/src/__tests__/spec-validator.test.mjs
  • .agentkit/engines/node/src/__tests__/template-utils.test.mjs
  • .agentkit/engines/node/src/doctor.mjs
  • .agentkit/engines/node/src/project-mapping.mjs
  • .agentkit/engines/node/src/spec-validator.mjs
  • .agentkit/engines/node/src/synchronize.mjs
  • .agentkit/engines/node/src/template-utils.mjs
  • .agentkit/spec/project.yaml
  • .agentkit/templates/claude/hooks/session-start.ps1
  • .agentkit/templates/claude/hooks/session-start.sh
  • .agentkit/templates/claude/hooks/stop-build-check.ps1
  • .agentkit/templates/claude/hooks/stop-build-check.sh
  • .agentkit/templates/copilot/copilot-instructions.md
  • .agentkit/templates/copilot/instructions/performance.md
  • .agentkit/templates/copilot/prompts/TEMPLATE.prompt.md
  • .agentkit/templates/cursor/rules/project-context.mdc
  • .agentkit/templates/language-instructions/README.md
  • .agentkit/templates/windsurf/rules/project.md
  • .github/copilot-instructions.md
  • .github/prompts/build.prompt.md
  • .github/prompts/check.prompt.md
  • .github/prompts/cost.prompt.md
  • .github/prompts/deploy.prompt.md
  • .github/prompts/discover.prompt.md
  • .github/prompts/doctor.prompt.md
  • .github/prompts/format.prompt.md
  • .github/prompts/handoff.prompt.md
  • .github/prompts/healthcheck.prompt.md
  • .github/prompts/orchestrate.prompt.md
  • .github/prompts/plan.prompt.md
  • .github/prompts/preflight.prompt.md
  • .github/prompts/project-review.prompt.md
  • .github/prompts/review.prompt.md
  • .github/prompts/scaffold.prompt.md
  • .github/prompts/security.prompt.md
  • .github/prompts/sync-backlog.prompt.md
  • .github/prompts/test.prompt.md
  • .github/prompts/validate.prompt.md
  • docs/08_reference/analysis/README.md
  • docs/08_reference/analysis/language-aware-hooks-phase-plan.md
  • docs/08_reference/issue_170_patch_blocks.md
  • scripts/create-quality-issues.sh

Comment on lines +293 to 462
it('should report warning when language profile is inferred heuristically', async () => {
const { validateSpec } = await import('../spec-validator.mjs');
validateSpec.mockReturnValue({ valid: true, errors: [], warnings: [] });

vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
if (typeof p === 'string') {
if (p.includes('overlays') && p.includes('settings.yaml')) {
return 'renderTargets: ["claude"]';
}
if (p.endsWith('project.yaml')) {
return `
name: Test Project
description: A test
phase: active
stack:
languages: []
frameworks:
backend: [node.js]
testing:
unit: []
`;
}
}
return '';
});

vi.spyOn(fs, 'existsSync').mockReturnValue(true);

const result = await runDoctor({
agentkitRoot: mockAgentkitRoot,
projectRoot: mockProjectRoot,
});

expect(result.findings).toEqual(
expect.arrayContaining([
expect.objectContaining({
severity: 'warning',
message: expect.stringContaining('Language profile is being inferred heuristically'),
}),
])
);
});

it('should report warning when configured and inferred language profiles diverge', async () => {
const { validateSpec } = await import('../spec-validator.mjs');
validateSpec.mockReturnValue({ valid: true, errors: [], warnings: [] });

vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
if (typeof p === 'string') {
if (p.includes('overlays') && p.includes('settings.yaml')) {
return 'renderTargets: ["claude"]';
}
if (p.endsWith('project.yaml')) {
return `
name: Test Project
description: A test
phase: active
stack:
languages: [python]
frameworks:
backend: [node.js]
testing:
unit: []
`;
}
}
return '';
});

vi.spyOn(fs, 'existsSync').mockReturnValue(true);

const result = await runDoctor({
agentkitRoot: mockAgentkitRoot,
projectRoot: mockProjectRoot,
});

expect(result.findings).toEqual(
expect.arrayContaining([
expect.objectContaining({
severity: 'warning',
message: expect.stringContaining('Configured stack.languages diverges'),
}),
])
);
});

it('should report diagnostics disabled info when language profile diagnostics are off', async () => {
const { validateSpec } = await import('../spec-validator.mjs');
validateSpec.mockReturnValue({ valid: true, errors: [], warnings: [] });

vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
if (typeof p === 'string') {
if (p.includes('overlays') && p.includes('settings.yaml')) {
return 'renderTargets: ["claude"]';
}
if (p.endsWith('project.yaml')) {
return `
name: Test Project
phase: active
stack:
languages: [python]
frameworks:
backend: [node.js]
automation:
languageProfile:
diagnostics: off
`;
}
}
return '';
});

vi.spyOn(fs, 'existsSync').mockReturnValue(true);

const result = await runDoctor({
agentkitRoot: mockAgentkitRoot,
projectRoot: mockProjectRoot,
});

expect(result.findings).toEqual(
expect.arrayContaining([
expect.objectContaining({
severity: 'info',
message: expect.stringContaining('diagnostics are disabled'),
}),
])
);
});

it('should warn when configured mode is set but stack.languages is empty', async () => {
const { validateSpec } = await import('../spec-validator.mjs');
validateSpec.mockReturnValue({ valid: true, errors: [], warnings: [] });

vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
if (typeof p === 'string') {
if (p.includes('overlays') && p.includes('settings.yaml')) {
return 'renderTargets: ["claude"]';
}
if (p.endsWith('project.yaml')) {
return `
name: Test Project
phase: active
stack:
languages: []
automation:
languageProfile:
mode: configured
`;
}
}
return '';
});

vi.spyOn(fs, 'existsSync').mockReturnValue(true);

const result = await runDoctor({
agentkitRoot: mockAgentkitRoot,
projectRoot: mockProjectRoot,
});

expect(result.findings).toEqual(
expect.arrayContaining([
expect.objectContaining({
severity: 'warning',
message: expect.stringContaining('configured-only but stack.languages is empty'),
}),
])
);
});
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add a test for heuristic mode with all inference signals disabled.

doctor.mjs adds a warning branch at Line 160 (mode: heuristic + both inferFrom.frameworks/tests disabled), but this specific behavior is not covered here.

🧪 Suggested test addition
+  it('should warn when heuristic mode has all inference signals disabled', async () => {
+    const { validateSpec } = await import('../spec-validator.mjs');
+    validateSpec.mockReturnValue({ valid: true, errors: [], warnings: [] });
+
+    vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
+      if (typeof p === 'string') {
+        if (p.includes('overlays') && p.includes('settings.yaml')) {
+          return 'renderTargets: ["claude"]';
+        }
+        if (p.endsWith('project.yaml')) {
+          return `
+name: Test Project
+phase: active
+stack:
+  languages: []
+automation:
+  languageProfile:
+    mode: heuristic
+    inferFrom:
+      frameworks: false
+      tests: false
+`;
+        }
+      }
+      return '';
+    });
+    vi.spyOn(fs, 'existsSync').mockReturnValue(true);
+
+    const result = await runDoctor({ agentkitRoot: mockAgentkitRoot, projectRoot: mockProjectRoot });
+    expect(result.findings).toEqual(
+      expect.arrayContaining([
+        expect.objectContaining({
+          severity: 'warning',
+          message: expect.stringContaining('all inference signals are disabled'),
+        }),
+      ])
+    );
+  });
Based on learnings: Add tests for every behavioral change. Every behavioral change should include at least one test that would have failed before the change and passes after.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('should report warning when language profile is inferred heuristically', async () => {
const { validateSpec } = await import('../spec-validator.mjs');
validateSpec.mockReturnValue({ valid: true, errors: [], warnings: [] });
vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
if (typeof p === 'string') {
if (p.includes('overlays') && p.includes('settings.yaml')) {
return 'renderTargets: ["claude"]';
}
if (p.endsWith('project.yaml')) {
return `
name: Test Project
description: A test
phase: active
stack:
languages: []
frameworks:
backend: [node.js]
testing:
unit: []
`;
}
}
return '';
});
vi.spyOn(fs, 'existsSync').mockReturnValue(true);
const result = await runDoctor({
agentkitRoot: mockAgentkitRoot,
projectRoot: mockProjectRoot,
});
expect(result.findings).toEqual(
expect.arrayContaining([
expect.objectContaining({
severity: 'warning',
message: expect.stringContaining('Language profile is being inferred heuristically'),
}),
])
);
});
it('should report warning when configured and inferred language profiles diverge', async () => {
const { validateSpec } = await import('../spec-validator.mjs');
validateSpec.mockReturnValue({ valid: true, errors: [], warnings: [] });
vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
if (typeof p === 'string') {
if (p.includes('overlays') && p.includes('settings.yaml')) {
return 'renderTargets: ["claude"]';
}
if (p.endsWith('project.yaml')) {
return `
name: Test Project
description: A test
phase: active
stack:
languages: [python]
frameworks:
backend: [node.js]
testing:
unit: []
`;
}
}
return '';
});
vi.spyOn(fs, 'existsSync').mockReturnValue(true);
const result = await runDoctor({
agentkitRoot: mockAgentkitRoot,
projectRoot: mockProjectRoot,
});
expect(result.findings).toEqual(
expect.arrayContaining([
expect.objectContaining({
severity: 'warning',
message: expect.stringContaining('Configured stack.languages diverges'),
}),
])
);
});
it('should report diagnostics disabled info when language profile diagnostics are off', async () => {
const { validateSpec } = await import('../spec-validator.mjs');
validateSpec.mockReturnValue({ valid: true, errors: [], warnings: [] });
vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
if (typeof p === 'string') {
if (p.includes('overlays') && p.includes('settings.yaml')) {
return 'renderTargets: ["claude"]';
}
if (p.endsWith('project.yaml')) {
return `
name: Test Project
phase: active
stack:
languages: [python]
frameworks:
backend: [node.js]
automation:
languageProfile:
diagnostics: off
`;
}
}
return '';
});
vi.spyOn(fs, 'existsSync').mockReturnValue(true);
const result = await runDoctor({
agentkitRoot: mockAgentkitRoot,
projectRoot: mockProjectRoot,
});
expect(result.findings).toEqual(
expect.arrayContaining([
expect.objectContaining({
severity: 'info',
message: expect.stringContaining('diagnostics are disabled'),
}),
])
);
});
it('should warn when configured mode is set but stack.languages is empty', async () => {
const { validateSpec } = await import('../spec-validator.mjs');
validateSpec.mockReturnValue({ valid: true, errors: [], warnings: [] });
vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
if (typeof p === 'string') {
if (p.includes('overlays') && p.includes('settings.yaml')) {
return 'renderTargets: ["claude"]';
}
if (p.endsWith('project.yaml')) {
return `
name: Test Project
phase: active
stack:
languages: []
automation:
languageProfile:
mode: configured
`;
}
}
return '';
});
vi.spyOn(fs, 'existsSync').mockReturnValue(true);
const result = await runDoctor({
agentkitRoot: mockAgentkitRoot,
projectRoot: mockProjectRoot,
});
expect(result.findings).toEqual(
expect.arrayContaining([
expect.objectContaining({
severity: 'warning',
message: expect.stringContaining('configured-only but stack.languages is empty'),
}),
])
);
});
});
it('should report warning when language profile is inferred heuristically', async () => {
const { validateSpec } = await import('../spec-validator.mjs');
validateSpec.mockReturnValue({ valid: true, errors: [], warnings: [] });
vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
if (typeof p === 'string') {
if (p.includes('overlays') && p.includes('settings.yaml')) {
return 'renderTargets: ["claude"]';
}
if (p.endsWith('project.yaml')) {
return `
name: Test Project
description: A test
phase: active
stack:
languages: []
frameworks:
backend: [node.js]
testing:
unit: []
`;
}
}
return '';
});
vi.spyOn(fs, 'existsSync').mockReturnValue(true);
const result = await runDoctor({
agentkitRoot: mockAgentkitRoot,
projectRoot: mockProjectRoot,
});
expect(result.findings).toEqual(
expect.arrayContaining([
expect.objectContaining({
severity: 'warning',
message: expect.stringContaining('Language profile is being inferred heuristically'),
}),
])
);
});
it('should report warning when configured and inferred language profiles diverge', async () => {
const { validateSpec } = await import('../spec-validator.mjs');
validateSpec.mockReturnValue({ valid: true, errors: [], warnings: [] });
vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
if (typeof p === 'string') {
if (p.includes('overlays') && p.includes('settings.yaml')) {
return 'renderTargets: ["claude"]';
}
if (p.endsWith('project.yaml')) {
return `
name: Test Project
description: A test
phase: active
stack:
languages: [python]
frameworks:
backend: [node.js]
testing:
unit: []
`;
}
}
return '';
});
vi.spyOn(fs, 'existsSync').mockReturnValue(true);
const result = await runDoctor({
agentkitRoot: mockAgentkitRoot,
projectRoot: mockProjectRoot,
});
expect(result.findings).toEqual(
expect.arrayContaining([
expect.objectContaining({
severity: 'warning',
message: expect.stringContaining('Configured stack.languages diverges'),
}),
])
);
});
it('should report diagnostics disabled info when language profile diagnostics are off', async () => {
const { validateSpec } = await import('../spec-validator.mjs');
validateSpec.mockReturnValue({ valid: true, errors: [], warnings: [] });
vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
if (typeof p === 'string') {
if (p.includes('overlays') && p.includes('settings.yaml')) {
return 'renderTargets: ["claude"]';
}
if (p.endsWith('project.yaml')) {
return `
name: Test Project
phase: active
stack:
languages: [python]
frameworks:
backend: [node.js]
automation:
languageProfile:
diagnostics: off
`;
}
}
return '';
});
vi.spyOn(fs, 'existsSync').mockReturnValue(true);
const result = await runDoctor({
agentkitRoot: mockAgentkitRoot,
projectRoot: mockProjectRoot,
});
expect(result.findings).toEqual(
expect.arrayContaining([
expect.objectContaining({
severity: 'info',
message: expect.stringContaining('diagnostics are disabled'),
}),
])
);
});
it('should warn when configured mode is set but stack.languages is empty', async () => {
const { validateSpec } = await import('../spec-validator.mjs');
validateSpec.mockReturnValue({ valid: true, errors: [], warnings: [] });
vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
if (typeof p === 'string') {
if (p.includes('overlays') && p.includes('settings.yaml')) {
return 'renderTargets: ["claude"]';
}
if (p.endsWith('project.yaml')) {
return `
name: Test Project
phase: active
stack:
languages: []
automation:
languageProfile:
mode: configured
`;
}
}
return '';
});
vi.spyOn(fs, 'existsSync').mockReturnValue(true);
const result = await runDoctor({
agentkitRoot: mockAgentkitRoot,
projectRoot: mockProjectRoot,
});
expect(result.findings).toEqual(
expect.arrayContaining([
expect.objectContaining({
severity: 'warning',
message: expect.stringContaining('configured-only but stack.languages is empty'),
}),
])
);
});
it('should warn when heuristic mode has all inference signals disabled', async () => {
const { validateSpec } = await import('../spec-validator.mjs');
validateSpec.mockReturnValue({ valid: true, errors: [], warnings: [] });
vi.spyOn(fs, 'readFileSync').mockImplementation((p) => {
if (typeof p === 'string') {
if (p.includes('overlays') && p.includes('settings.yaml')) {
return 'renderTargets: ["claude"]';
}
if (p.endsWith('project.yaml')) {
return `
name: Test Project
phase: active
stack:
languages: []
automation:
languageProfile:
mode: heuristic
inferFrom:
frameworks: false
tests: false
`;
}
}
return '';
});
vi.spyOn(fs, 'existsSync').mockReturnValue(true);
const result = await runDoctor({
agentkitRoot: mockAgentkitRoot,
projectRoot: mockProjectRoot,
});
expect(result.findings).toEqual(
expect.arrayContaining([
expect.objectContaining({
severity: 'warning',
message: expect.stringContaining('all inference signals are disabled'),
}),
])
);
});
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agentkit/engines/node/src/__tests__/doctor.test.mjs around lines 293 - 462,
Add a new unit test in the doctor.test.mjs suite that calls runDoctor with a
project.yaml containing automation.languageProfile.mode set to "heuristic" and
automation.languageProfile.inferFrom.frameworks: false and inferFrom.tests:
false (i.e., both inference signals disabled) to assert that doctor.mjs emits
the warning branch added around the heuristic handling (doctor.mjs ~line 160);
ensure the test mocks fs.readFileSync/existsSync and spec-validator like the
other tests and checks result.findings contains a warning whose message
references heuristic/inference signals being disabled.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
scripts/sync-split-pr.ps1 (1)

36-37: Prefer pipeline-friendly output cmdlets over Write-Host.

Use Write-Information/Write-Verbose (or Write-Output) so output can be redirected/suppressed consistently in automation contexts.

Proposed fix
-Write-Host 'Running sync...'
+Write-Information 'Running sync...' -InformationAction Continue
@@
-  Write-Host 'No sync-generated changes detected.'
+  Write-Information 'No sync-generated changes detected.' -InformationAction Continue
@@
-Write-Host "Detected $filesCount changed file(s) from sync."
+Write-Information "Detected $filesCount changed file(s) from sync." -InformationAction Continue
@@
-  Write-Host 'Dry run enabled; not creating branch/commit/PR.'
+  Write-Information 'Dry run enabled; not creating branch/commit/PR.' -InformationAction Continue
@@
-Write-Host "Created PR: $prUrl"
+Write-Information "Created PR: $prUrl" -InformationAction Continue

Also applies to: 41-42, 47-47, 50-51, 70-70

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/sync-split-pr.ps1` around lines 36 - 37, Replace all uses of
Write-Host (e.g., the "Running sync..." message and the other Write-Host
occurrences noted) with a pipeline-friendly cmdlet such as Write-Information or
Write-Output (or Write-Verbose if these are diagnostic messages) so output can
be redirected/suppressed in automation; update each occurrence (the "Running
sync..." message and the other Write-Host lines around the pnpm calls) to call
Write-Information/Write-Output and, if using Write-Information, include an
appropriate -InformationAction or switch (or use Write-Verbose and call
[CmdletBinding()] with Param()/$VerbosePreference) so behavior is consistent in
CI and scripts.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/sync-split-pr.ps1`:
- Around line 21-24: Add an upfront command validation step that ensures
required CLI tools exist before any branch creation/push occurs: check presence
of git, pnpm, and gh (e.g., via Get-Command or Test-Path on their executables)
at the start of the script and exit with a clear error if any are missing; keep
the existing working-tree cleanliness check ($status) but move or augment it
after the command checks so the script never creates or pushes a branch (the
code that runs 'git checkout -b' / push and invokes 'gh pr create') when
prerequisites are absent.

In `@scripts/sync-split-pr.sh`:
- Around line 12-27: The flag handlers for --base, --branch, --commit-message,
and --pr-title currently assign "${2:-}" and then blindly shift 2, which allows
empty values and causes a cryptic shift error; update each case branch to check
that "$2" exists and is non-empty before assigning to BASE_BRANCH, NEW_BRANCH,
COMMIT_MESSAGE, and PR_TITLE (respectively) and before executing shift 2, and if
the value is missing print a clear usage/error message and exit with non-zero
status so the script fails fast with an actionable message.
- Around line 55-58: Add an early dependency check for the required CLIs (git,
pnpm, gh) at the top of the script before the existing working-tree cleanliness
check (the block that runs git status --porcelain) so the script exits fast if
any are missing; also add the same pre-check immediately before the branch
creation/PR flow (the section that creates/pushes a branch and calls gh to
create a PR) to avoid creating a remote branch when gh is not available.
Implement the check by testing each binary (e.g., using command -v or which) and
printing a clear error for the missing tool and exiting nonzero if any are
absent.

---

Nitpick comments:
In `@scripts/sync-split-pr.ps1`:
- Around line 36-37: Replace all uses of Write-Host (e.g., the "Running sync..."
message and the other Write-Host occurrences noted) with a pipeline-friendly
cmdlet such as Write-Information or Write-Output (or Write-Verbose if these are
diagnostic messages) so output can be redirected/suppressed in automation;
update each occurrence (the "Running sync..." message and the other Write-Host
lines around the pnpm calls) to call Write-Information/Write-Output and, if
using Write-Information, include an appropriate -InformationAction or switch (or
use Write-Verbose and call [CmdletBinding()] with Param()/$VerbosePreference) so
behavior is consistent in CI and scripts.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3b4b4fb1-8abd-44d4-b12e-9d7efa791b8a

📥 Commits

Reviewing files that changed from the base of the PR and between ecb871b and bcf8536.

📒 Files selected for processing (7)
  • .agentkit/.markdownlintignore
  • docs/06_engineering/08_sync_split_pr_workflow.md
  • docs/08_reference/issue_170_patch_blocks.md
  • docs/history/issues/TEMPLATE-issue.md
  • package.json
  • scripts/sync-split-pr.ps1
  • scripts/sync-split-pr.sh
✅ Files skipped from review due to trivial changes (4)
  • docs/history/issues/TEMPLATE-issue.md
  • docs/06_engineering/08_sync_split_pr_workflow.md
  • .agentkit/.markdownlintignore
  • docs/08_reference/issue_170_patch_blocks.md

@JustAGhosT JustAGhosT merged commit 1383ff4 into dev Mar 4, 2026
13 checks passed
@JustAGhosT JustAGhosT deleted the plan/language-aware-generated-hooks branch March 4, 2026 22:01
@JustAGhosT
Copy link
Collaborator Author

Tracking note: markdownlint prevention is being handled in #242.

This PR had markdownlint-related context, and follow-up hardening for templates + future changes is centralized here:
#242

JustAGhosT added a commit that referenced this pull request Mar 5, 2026
…ics (#239)

* fix(claude-hooks): make session-start cross-platform and detect gh

* feat(language-profile): add configurable inference modes and diagnostics

* chore(sync): add split-pr helpers and telemetry workflow docs

* fix(scripts): report created vs skipped quality issues

* fix(sync): harden prereq checks and argument handling
JustAGhosT added a commit that referenced this pull request Mar 5, 2026
…#284)

* feat(features): add kit feature management strategy for adopting repos

Enable repos implementing agentkit-forge to opt-in/opt-out of specific
kit features through a declarative feature management system integrated
into the template generation engine.

New files:
- spec/features.yaml: canonical registry of 20 features across 7
  categories (core, workflow, quality, docs, security, infra, advanced)
  with 4 named presets (minimal, standard, full, lean)
- engines/node/src/feature-manager.mjs: feature resolution engine with
  dependency tracking, preset expansion, template var generation, and
  CLI handlers (features list/enable/disable/preset)

Modified files:
- cli.mjs: add `features` command with enable/disable/preset sub-actions
- init.mjs: add feature selection phase (Phase 5.5) to interactive
  wizard with preset and custom modes; wire feature presets to init
  presets (minimal/full/team/infra)
- synchronize.mjs: load features.yaml, resolve enabled features, and
  merge feature template vars (e.g., hasTeamOrchestration,
  hasQualityGates) into the rendering pipeline
- spec-validator.mjs: validate features.yaml structure, dependencies,
  cycles, and preset references
- overlays/__TEMPLATE__/settings.yaml: add featurePreset field and
  commented enabledFeatures example

https://claude.ai/code/session_01NQfKaGKkx5jHwmxwnNmvNz

* docs(features): address review gaps — presets, dependencies, conflicts, migration

Addresses all four suggestions from the AI evaluation (7/10 → target 9/10):

S1 (high): Expand presets with explicit feature-to-preset mappings
- Add ASCII comparison table showing features × presets at a glance
- Add one-sentence use-case and "best for" guidance per preset
- Show feature count per preset (e.g., "5 features", "12 features")
- Verbose CLI output now lists each preset's feature IDs

S2 (high): Expand dependency/conflict/precedence documentation
- feature-manager.mjs module-level JSDoc documents full overlay precedence
  chain (enabledFeatures > featurePreset > defaults), conflict resolution
  rules, and schema versioning contract
- resolveFeatures() JSDoc documents all 7 resolution steps with conflict
  semantics (disabledFeatures wins over enabledFeatures, alwaysOn survives all)
- validateFeatureSpec() now checks: valid categories, templateVar naming,
  preset label/description, redundant alwaysOn in presets, missing transitive
  deps in presets, and documents all checks in JSDoc
- validateOverlayFeatures() now detects: enabledFeatures+featurePreset
  conflict, features in both enabled+disabled lists, dependency breakage
  from disabled features
- Add SUPPORTED_SCHEMA_VERSION constant and forward-compat warning in
  loadFeatureSpec()
- Verbose CLI now shows dependency graph and standalone feature count

S3 (medium): Concrete template conditionals and expected output
- features.yaml header now includes {{#if}}/{{#unless}} template examples
  showing nesting, feature gating, and fallback patterns
- Includes expected generated output comparison for standard vs lean vs
  minimal presets showing which sections appear/disappear

S4: Migration/upgrade guidance
- features.yaml header documents behavior for new features (default:false
  is opt-in, default:true auto-enables for default-mode repos, explicit
  list repos are unaffected, preset repos follow preset changes)
- Documents schema versioning and pinning strategy

https://claude.ai/code/session_01NQfKaGKkx5jHwmxwnNmvNz

* feat(features): add feature-aware agents, commands, and sync-time gating

- Add feature-ops agent to agents.yaml under new feature-management category
- Add 3 feature management commands: feature-review, feature-configure, feature-flow
- Create command templates for all 3 feature commands with detailed workflows
- Add requiredFeature field to commands.yaml spec and wire to existing commands
  (orchestrate, healthcheck, review, check, handoff, project-review, scaffold)
- Add aggregate template vars: enabledFeaturesList, enabledFeaturesCount,
  totalFeaturesCount, featureSummary for agent/command template consumption
- Wire isFeatureGated() into all sync functions (Claude, Cursor, Windsurf,
  Copilot, Agents SDK) so commands gated by a disabled feature are skipped

https://claude.ai/code/session_01NQfKaGKkx5jHwmxwnNmvNz

* feat(features): comprehensive feature gating across sync pipeline and templates

File-level gating in synchronize.mjs:
- Gate team generation (commands, rules, chatmodes) behind team-orchestration
  across Claude, Cursor, Windsurf, and Copilot sync functions
- Gate agent generation behind agent-personas for Claude and Copilot
- Move docs/, GitHub CI, and renovate out of always-on block — gate behind
  doc-scaffolding, ci-automation, and dependency-management respectively
- Replace wholesale hooks copy with per-file syncClaudeHooks() using
  HOOK_FEATURE_MAP: stop-build-check→quality-gates,
  protect-sensitive→sensitive-file-protection, guard-destructive→permission-guards
- Gate rules directories and language instructions behind coding-rules
  for all platforms (Claude, Cursor, Windsurf, Copilot, Cline, Roo)
- Double-gate MCP/A2A config behind both render target and mcp-integration
- Add isFeatureEnabled() helper for cleaner feature checks

Content-level gating in templates:
- CLAUDE.md: wrap Quick Reference table entries, Team Commands section,
  and Session Flow with feature conditionals (hasSlashCommands,
  hasTeamOrchestration, hasQualityGates, hasCodeReview, hasSessionHandoff)
- AGENTS.md: wrap Documentation section with hasDocScaffolding, Agent Teams
  section with hasTeamOrchestration, quality/handoff references with their
  respective feature guards

https://claude.ai/code/session_01NQfKaGKkx5jHwmxwnNmvNz

* feat(merge): add automated merge conflict resolution system

Add a multi-layered merge conflict resolution system:

1. Custom git merge drivers in .gitattributes — auto-resolves ~80% of
   conflicts on generated/framework-managed files by accepting upstream.

2. Sync engine integration — syncGitattributes() appends managed merge
   driver rules to .gitattributes (preserving user EOL config) on every
   agentkit sync, so downstream repos inherit merge drivers automatically.

3. Executable resolution scripts (sh + ps1) — scripts/resolve-merge.sh
   codifies the merge resolution matrix: auto-resolves generated files,
   lockfiles, and configs; flags engine/spec files for manual review.

4. GitHub Actions workflow — merge-conflict-detection.yml triggers on
   pushes to dev/main, checks all open PRs for conflicts, and posts
   categorised PR comments with resolution instructions.

5. CLAUDE.md template policy — teaches Claude Code the merge resolution
   matrix so it resolves conflicts automatically without manual prompting.

https://claude.ai/code/session_01CTigWAqvS1WmKfBG6yVG2x

* feat(doctor+ci): add merge driver health checks

- doctor.mjs now checks .gitattributes for managed merge driver section
  markers and merge=agentkit-generated rules, and verifies the local git
  config has the driver activated
- ci.yml validate job now explicitly checks .gitattributes merge driver
  rules are present and runs doctor diagnostics before the drift check

https://claude.ai/code/session_01CTigWAqvS1WmKfBG6yVG2x

* fix(features): address review feedback — naming, gating, tests, validation

1. Split Cline/Roo target entry from coding-rules gate (targets are
   entered regardless, only rule sync is feature-gated)
2. Rename isFeatureGated → isItemFeatureEnabled (consistent positive
   naming with isFeatureEnabled, eliminates confusing inverted semantics)
3. Rename syncEditorConfigs → syncRenovateConfig (was misleading —
   only copies renovate.json, not editor configs)
4. Derive hook→feature mapping dynamically from features.yaml
   affectsTemplates via buildHookFeatureMap() instead of static
   HOOK_FEATURE_MAP constant (prevents silent breakage on feature renames)
5. Fix runFeatureEnable/Disable to delete featurePreset when switching
   to explicit mode (prevents validator warning about conflicting config)
6. Fix CLAUDE.md template conditional formatting (remove extra blank
   lines between {{/if}} closers)
7. Add 57 unit tests for feature-manager.mjs covering resolveFeatures,
   buildFeatureVars, buildHookFeatureMap, validateFeatureSpec,
   validateOverlayFeatures, validateAffectsTemplates, loadFeatureSpec,
   and integration tests with real features.yaml
8. Add validateAffectsTemplates() to verify feature affectsTemplates
   paths reference real template files/directories; integrated into
   spec-validator pipeline

https://claude.ai/code/session_01NQfKaGKkx5jHwmxwnNmvNz

* feat(commands): add command-specific prompts to slash command generation

Previously, Copilot, Cursor, Codex, and Windsurf slash commands were
generated using a single generic template that produced identical
boilerplate for every command. The rich behavioral instructions from
Claude command templates (review criteria, check sequences, security
audit categories, deployment safety rules, etc.) were lost for all
non-Claude platforms.

Changes:
- Add `prompt` field to all 20 non-team commands in commands.yaml with
  condensed behavioral instructions extracted from Claude templates
- Add `commandPrompt` to buildCommandVars() in synchronize.mjs
- Update Copilot, Cursor, Codex, and Windsurf templates to render
  command-specific content via {{#if commandPrompt}} conditional blocks,
  falling back to the generic body for commands without a prompt
- Fix formatting on pre-existing unformatted docs

https://claude.ai/code/session_01RpddU57pqGgRrrmdTJCn3Z

* docs(issue): add maintenance-coordinator agent proposal and gap audit

Comprehensive issue documenting 6 gaps, 3 contradictions, and 4
integration opportunities found during agent/hooks/CLI/CI audit.
Proposes a maintenance-coordinator agent to consolidate ownership
of rules.yaml, scripts/, CLI completeness, and tech debt tracking.

https://claude.ai/code/session_01CTigWAqvS1WmKfBG6yVG2x

* fix(templates): add prettierignore for templates, stateDir variable, and fix flaky test

- Add .agentkit/templates/**/*.{md,mdc} to .prettierignore to prevent
  Prettier from reformatting Handlebars {{/if}} tags inconsistently
- Add .test-validate to .prettierignore to fix flaky prettier test caused
  by race condition with validate edge-case tests creating unformatted files
- Add {{stateDir}} template variable to buildCommandVars() with platform-
  specific defaults (.claude/state, .cursor/state, .windsurf/state,
  .github/state, .agents/state) so command prompts render correct paths
- Replace hardcoded .claude/state paths in commands.yaml with {{stateDir}}
- Fix {{/if}} indentation to be flush-left in codex, copilot, and cursor
  templates to avoid injecting whitespace into rendered output

https://claude.ai/code/session_01RpddU57pqGgRrrmdTJCn3Z

* feat(agents): add cross-agent integration engine for testing, docs, security, and quality

Address 8 testing integration gaps and additional agent coordination gaps:

Gap 1: Wire up `notifies` field from agents.yaml — create review tasks
       for notified agents when engineering tasks complete
Gap 2: Auto-create test tasks for team-testing after engineering completion
Gap 3: Add coverage threshold enforcement to check.mjs (--coverage flag)
Gap 4: Auto-trigger integration tests when both backend+frontend complete
Gap 5: Add coverage delta checking to review-runner.mjs
Gap 6: Add incremental test validation instructions between Phase 3 rounds
Gap 7: Route test/quality failures to testing team in Phase 4
Gap 8: Validate test acceptance criteria on task completion

Additional agent gaps addressed:
- Auto-create documentation tasks for teams with docs in handoff-chain
- Auto-create security review tasks for teams with security in handoff-chain
- Auto-create dependency audit tasks when lock files change
- Auto-create quality review tasks (testing→quality handoff-chain)

New files:
- agent-integration.mjs: Cross-agent notification, auto-delegation, coverage,
  and acceptance criteria validation engine
- agent-integration.test.mjs: 53 tests covering all integration functions

Modified files:
- orchestrator.mjs: processCompletedTask(), routePhase4TestFailure(), re-exports
- check.mjs: Coverage threshold checking, --coverage flag support
- review-runner.mjs: Coverage delta check step after TODO scan
- orchestrate.md: Phase 3 cross-agent integration, Phase 4 test routing

https://claude.ai/code/session_01NQfKaGKkx5jHwmxwnNmvNz

* docs(issues): break out 12 sub-issues with detailed implementation plans

Each issue includes: problem statement, step-by-step implementation plan
with code samples, acceptance criteria, and cross-references.

Gaps:
- 001: 6 missing CLI handlers (build, test, format, deploy, security, sync-backlog)
- 002: maintenance-coordinator agent definition
- 003: task delegation lifecycle completion
- 004: rules.yaml ownership and governance
- 005: script agent ownership mapping
- 006: 8 CLI commands missing from spec (reverse mismatch)

Contradictions:
- 007: team context routing undefined
- 008: check.mjs allowlists not in spec

Integration opportunities:
- 009: doctor.mjs into healthcheck + pre-sync
- 010: security command extending review-runner
- 011: hook executable/shebang validation
- 012: CI per-commit secret scanning

https://claude.ai/code/session_01CTigWAqvS1WmKfBG6yVG2x

* fix(templates): add commandPrompt to Claude skills, stateDir tests, and fix flaky prettier

- Add {{#if commandPrompt}} conditional to Claude skills template so
  Claude's own skills render the rich command prompts from commands.yaml
- Add integration tests verifying {{stateDir}} resolves correctly for
  each platform: .claude/state, .cursor/state, .github/state, .agents/state
- Add test verifying Claude skills render commandPrompt content and
  exclude the generic fallback instructions
- Fix flaky prettier test by retrying on exit code 2 (transient internal
  error from parallel test file creation/deletion during prettier scan)

https://claude.ai/code/session_01RpddU57pqGgRrrmdTJCn3Z

* fix: address code review findings — circular imports, bugs, coverage, glob matching

- Extract appendEvent/readEvents into standalone events.mjs to break
  circular dependency between orchestrator.mjs and agent-integration.mjs
- Remove redundant TERMINAL_STATES check in autoCreateIntegrationTestTask
- Fix resolveCoverageCommand to detect actual runner from package.json
  for generic pnpm test/npm test commands instead of assuming vitest
- Hoist loadCoverageThreshold above per-stack loop in check.mjs
- Make review-runner.mjs coverage opt-in (flags.coverage === true)
  instead of opt-out to align with check.mjs behavior
- Replace simplistic glob matching with proper matchGlob that handles
  ** with extension filters (e.g. src/**/*.ts no longer matches .rs)
- Extract shared trackTaskInState/cloneState helpers in orchestrator.mjs
- Fix Phase 4 step numbering (was 1-6,5,6 → now 1-8)
- Register --coverage flag in CLI parseArgs for check and review commands
- Fix autoCreateDocTask to skip when changedFiles array is empty
- Add 16 new tests: integration test triggering, dependency audit in
  processTaskCompletion, doc task empty-files edge case, coverage
  command detection with projectRoot, glob matching correctness

https://claude.ai/code/session_01NQfKaGKkx5jHwmxwnNmvNz

* chore(sync): regenerate Copilot prompts with rich commandPrompt content

Re-run sync to update .github/prompts/ files after the commandPrompt
template fix. All 19 prompt files now render full command-specific
instructions instead of the generic 5-line fallback.

https://claude.ai/code/session_01RpddU57pqGgRrrmdTJCn3Z

* chore(sync): regenerate Copilot agents and root docs after template fix

Sync output for .github/agents/ and root docs (AGENTS.md, COMMAND_GUIDE.md)
was stale after the commandPrompt template changes.

https://claude.ai/code/session_01RpddU57pqGgRrrmdTJCn3Z

* style: apply prettier formatting to align with dev branch standards

https://claude.ai/code/session_01NQfKaGKkx5jHwmxwnNmvNz

* fix(sync): resolve merge conflict — keep both syncGitattributes and syncEditorTheme

The conflict between our branch and dev was:
- Ours: added syncGitattributes() for merge driver .gitattributes management
- Theirs: added syncEditorTheme() for brand-driven editor color customization

Resolution: keep BOTH functions since they serve independent purposes.
- syncGitattributes: manages merge driver entries in .gitattributes
- syncEditorTheme: resolves brand.yaml colors into editor settings.json

Also adds brand-resolver.mjs (from dev) and brand identity injection in
template vars, plus prettier formatting for issue files.

https://claude.ai/code/session_01CTigWAqvS1WmKfBG6yVG2x

* feat(commands): add /sync command for cross-platform config regeneration

Add a sync command to commands.yaml so agents on any platform (Claude,
Cursor, Copilot, Windsurf, Codex, etc.) can invoke /sync to regenerate
AI tool configurations from the AgentKit Forge spec.

Also fix validate.test.mjs imports that were dropped by the linter
(spawnSync, PRETTIER_BIN).

https://claude.ai/code/session_01RpddU57pqGgRrrmdTJCn3Z

* fix(review): address all code review findings

1. Fix agentDomainRules regression — restore domain-rules reading from
   agent spec instead of hardcoding empty string. Agents with domain-rules
   will now correctly render them in generated templates.

2. Restore brand-resolver tests (405 lines) — brand-resolver.test.mjs was
   deleted during merge; tests cover resolveColor, resolveThemeMapping,
   validateBrandSpec, and mergeThemeIntoSettings.

3. Restore editor theme integration tests (134 lines) — sync-integration
   tests for syncEditorTheme verify colorCustomizations generation, brand
   metadata sentinel, and user key preservation.

4. Add syncGitattributes tests (4 tests) — covers managed section
   generation, file pattern inclusion, user content preservation across
   re-syncs, and no-duplication on repeated syncs.

5. Restore spec files from dev — brand.yaml, editor-theme.yaml, overlay
   variants, project.yaml fields, agents.yaml (full brand-guardian with
   domain-rules/conventions/anti-patterns/examples), commands.yaml (brand
   command), and brand.md template. syncEditorTheme is no longer dead code.

6. Document syncGitattributes always-on behavior — added comment explaining
   why .gitattributes sync runs even with --only flag (repo-wide infra,
   not tool-specific).

All 565 tests pass across 23 test files.

https://claude.ai/code/session_01CTigWAqvS1WmKfBG6yVG2x

* fix(tests): extract prettier test, add Windsurf stateDir coverage, document issues

- Extract prettier check into dedicated prettier.test.mjs to prevent
  linter from stripping spawnSync import (happened twice this session)
- Add Windsurf stateDir integration test (.windsurf/state) — completes
  coverage for all 5 major platforms
- Fix stale comment referencing "19 commands" (now dynamic wording)
- Add platform tool restriction note to /sync command prompt
- Document follow-up issues (linter guard, parameterized stateDir tests)

https://claude.ai/code/session_01RpddU57pqGgRrrmdTJCn3Z

* fix: address all review findings — dead code, perf, logging, tests

Major fixes:
- Remove duplicate syncRenovateConfig (dead code after merge)
- Restore hookFeatureMap feature-aware filtering in Claude sync
  (was regressed to plain syncDirectCopy by merge)
- Add runtime warning when dependency resolution overrides
  explicit disabledFeatures entries
- Fix fragile vitest matching in resolveCoverageCommand
  (handle bare `vitest` without `run`)

Performance:
- processTaskCompletion now loads tasks once and passes to all
  8 sub-functions (was 8 separate disk reads)
- Cache compiled regex in matchGlob via Map (was recompiling
  per file per scope pattern)

Quality:
- Replace console.warn with log callback in loadFeatureSpec
  and resolveFeatures for consistency
- Make events.mjs appendEvent properly async (was sync with
  misleading await at call sites)
- Add 12 CLI handler integration tests (runFeatures,
  runFeatureEnable, runFeatureDisable, runFeaturePreset)
- Add 2 dependency resurrection warning tests

https://claude.ai/code/session_01NQfKaGKkx5jHwmxwnNmvNz

* fix: resolve Phase 4 merge conflict — combine both branches

Merge resolution for orchestrate.md Phase 4 Validation section:
- Keep our branch: cross-agent task verification (step 2),
  coverage threshold enforcement (step 3), test failure routing
  (step 5/6), expanded retry policy documentation
- Add dev branch: feature-gated infra-eval step via
  {{#if hasInfraEval}} conditionals with dynamic step numbering
- Add infra-eval feature to features.yaml (category: infra,
  default: false) with hasInfraEval templateVar
- Add infra-eval to the "full" preset

https://claude.ai/code/session_01NQfKaGKkx5jHwmxwnNmvNz

* feat(issues): add structured issue forms with area, priority, severity, phase, and impact fields

Convert issue templates from Markdown to GitHub YAML issue forms with
validated dropdown fields. Add feature request template alongside the
existing bug report. New fields (area, priority, severity, phase, impact)
use preset values derived from teams.yaml and project.yaml enums.

Changes:
- Replace .github/ISSUE_TEMPLATE/bug_report.md with bug_report.yml (YAML form)
- Add .github/ISSUE_TEMPLATE/feature_request.yml with matching fields
- Add .github/ISSUE_TEMPLATE/config.yml (disable blank issues, link security advisories)
- Add .github/workflows/issue-label-validation.yml (validates fields on issue open/edit,
  auto-applies area:/priority:/severity: labels)
- Update .agentkit/templates/github/ISSUE_TEMPLATE/ source templates
- Add issueArea, issuePriority, issueSeverity, issueImpact enums to spec-validator
- Add Phase 9 to validate.mjs: validates issue template dropdown values against enums

https://claude.ai/code/session_01Ue9aaiqqt1iHDx8KNwQ92m

* feat(teams): integrate issue template fields with agent teams routing and task protocol

Wire the new issue area/priority/severity/impact fields into the agent
teams orchestration pipeline so issues flow through to the right teams
automatically.

Changes:
- task-protocol: add area, severity fields to task schema with validation,
  filtering, and display; extend TASK_PRIORITIES to include P4
- orchestrator: add resolveTeamByArea() for area→team routing using
  teams.yaml intake.routing; add computeEscalation() for dynamic
  escalation based on severity + impact + area
- review-runner: normalize severity values to canonical lowercase
  (critical/high/medium/low) matching issue templates; export
  normalizeSeverity() helper
- sync-backlog template: add area labels table, severity levels,
  escalation rules, source tracking, and P4 priority level
- sync-backlog prompt: add issue field routing table and escalation rules
  for Copilot prompt
- teams.yaml: add cli→backend and sync-engine→devops intake routing

https://claude.ai/code/session_01Ue9aaiqqt1iHDx8KNwQ92m

* feat(templates): unify issue field enums across all platform templates and flows

Ensure consistent area/priority/severity values in GitHub issue filing,
Linear issue filing, and all platform command templates (Copilot, Cursor,
Windsurf, Codex).

Changes:
- review.md: normalize severity from CRITICAL/HIGH/MEDIUM/LOW to canonical
  lowercase (critical/high/medium/low); add area field to issue filing with
  file-path→area mapping; use structured labels (severity:X, area:X, priority:X)
  for both GitHub and Linear
- project-review.md: same severity normalization and structured label format;
  add area field to Phase 1c findings; add canonical field reference section
- Copilot TEMPLATE.prompt.md: add issue field routing section with area→team
  mapping, priority/severity enums, and escalation rules
- Cursor TEMPLATE.md: same routing section added
- Windsurf command.md: same routing section added
- Codex SKILL.md: same routing section added

All platforms now reference identical:
  - Area values (12 canonical values from teams.yaml)
  - Priority levels (P0–P4)
  - Severity levels (critical/high/medium/low)
  - Escalation rules (severity+area→security teams, impact+P0→product)

https://claude.ai/code/session_01Ue9aaiqqt1iHDx8KNwQ92m

* feat(branch-protection): expand setup scripts with code scanning, Copilot review, and merge settings

Add configurable branchProtection section to project.yaml covering:
- Code scanning rulesets (CodeQL thresholds via GitHub Rulesets API)
- Copilot automated code review (auto-request, new pushes, draft PRs)
- Merge strategies (squash/rebase/merge toggle, auto-delete, auto-merge)
- Signed commits requirement
- Merge queue configuration
- Previously hardcoded flags now configurable (enforceAdmins, requireLastPushApproval)

Update project-mapping.mjs with bp* template variables and add 'array'
transform type for status checks and code scanning tool lists.

Both .sh and .ps1 templates updated with conditional sections that
activate based on project.yaml configuration.

https://claude.ai/code/session_011Vp3WAEEQToMVkpdjNcimB

* chore: update package-lock.json

https://claude.ai/code/session_011Vp3WAEEQToMVkpdjNcimB

* feat(cost): add budget-guard module with circuit breaker logic

Initial implementation of the enforcement layer for cost management.
Provides session and daily budget checks with configurable thresholds,
warning/deny statuses, and hook integration points. This addresses
the recent incident where agent usage spiraled without limits.

https://claude.ai/code/session_01TdK27Dqh4JPrSqjCEUtCP2

* docs(cost): comprehensive cost management infrastructure plan

Detailed analysis and implementation plan covering:
- Budget-guard circuit breaker (agentkit-forge)
- Azure Budget Terraform resources (ai-gateway)
- Cost centre management with ADX/KQL (pvc-costops-analytics)
- Agent augmentation strategy (infra, data-analyst, architect)
- Template and overlay changes for FinOps integration
- 5-wave execution sequence with priority assignments

Addresses the recent agent usage spiral incident by designing
enforcement at three layers: session-level, gateway-level, and
Azure resource-level budgets.

https://claude.ai/code/session_01TdK27Dqh4JPrSqjCEUtCP2

* feat(cost): wire budget-guard circuit breaker, finops rules, and cost-centres command

- Fix budget-guard.mjs: replace broken async imports with sync
  createRequire and top-level appendFileSync import
- Add 27 tests for budget-guard (policy loading, session/daily checks,
  hook integration, CLI status)
- Create budget-guard-check.sh PreToolUse hook for Bash|Write|Edit
- Add budgetPolicy section to settings.yaml (warn mode, session+daily limits)
- Wire budget-guard-check hook as first preToolUse matcher
- Augment infra agent: consumption budgets, cost-center enforcement,
  cost impact assessment before provisioning
- Augment data agent: cost attribution dashboards, cost-centre reporting,
  anomaly monitoring; add adx/** and grafana/** to focus
- Add finops rule domain (7 rules): phased-delivery, reference-tables,
  tag-safety, audit-reversibility, cost-centre-governance,
  adx-alternatives, budget-approval
- Create /cost-centres slash command template with list/show/create/
  budget/map/unmap/status/unbudgeted/audit actions
- Register cost-centres command in commands.yaml with flags
- Add --budget flag to /cost command
- Populate pvc-costops-analytics overlay: enable finops domain,
  enforce tag-safety and audit-reversibility as critical,
  enable cost-centres and infra-eval commands

https://claude.ai/code/session_01TdK27Dqh4JPrSqjCEUtCP2

* chore(sync): regenerate outputs after cost-management spec changes

Sync-generated files from spec changes:
- .github/agents/data.agent.md — updated data agent focus and responsibilities
- .github/agents/infra.agent.md — updated infra agent cost responsibilities
- .github/instructions/languages/finops.md — new finops rule domain
- .github/scripts/setup-branch-protection.ps1 — updated command list

https://claude.ai/code/session_01TdK27Dqh4JPrSqjCEUtCP2

* docs(cost): add GitHub issue specs for waves 3-5

Three issue specifications for downstream work:
- Wave 3 (ai-gateway): Azure Budget Terraform, usage telemetry,
  spend cap middleware, dashboard enhancements
- Wave 4 (pvc-costops-analytics): cost centre tables (ADX + Log
  Analytics dual backend), KQL functions, Grafana dashboards,
  management scripts, Azure Policy, anomaly detection
- Wave 5 (cross-repo): end-to-end telemetry pipeline, budget alert
  webhooks, monthly review automation, budget approval workflow
  via GitHub Issues, cost governance runbook

Decision records embedded: per-API-key spend caps, 1:N cost centre
mapping, custom KQL with ADX+Log Analytics dual backend, audit-first
tag enforcement, GitHub Issues for budget approval.

https://claude.ai/code/session_01TdK27Dqh4JPrSqjCEUtCP2

* fix: address review findings — correctness, tests, DRY, performance, robustness

Required fixes:
- review.md: fix uppercase "CRITICAL→P0, HIGH→P1" to lowercase "critical→P0, high→P1"
- validate.mjs Phase 9: make area parsing consistent with severity — extract
  bare value before " — " separator so "backend — Server-side" validates correctly
- (PROJECT_ENUMS export verified as already present on line 1086)

Tests:
- orchestrator.test.mjs: add tests for resolveTeamByArea() (default routing,
  unknown areas, config overrides, team- prefix handling) and computeEscalation()
  (security escalation, blocked cross-team, operations team from config, edge cases)
- review-runner.test.mjs: add tests for normalizeSeverity() (uppercase, lowercase,
  mixed case, unknown values)
- validate.test.mjs: add Phase 9 tests (valid dropdowns, invalid area, invalid
  severity, malformed template, area options with description separators)

DRY improvements:
- synchronize.mjs: add buildAreaRoutingTable() to generate routing from teams.yaml
  and expose as {{intakeAreaRoutingTable}} template variable
- All 4 platform templates (Copilot, Cursor, Windsurf, Codex) now use
  {{intakeAreaRoutingTable}} instead of hardcoded routing strings

Performance:
- orchestrator.mjs: add loadTeamsSpec() cache (Map keyed by agentkitRoot) so
  resolveTeamByArea() and computeEscalation() read teams.yaml at most once per
  process. Export clearTeamsSpecCache() for test isolation.

Robustness:
- computeEscalation(): read operationsTeam from teams.yaml config instead of
  hardcoding 'team-quality'
- issue-label-validation.yml: add workflow_dispatch trigger with optional
  issue_number input for manual dry-run testing

All 597 tests pass.

https://claude.ai/code/session_01Ue9aaiqqt1iHDx8KNwQ92m

* chore: regenerate sync-backlog.prompt.md after template variable change

The Copilot prompt template now uses {{intakeAreaRoutingTable}} which
renders the area→team routing as a compact inline string instead of a
full markdown table.

https://claude.ai/code/session_01Ue9aaiqqt1iHDx8KNwQ92m

* fix(branch-protection): address review findings for JSON commas, defaults, and Copilot API

1. Fix invalid JSON from {{#each}} blocks: add trailing commas to array
   items in bash templates and pipe through strip_trailing_commas helper
2. Fix securityAlertThreshold comment: correct valid values to
   none | critical | high_or_higher | medium_or_higher | all
3. Fix Copilot review API: use PUT /repos/{owner}/{repo}/copilot/code_review
   endpoint with review_new_pushes and review_draft_pull_requests in payload
4. Add bp* defaults in synchronize.mjs so missing branchProtection config
   produces valid scripts instead of broken JSON
5. Add 12 tests: branchProtection mapping coverage, array transform type,
   and JSON comma handling with resolveEachBlocks

https://claude.ai/code/session_011Vp3WAEEQToMVkpdjNcimB

* docs(issues): add issue specs for template update, finops agent, and team restructuring

- cost-budget-flag-template-update: Document --budget flag in /cost template
- finops-specialist-agent-consideration: Future split of FinOps from Data Engineer
- agent-team-restructuring-gaps: Address docs/quality team gaps and orphaned agents

https://claude.ai/code/session_01TdK27Dqh4JPrSqjCEUtCP2

* docs(issues): add agent/team analysis and gap issues

- architect-agent-analysis: evaluate need for dedicated Architect agent
- docs-quality-teams-missing-agents: T8 and T10 have no dedicated agents
- data-agent-concerns-refactoring: separate cost analytics from Data Engineer
- design-agents-missing-team: brand-guardian and ui-designer have no team
- marketing-agents-missing-team: content-strategist and growth-analyst have no team
- cost-budget-cli-flag-partial: --budget flag not exposed in command template
- cost-review-handoff-chain-gap: no cost governance in any handoff chain
- finops-md-content-verification: verify finops.md content across platforms

https://claude.ai/code/session_01TdK27Dqh4JPrSqjCEUtCP2

* fix(branch-protection): apply PR #262 review comments

- Replace {{#each}} in JSON heredocs with precomputed JSON vars
  (bpRequiredStatusChecksJson, bpCodeScanningToolsJson) to avoid
  invalid JSON from missing commas
- Remove strip_trailing_commas helper (no longer needed)
- Use $BRANCH/$Branch variable instead of hardcoded {{defaultBranch}}
  in code scanning and merge queue rulesets
- Add branch name validation regex to prevent injection via --branch
- Wrap code scanning and merge queue gh api calls with error handling
  (if ! ... in bash, try/catch in PowerShell)
- Switch to unquoted heredocs (<<ENDJSON) where variable expansion is
  needed, keep quoted (<<'ENDJSON') where it is not
- Use PowerShell here-strings (@"..."@) instead of hashtable literals
  for JSON payloads for consistency and correctness

https://claude.ai/code/session_011Vp3WAEEQToMVkpdjNcimB

* chore(sync): update generated file timestamps

Sync engine updated last_updated timestamps from 2026-03-04 to
2026-03-05 across agents, chatmodes, and prompts. No content changes.

https://claude.ai/code/session_01TdK27Dqh4JPrSqjCEUtCP2

* fix(template-utils): add JSON vars to RAW_TEMPLATE_VARS to preserve braces

The sanitizeTemplateValue function strips `{` and `}` from string values
in shell script templates. This caused precomputed JSON variables
(bpRequiredStatusChecksJson, bpCodeScanningToolsJson) to lose their
object braces, producing invalid JSON in generated scripts.

Adding these vars to RAW_TEMPLATE_VARS bypasses sanitization since they
contain pre-validated JSON that must preserve its structure.

https://claude.ai/code/session_011Vp3WAEEQToMVkpdjNcimB

* chore: regenerate files via agentkit sync

https://claude.ai/code/session_011Vp3WAEEQToMVkpdjNcimB

* docs(issues): add phased remediation plan for budget-guard review findings

Addresses findings across security (command injection in shell hook),
correctness (falsy-zero bug, regex ambiguity), performance (O(N) scan),
and test coverage gaps. Organised into 4 phases by priority.

https://claude.ai/code/session_01TdK27Dqh4JPrSqjCEUtCP2

* feat: add document-history command for institutional memory (#236)

* feat(docs): improve template adoption across agent workflows and commands

The docs/history/ TEMPLATE-* files existed but were rarely used because
nothing in the agent workflow triggered their creation. This change adds
history document creation prompts at every natural touchpoint:

- CLAUDE.md template: add History Documentation section and /document-history
  to quick reference and standard session flow
- team-TEMPLATE.md: add Step 4b (Create History Document) to team workflow
  and History Document section to output format
- orchestrate.md: add history doc creation step to Phase 5 (Ship)
- handoff.md: add history doc creation as output destination step 3
- review.md: add history doc recommendation to review output, update
  retrospective to use create-doc.sh for issue/lesson types
- stop-build-check.sh: add non-blocking warning when significant source
  changes lack history documentation
- New /document-history command: dedicated slash command with auto-detection
  of type and title from git history
- commands.yaml: add document-history command spec
- create-doc.sh: extend to support issue and lesson types
- .index.json: add issue and lesson sequence keys
- docs/history/README.md: document all six subdirectories and /document-history

https://claude.ai/code/session_01VpYZ9Gr9JiMBKVJKKRujtD

* fix(hooks): prevent grep -c exit code 1 from terminating stop hook

grep -c returns exit code 1 when count is 0, which under set -euo
pipefail would terminate the hook prematurely. Wrap in subshell with
|| true to handle zero-match case safely. Also fix table alignment
in CLAUDE.md quick reference.

https://claude.ai/code/session_01VpYZ9Gr9JiMBKVJKKRujtD

* fix: address review findings across templates, hooks, and scripts

- commands.yaml: expand --type enum to include issue/lesson with
  clarifying description that they're typically from retrospective
- document-history.md: remove Bash(cat *) from allowed-tools (use Read
  instead), add merge-base fallback for shallow clones/short branches
- stop-build-check.sh: hoist BRANCH/DEFAULT_BRANCH resolution to shared
  block to avoid redundant git calls, normalize indentation after
  refactor
- create-doc.ps1: add issue/lesson support (ValidateSet, SubdirMap,
  initial sequences, sed placeholders, changelog skip logic) to match
  create-doc.sh parity

https://claude.ai/code/session_01VpYZ9Gr9JiMBKVJKKRujtD

* fix: address inline review findings for document-history, handoff, team template, and create-doc

- Add Read/Write/Edit/Glob/Grep to document-history allowed-tools
- Replace fragile hardcoded git ranges with commit-count-safe logic
- Add deduplication guard to handoff history doc section
- Rewrite team-TEMPLATE Step 4b to use /document-history --auto
- Add issue/lesson types to create-doc.sh index initialization

https://claude.ai/code/session_01VpYZ9Gr9JiMBKVJKKRujtD

---------

Co-authored-by: Claude <noreply@anthropic.com>

* feat(language-profile): add configurable inference modes and diagnostics (#239)

* fix(claude-hooks): make session-start cross-platform and detect gh

* feat(language-profile): add configurable inference modes and diagnostics

* chore(sync): add split-pr helpers and telemetry workflow docs

* fix(scripts): report created vs skipped quality issues

* fix(sync): harden prereq checks and argument handling

* docs(issue-170): track source-of-truth patch tasks and verification (#256)

* fix(claude-hooks): make session-start cross-platform and detect gh

* feat(language-profile): add configurable inference modes and diagnostics

* chore(sync): add split-pr helpers and telemetry workflow docs

* fix(scripts): report created vs skipped quality issues

* fix(sync): harden prereq checks and argument handling

* docs(issue-170): add source-file verification and task links

* feat: remove idempotent issue creation script and streamline sync scripts

- Deleted the `create-quality-issues.sh` script which was responsible for batch-creating GitHub issues for the quality framework expansion plan.
- Updated `sync-split-pr.ps1` and `sync-split-pr.sh` scripts to remove redundant command assertions and improve logging output.
- Simplified the usage instructions in `sync-split-pr.sh` and removed the command requirement checks, focusing on a cleaner execution flow.

* docs(prd): implement autoupdate feature spec and CLI delivery milestone tracker (#244)

* Initial plan

* docs(prd): add autoupdate PRD, milestone tracker, and cross-references for CLI delivery issues

Co-authored-by: JustAGhosT <5531814+JustAGhosT@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: JustAGhosT <5531814+JustAGhosT@users.noreply.github.com>

* feat: add expansion analyst agent with gap analysis engine (#264)

* docs: add feasibility analysis for feature expansion agent

Comprehensive analysis covering architecture fit, integration strategy,
human-in-the-loop controls, spec generation approach, risk assessment,
and phased implementation plan for a proposed expansion/addition agent.

https://claude.ai/code/session_01WDZpGwDtTp9fADCJsLzXic

* feat(expansion): add Phase 1 expansion analyst agent with analysis engine

- ADR-08: Document decision to introduce expansion analyst agent
- Add expansion-analyzer.mjs with 6 gap analyzers (docs, ADR, testing,
  security, ops, architecture) and scoring/ranking engine
- Add suggestion-store.mjs with YAML persistence, lifecycle management,
  and rejection memory for deduplication
- Add expansion-analyst agent definition to agents.yaml (product category)
- Add /expand command to commands.yaml (read-only, no file writes)
- Add comprehensive tests for both modules (all 606 tests passing)

Phase 1 is analysis-only: produces scored suggestions as structured
output without writing files or creating tasks. Human approval gates
are required before any downstream action.

https://claude.ai/code/session_01WDZpGwDtTp9fADCJsLzXic

* Add phase gates and stopping conditions for expansion agent rollout

Define explicit go/no-go criteria for each phase transition (analysis →
suggestion store → spec generation → full integration) with measurable
thresholds for signal-to-noise ratio, approval rates, draft quality, and
performance. Include stopping conditions to abandon further phases if
the agent produces more noise than value.

https://claude.ai/code/session_01WDZpGwDtTp9fADCJsLzXic

* Address PR #264 review comments: security, correctness, and cleanup

- Fix path traversal vulnerability: validate suggestion IDs against strict
  pattern (SUG-NNN) before filesystem access (comments #4, #9)
- Fix ID collision risk: namespace suggestion files by run timestamp to
  prevent overwrites across analysis runs (comment #3)
- Add Write to /expand allowed-tools for --save flag (comment #1)
- Change /expand from workflow to utility type to match docs (comment #2)
- Derive operations docs path from docsSpec instead of hardcoding (comment #5)
- Use nullish coalescing (??) for maxSuggestions/minImpact (comment #6)
- Remove unused adrCount variable (comment #7)
- Update header comment to reflect file-backed storage (comment #8)
- Remove unused imports: basename, join, stat (comment #10)
- Update tests for namespaced IDs and path traversal validation

https://claude.ai/code/session_01WDZpGwDtTp9fADCJsLzXic

* Regenerate outputs after /expand type change (agentkit sync)

Run agentkit sync to propagate the /expand command type change from
workflow to utility across all generated AI tool configurations.

https://claude.ai/code/session_01WDZpGwDtTp9fADCJsLzXic

---------

Co-authored-by: Claude <noreply@anthropic.com>

* feat: dd issue sync script and ADR-08 for local-to-GitHub issue promotion (#263)

* feat(issues): add gh fallback workflow, sync script, and ADR-08

When `gh` CLI is unavailable (proxy, air-gap, missing install), issues
are recorded locally via `create-doc.sh issue`. A new `sync-issues.sh`
script promotes unsynced local issue docs to GitHub Issues once access
is restored (dry-run by default, --apply to create).

- Update issue READMEs and templates with preferred/fallback workflow
- Add Sync Status metadata section to issue template (gh_synced flag)
- Add scripts/sync-issues.sh for local-to-GitHub issue sync
- Add ADR-08 documenting sync trigger strategy (manual + CI)

https://claude.ai/code/session_012h3YEeccLbQTMNUw1YDWHG

* fix(sync-issues): address review findings for portability and robustness

- Add --label missing-arg bounds check (prevents set -u crash)
- Replace sed -i with portable temp-file pattern (macOS compat)
- Redirect gh stderr to /dev/null, capture only stdout URL
- Add comment explaining glob pattern naming convention assumption
- Rename SYNCED counter to CANDIDATES for dry-run clarity
- Fix ADR-08 branch reference from main to master (actual default)

https://claude.ai/code/session_012h3YEeccLbQTMNUw1YDWHG

* fix(sync-issues): address PR #263 review comments

- Defer gh CLI preflight checks to --apply mode so dry-run works in
  air-gapped/restricted environments without gh installed
- Make grep for H1 title non-fatal (|| true) so one malformed issue doc
  doesn't abort the entire sync batch under set -e
- Update ADR README template source with ADR-07 and ADR-08 entries and
  regenerate via agentkit:sync to keep template and output in sync

Previously fixed (prior commit):
- --label missing-arg bounds check
- sed -i replaced with portable temp-file pattern

https://claude.ai/code/session_012h3YEeccLbQTMNUw1YDWHG

* fix(sync-issues): address second round of PR #263 review comments

- Capture gh stderr to temp file; surface it on failure instead of
  discarding with 2>/dev/null for better diagnostics
- Make ISSUE_NUMBER extraction non-fatal using parameter expansion
  with grep fallback and "unknown" default, preventing set -e exit
  after a successful gh issue create
- Metadata stamping (sed -> tmpfile -> mv) is now unconditional after
  gh issue create succeeds, preventing duplicate issues on next run
- Fix default branch reference in ADR-08 from master to dev (actual
  default branch per git remote)
- Update contradictory "None are implemented yet" wording to reflect
  Phase 1 (manual sync) is complete; only CI/hook triggers remain

Note: history README template fix (contradictory create-doc wording)
is blocked by the protect-templates hook — requires a manual edit to
.agentkit/templates/docs/history/README.md followed by agentkit:sync.

https://claude.ai/code/session_012h3YEeccLbQTMNUw1YDWHG

---------

Co-authored-by: Claude <noreply@anthropic.com>

* ci(sync): Standardize Node.js version management across CI workflows (#235)

* ci: improve workflow naming and replace hardcoded node versions

- Rename CI workflow from "CI" to "AgentKit Forge CI" for clarity
- Add descriptive job names (Test, Validate, YAML Lint, Markdown Lint)
- Remove node-version from matrix to eliminate meaningless "24" in job names
  (was showing as "test (24, windows-latest)" → now "Test (windows-latest)")
- Replace hardcoded node-version: 24 with node-version-file: package.json
  in our own workflows (reads from engines.node in package.json)
- Replace hardcoded node-version: 24 with node-version: lts/* in generated
  template files for consumer projects
- Fix block-agentkit-changes.yml naming from snake_case to Title Case
- Update branch-protection.yml comments to reflect new CI job names

https://claude.ai/code/session_01HQwG1sTW7FyrbidZceZkQb

* ci: replace hardcoded CI values with template engine variables

Add new spec fields (process.protectedBranches, documentation.historyPath,
stack.nodeVersion, stack.pythonVersion) and corresponding template var
mappings so CI workflow templates derive values from project.yaml instead
of hardcoding them.

- Gate audit-rust/audit-python jobs with {{#if hasLanguageRust/Python}}
- Gate coverage-rust job with {{#if hasLanguageRust}}
- Gate breaking-change version-file patterns by language booleans
- Replace hardcoded branches: [main, dev] with {{protectedBranches}}
- Replace hardcoded node-version: lts/* with {{nodeVersion}}
- Replace hardcoded python-version: '3.12' with {{pythonVersion}}
- Replace hardcoded docs/history/ paths with {{docsHistoryPath}}
- Add missing GENERATED headers to documentation-quality.yml and
  documentation-validation.yml for consistency

https://claude.ai/code/session_01HQwG1sTW7FyrbidZceZkQb

* ci: use testingCoverage from project.yaml in coverage-report threshold

The coverage-report workflow previously required a manual COVERAGE_THRESHOLD
env var to enforce thresholds. Now it defaults to {{testingCoverage}} from
project.yaml (currently 80%) with env var override still supported.

https://claude.ai/code/session_01HQwG1sTW7FyrbidZceZkQb

* ci: add template hygiene checks, mapping coverage validation, and always-on placeholder warnings

- Add checkTemplateHygiene() to doctor.mjs with 5 detection rules for
  hardcoded values that should use template vars (nodeVersion, pythonVersion,
  protectedBranches, docsHistoryPath, testingCoverage)
- Add validateMappingCoverage() to spec-validator.mjs to verify all
  PROJECT_MAPPING src paths exist in project.yaml
- Promote unresolved placeholder warnings in template-utils.mjs from
  DEBUG-only to always-on for better visibility during sync
- Gate dependency-audit.yml trigger paths with language conditionals
  (Cargo.toml/lock, pyproject.toml, requirements*.txt, *.csproj)
- Add 8 new tests covering all new functionality

https://claude.ai/code/session_01HQwG1sTW7FyrbidZceZkQb

* fix: address review findings for validateMappingCoverage and unused imports

- Fix logic bug: `!resolved && current === undefined` → `!resolved || current === undefined`
  to catch leaf-level missing fields (e.g. stack.missingField when stack exists)
- Remove unused imports: `relative` from path, `flattenProjectYaml` from template-utils
- Remove redundant comment in spec-validator exports block
- Add test for leaf-undefined edge case

https://claude.ai/code/session_01HQwG1sTW7FyrbidZceZkQb

* chore(ci): regenerate sync outputs after spec validation fixes

Sync removed dependency-audit trigger paths for languages not configured
in project.yaml (Rust, Python, C#). The {{teamAccepts}} placeholder
warning remains — requires engine-level fix in synchronize.mjs (tracked
separately).

https://claude.ai/code/session_01HQwG1sTW7FyrbidZceZkQb

* chore: regenerate sync outputs after dev merge

Sync outputs updated from merge with dev branch including
language-profile feature and document-history command.

https://claude.ai/code/session_01HQwG1sTW7FyrbidZceZkQb

* fix(ci): address PR review comments and resolve doctor/sync bugs

- Guard validateMappingCoverage return in doctor.mjs against undefined
- Change file-level placeholder skip to per-line check in checkTemplateHygiene
- Add validateMappingCoverage mocks to 4 language profile doctor tests
- Remove dead DEBUG beforeEach/afterEach hooks in template-utils tests
- Add teamAccepts and teamHandoffChain to all 4 teamVars blocks in sync
- Pin Node.js version via .node-version file instead of package.json range
- Update branch-protection script contexts to match renamed workflow
- Wire COVERAGE_THRESHOLD from vars context in coverage-report workflow
- Restore if-guard and wire vars in coverage-report template
- Fix inline conditional YAML syntax in dependency-audit template
- Widen .csproj glob to **/*.csproj for monorepo support
- Add fallback defaults for nodeVersion, pythonVersion, docsHistoryPath

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(ci): use .node-version in dependency-audit workflow

Replace lts/* with .node-version file for deterministic Node.js version.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: regenerate sync outputs after review fixes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>

* feat(governance): consolidate autoupdate docs and upstream-link guardrails (#257)

* ci: improve workflow naming and replace hardcoded node versions

- Rename CI workflow from "CI" to "AgentKit Forge CI" for clarity
- Add descriptive job names (Test, Validate, YAML Lint, Markdown Lint)
- Remove node-version from matrix to eliminate meaningless "24" in job names
  (was showing as "test (24, windows-latest)" → now "Test (windows-latest)")
- Replace hardcoded node-version: 24 with node-version-file: package.json
  in our own workflows (reads from engines.node in package.json)
- Replace hardcoded node-version: 24 with node-version: lts/* in generated
  template files for consumer projects
- Fix block-agentkit-changes.yml naming from snake_case to Title Case
- Update branch-protection.yml comments to reflect new CI job names

https://claude.ai/code/session_01HQwG1sTW7FyrbidZceZkQb

* ci: replace hardcoded CI values with template engine variables

Add new spec fields (process.protectedBranches, documentation.historyPath,
stack.nodeVersion, stack.pythonVersion) and corresponding template var
mappings so CI workflow templates derive values from project.yaml instead
of hardcoding them.

- Gate audit-rust/audit-python jobs with {{#if hasLanguageRust/Python}}
- Gate coverage-rust job with {{#if hasLanguageRust}}
- Gate breaking-change version-file patterns by language booleans
- Replace hardcoded branches: [main, dev] with {{protectedBranches}}
- Replace hardcoded node-version: lts/* with {{nodeVersion}}
- Replace hardcoded python-version: '3.12' with {{pythonVersion}}
- Replace hardcoded docs/history/ paths with {{docsHistoryPath}}
- Add missing GENERATED headers to documentation-quality.yml and
  documentation-validation.yml for consistency

https://claude.ai/code/session_01HQwG1sTW7FyrbidZceZkQb

* ci: use testingCoverage from project.yaml in coverage-report threshold

The coverage-report workflow previously required a manual COVERAGE_THRESHOLD
env var to enforce thresholds. Now it defaults to {{testingCoverage}} from
project.yaml (currently 80%) with env var override still supported.

https://claude.ai/code/session_01HQwG1sTW7FyrbidZceZkQb

* ci: add template hygiene checks, mapping coverage validation, and always-on placeholder warnings

- Add checkTemplateHygiene() to doctor.mjs with 5 detection rules for
  hardcoded values that should use template vars (nodeVersion, pythonVersion,
  protectedBranches, docsHistoryPath, testingCoverage)
- Add validateMappingCoverage() to spec-validator.mjs to verify all
  PROJECT_MAPPING src paths exist in project.yaml
- Promote unresolved placeholder warnings in template-utils.mjs from
  DEBUG-only to always-on for better visibility during sync
- Gate dependency-audit.yml trigger paths with language conditionals
  (Cargo.toml/lock, pyproject.toml, requirements*.txt, *.csproj)
- Add 8 new tests covering all new functionality

https://claude.ai/code/session_01HQwG1sTW7FyrbidZceZkQb

* fix: address review findings for validateMappingCoverage and unused imports

- Fix logic bug: `!resolved && current === undefined` → `!resolved || current === undefined`
  to catch leaf-level missing fields (e.g. stack.missingField when stack exists)
- Remove unused imports: `relative` from path, `flattenProjectYaml` from template-utils
- Remove redundant comment in spec-validator exports block
- Add test for leaf-undefined edge case

https://claude.ai/code/session_01HQwG1sTW7FyrbidZceZkQb

* Initial plan

* docs(prd): add autoupdate PRD, milestone tracker, and cross-references for CLI delivery issues

Co-authored-by: JustAGhosT <5531814+JustAGhosT@users.noreply.github.com>

* docs(reference): update delivery milestone tracker with issue links

* docs(reference): format delivery milestone issue table

* fix(docs): remove leftover merge markers in milestone tracker

* chore(ci): regenerate sync outputs after spec validation fixes

Sync removed dependency-audit trigger paths for languages not configured
in project.yaml (Rust, Python, C#). The {{teamAccepts}} placeholder
warning remains — requires engine-level fix in synchronize.mjs (tracked
separately).

https://claude.ai/code/session_01HQwG1sTW7FyrbidZceZkQb

* chore: regenerate sync outputs after dev merge

Sync outputs updated from merge with dev branch including
language-profile feature and document-history command.

https://claude.ai/code/session_01HQwG1sTW7FyrbidZceZkQb

* docs(autoupdate): address PR #257 review comments

* Update last_updated dates for agents and prompts to 2026-03-05

* Initial plan

* fix(docs): update dependency map to reference #258 consistently

Address remaining Copilot review comment from PR #257 — replace
"autoupdate issue (TBD)" with "#258 (autoupdate)" in the dependency map.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(commands): add --branch and --project flags, surface flags in skill templates

- Add --branch flag to review and preflight commands for explicit branch targeting
- Add --project flag to review, check, healthcheck, and deploy for monorepo scoping
- Add {{commandFlags}} section to all generic skill/command templates (Claude,
  Codex, Copilot, Cursor, Windsurf) so flags are visible at invocation time
- Revert accidental blank line in doctor.mjs (protected file)
- Regenerate all Copilot prompt outputs with flag tables

Flag overlap analysis identified --stack (7 commands), --focus (5), --output (5),
--dry-run (4), --scope (4) as the most shared flags. --branch and --project were
entirely missing from the spec despite being natural scoping dimensions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(cli): wire new spec flags into VALID_FLAGS and FLAG_TYPES

Add --branch, --project, --open-issues, and --dry-run to the CLI
runtime allowlist for check, review, healthcheck, and preflight
commands so the parser accepts flags defined in commands.yaml.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: JustAGhosT <5531814+JustAGhosT@users.noreply.github.com>

* feat(governance): add task governance controls with turn limits, loop detection, stagnation (#238)

* fix: add intra-task loop prevention guards for agent execution

Addresses the GPT 5.3 Copilot-style implementation loop where an agent
repeatedly attempts the same action without progress. Adds four new
guardrails to the team execution template:

- MAX_TASK_TURNS (25): hard cap on agentic turns per task, escalates to
  input-required when exceeded
- Action Repetition Detection: tracks last 5 actions, triggers on 3+
  similar consecutive attempts
- Stagnation Detection: flags tasks with no measurable progress after
  10 turns
- Handoff chain depth promoted from soft warning to hard stop

Registers four new event types in orchestrate.md:
TURN_LIMIT_REACHED, LOOP_DETECTED, STAGNATION_DETECTED,
HANDOFF_DEPTH_EXCEEDED

https://claude.ai/code/session_01APLR2oHKfwhra46MAWS41f

* feat: make loop prevention limits configurable via teams.yaml

Wire teamAccepts, teamHandoffChain, and three new loop prevention
variables (maxTaskTurns, maxHandoffChainDepth, maxStagnationTurns)
into the template rendering pipeline across all platforms (Claude,
Cursor, Windsurf, Copilot).

Teams can now override defaults per-team in teams.yaml:
  - max-task-turns: 25 (default)
  - max-handoff-chain-depth: 5 (default)
  - max-stagnation-turns: 10 (default)

Also fixes two pre-existing bugs where teamAccepts and
teamHandoffChain were referenced in team-TEMPLATE.md but never
populated during sync, rendering as unresolved placeholders.

Updates spec-validator to accept the new optional fields.

All 576 tests pass.

https://claude.ai/code/session_01APLR2oHKfwhra46MAWS41f

* docs: add template variable audit and heuristic defaults plan

Comprehensive analysis of all YAML spec → template variable wiring,
identifying bugs (name mismatches, unwired vars), heuristic
improvement opportunities, and open PR overlap.

https://claude.ai/code/session_01APLR2oHKfwhra46MAWS41f

* feat: fix unwired template variables, add heuristic defaults, and pipe syntax

Phase 1 — Fix unwired/misnamed template variables:
- loggingRetentionDays: templates used this name but mapping produced
  logRetentionDays; add dual mapping so both work
- containerRuntime: add spec field (deployment.containerRuntime) and
  project-mapping entry
- drTestSchedule: add spec field (compliance.disasterRecovery.testSchedule)
  and project-mapping entry

Phase 2 — Heuristic defaults based on project context:
- maxTaskTurns inferred from teamSize (solo=15, small=25, medium/large=35)
- maxHandoffChainDepth inferred from team count (≤3→3, ≤6→5, >6→7)
- maxStagnationTurns inferred from projectPhase (greenfield=15, active=10,
  maintenance/legacy=5)
- testingCoverage fallback from projectPhase (greenfield=60, active=80,
  maintenance/legacy=90)

Phase 3 — Template engine {{var|default}} pipe syntax:
- Adds support for inline fallback values: {{testingCoverage|80}}
- Resolves after normal substitution, before unresolved warning
- Prevents literal {{varName}} rendering without requiring code changes
- 3 new tests covering fallback, override, and empty default cases

All 579 tests pass.

https://claude.ai/code/session_01APLR2oHKfwhra46MAWS41f

* docs: add functional + technical specs for commitConvention auto-detect and spec-defaults.yaml

Two new feature specs to plan upcoming work:

- SPEC-commit-convention-auto-detect: Extends agentkit discover to detect
  commit conventions from filesystem artifacts (.commitlintrc, .releaserc,
  package.json keys) and git-log heuristics.

- SPEC-spec-defaults-yaml: Centralises template variable defaults into a
  declarative YAML file with static, phase-conditional, and teamSize-conditional
  blocks. Replaces scattered inline defaults across synchronize.mjs.

Both specs include functional requirements, technical implementation details,
testing strategy, and rollout plans.

https://claude.ai/code/session_01APLR2oHKfwhra46MAWS41f

* fix(governance): address PR review findings for task governance controls

- Fix spec-validator schema: use `min` instead of `minimum` to match validator
- Extract `buildTeamVars()` helper to eliminate 4x duplicated team variable blocks
- Fix invalid `blocked` status references to use canonical `input-required`
- Fix stagnation detection to track turn count (`_lastProgressTurn`) not timestamp
- Remove duplicate separator line in synchronize.mjs
- Sanitize pipe syntax values in template-utils.mjs for shell target safety
- Update PLAN doc: reflect pipe syntax support, fix variable status, move to docs/
- Regenerate sync outputs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>

* fix(ci): add workflow to fix stuck branch protection checks

Branch protection required status checks use names that don't match
the actual CI check names (e.g. `markdown-lint` vs `Markdown Lint`),
causing checks to stay in "Waiting for status" forever.

This adds a manually-triggered workflow that:
1. Creates a tracking issue documenting the mismatch
2. Attempts to update branch protection check names via API

https://claude.ai/code/session_01Q3u76p7dbyt2qzX62aaf4P

* feat(editor): add brand tier and scheme config for IDE theme generation

Add two new options to editor-theme.yaml:
- `tier` (full/medium/minimal) — controls how many editor surfaces get
  branded. Minimal themes only the title bar for instant project
  identification; medium adds activity bar, status bar, and sidebar;
  full themes everything.
- `scheme` (dark/light) — controls which color mapping wins when mode
  is 'both', so dark-scheme users get deep muted hues by default.

The filterByTier() function in brand-resolver.mjs classifies VS Code
color keys by surface prefix and strips non-matching slots before
writing settings. Sync engine passes tier/scheme through to metadata.

https://claude.ai/code/session_01QW2CpB4HDCWL8JES6N6Grq

* fix(docs): add language specifier to fenced code block in issue template

Fixes MD040 markdown lint failure in docs/history/issues/TEMPLATE-issue.md
by adding `text` language to the fenced code block.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(branch-protection): address CodeRabbit review findings

- Add defensive guards for bpCodeScanningTools entries in synchronize.mjs
  (filter nulls/scalars before property access)
- Fix dry-run mode in setup-branch-protection scripts to skip label
  creation when --dry-run is set (both bash and PowerShell)
- Fix PowerShell $Branch: scope qualifier issue by using ${Branch}
- Rebuild docs/history/.index.json to reflect actual entry files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(sync): address remaining CodeRabbit review findings

- Set IaC toolchain to [terraform, terragrunt] in project.yaml to match
  template content that extensively references these tools
- Fix coverage bullet indentation in dotnet/python language templates
  (was incorrectly nested under mocking bullet)
- Fix ADR-02 template: replace placeholder date with {{syncDate}},
  fill in repo-specific values for agentkit-forge instance
- Fix marketing template: reference brand token name instead of
  hardcoding hex value (contradicted the "no hardcoded hex" rule)
- Regenerated all outputs via agentkit sync --overwrite

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(branch-protection): harden error handling and input validation

- Replace PowerShell try/catch with $LASTEXITCODE checks for native
  gh api calls (try/catch doesn't catch native command failures)
- Filter out code scanning tools with empty names to prevent invalid
  API payloads ("tool": "" rejected by GitHub)
- Filter bpRequiredStatusChecks entries to strings before JSON.stringify
- Use jq `first` to handle duplicate rulesets returning multiple IDs
- Remove redundant projectVars fallback (vars already contains merged values)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(branch-protection): extract precomputation, add tests, fix docs

- Extract buildBranchProtectionJson() into exported testable function
- Add 13 unit …
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant