feat: add anti-pattern severity levels and mandatory understanding checks at resume (#1491) (#1610)

- Add severity column (blocking/advisory) to Critical Anti-Patterns table
  in .continue-here.md template in pause-work.md
- Document that blocking anti-patterns trigger a mandatory understanding
  check when discuss-phase or execute-phase resumes work
- Add check_blocking_antipatterns step to discuss-phase.md: parses
  .continue-here.md for blocking rows and requires three-question
  understanding demonstration before proceeding
- Add identical enforcement step to execute-phase.md
- Tests: tests/anti-pattern-enforcement.test.cjs (12 assertions, all pass)

Closes #1491
This commit is contained in:
Tom Boucher
2026-04-03 13:06:31 -04:00
committed by GitHub
parent bdf6b5efcb
commit d8ea195662
4 changed files with 250 additions and 0 deletions

View File

@@ -162,6 +162,30 @@ Exit workflow.
- This is the middle ground: user controls the discuss decisions, then plan+execute run autonomously
</step>
<step name="check_blocking_antipatterns" priority="first">
**MANDATORY — Check for blocking anti-patterns before any other work.**
Look for a `.continue-here.md` in the current phase directory:
```bash
ls ${phase_dir}/.continue-here.md 2>/dev/null || true
```
If `.continue-here.md` exists, parse its "Critical Anti-Patterns" table for rows with `severity` = `blocking`.
**If one or more `blocking` anti-patterns are found:**
This step cannot be skipped. Before proceeding to `check_existing` or any other step, the agent must demonstrate understanding of each blocking anti-pattern by answering all three questions for each one:
1. **What is this anti-pattern?** — Describe it in your own words, not by quoting the handoff.
2. **How did it manifest?** — Explain the specific failure that caused it to be recorded.
3. **What structural mechanism (not acknowledgment) prevents it?** — Name the concrete step, checklist item, or enforcement mechanism that stops recurrence.
Write these answers inline before continuing. If a blocking anti-pattern cannot be answered from the context in `.continue-here.md`, stop and ask the user for clarification.
**If no `.continue-here.md` exists, or no `blocking` rows are found:** Proceed directly to `check_existing`.
</step>
<step name="check_existing">
Check if CONTEXT.md already exists using `has_context` from init.

View File

@@ -110,6 +110,30 @@ fi
```
</step>
<step name="check_blocking_antipatterns" priority="first">
**MANDATORY — Check for blocking anti-patterns before any other work.**
Look for a `.continue-here.md` in the current phase directory:
```bash
ls ${phase_dir}/.continue-here.md 2>/dev/null || true
```
If `.continue-here.md` exists, parse its "Critical Anti-Patterns" table for rows with `severity` = `blocking`.
**If one or more `blocking` anti-patterns are found:**
This step cannot be skipped. Before proceeding to `check_interactive_mode` or any other step, the agent must demonstrate understanding of each blocking anti-pattern by answering all three questions for each one:
1. **What is this anti-pattern?** — Describe it in your own words, not by quoting the handoff.
2. **How did it manifest?** — Explain the specific failure that caused it to be recorded.
3. **What structural mechanism (not acknowledgment) prevents it?** — Name the concrete step, checklist item, or enforcement mechanism that stops recurrence.
Write these answers inline before continuing. If a blocking anti-pattern cannot be answered from the context in `.continue-here.md`, stop and ask the user for clarification.
**If no `.continue-here.md` exists, or no `blocking` rows are found:** Proceed directly to `check_interactive_mode`.
</step>
<step name="check_interactive_mode">
**Parse `--interactive` flag from $ARGUMENTS.**

View File

@@ -44,6 +44,9 @@ If phase is detected, proceed with phase handoff path. Otherwise use the first m
6. **Human actions pending**: Things that need manual intervention (MCP setup, API keys, approvals, manual testing)
7. **Background processes**: Any running servers/watchers that were part of the workflow
8. **Files modified**: What's changed but not committed
9. **Blocking constraints**: Anti-patterns or methodological failures encountered during this session that a resuming agent MUST be aware of before proceeding. Only include items discovered through actual failure — not warnings or predictions. Assign each constraint a `severity`:
- `blocking` — The resuming agent MUST demonstrate understanding before proceeding. The discuss-phase and execute-phase workflows will enforce a mandatory understanding check.
- `advisory` — Important context but does not gate resumption.
Ask user for clarifications if needed via conversational questions.
@@ -111,12 +114,35 @@ status: in_progress
last_updated: [timestamp from current-timestamp]
---
# BLOCKING CONSTRAINTS — Read Before Anything Else
> These are not suggestions. Each constraint below was discovered through failure.
> Acknowledge each one explicitly before proceeding.
- [ ] CONSTRAINT: [name] — [what it is] — [structural mitigation required]
**Do not proceed until all boxes are checked.**
_If no constraints have been identified yet, remove this section._
## Critical Anti-Patterns
| Pattern | Description | Severity | Prevention Mechanism |
|---------|-------------|----------|---------------------|
| [pattern name] | [what it is and how it manifested] | blocking | [structural step that prevents recurrence — not acknowledgment] |
| [pattern name] | [what it is and how it manifested] | advisory | [guidance for avoiding it] |
**Severity values:** `blocking` — resuming agent must pass understanding check before proceeding. `advisory` — important context, does not gate resumption.
_Remove rows that do not apply. The discuss-phase and execute-phase workflows parse this table and enforce a mandatory understanding check for any `blocking` rows._
<current_state>
[Where exactly are we? Immediate context]
</current_state>
<completed_work>
Completed Tasks:
- Task 1: [name] - Done
- Task 2: [name] - Done
- Task 3: [name] - In progress, [what's done]

View File

@@ -0,0 +1,176 @@
'use strict';
/**
* Anti-Pattern Enforcement Tests (#1491)
*
* Validates that the handoff/resume system structurally enforces critical
* anti-patterns via severity levels and mandatory understanding checks.
*/
const { test, describe } = require('node:test');
const assert = require('node:assert');
const fs = require('fs');
const path = require('path');
const PAUSE_WORK = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'pause-work.md');
const DISCUSS_PHASE = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'discuss-phase.md');
const EXECUTE_PHASE = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'execute-phase.md');
describe('pause-work.md — severity column in Critical Anti-Patterns template', () => {
test('template includes a Severity column header in the anti-patterns table', () => {
const content = fs.readFileSync(PAUSE_WORK, 'utf-8');
assert.ok(
content.includes('Severity') || content.includes('severity'),
'pause-work.md template must include a Severity column in the anti-patterns table'
);
});
test('template documents "blocking" as a valid severity value', () => {
const content = fs.readFileSync(PAUSE_WORK, 'utf-8');
assert.ok(
content.includes('blocking'),
'pause-work.md must document "blocking" as a valid severity value'
);
});
test('template documents "advisory" as a valid severity value', () => {
const content = fs.readFileSync(PAUSE_WORK, 'utf-8');
assert.ok(
content.includes('advisory'),
'pause-work.md must document "advisory" as a valid severity value'
);
});
test('template explains that blocking anti-patterns trigger understanding check at resume', () => {
const content = fs.readFileSync(PAUSE_WORK, 'utf-8');
const hasExplanation =
(content.includes('blocking') && content.includes('understanding check')) ||
(content.includes('blocking') && content.includes('resume')) ||
(content.includes('blocking') && content.includes('understanding'));
assert.ok(
hasExplanation,
'pause-work.md must explain that blocking anti-patterns trigger an understanding check at resume'
);
});
});
describe('discuss-phase.md — blocking anti-pattern understanding check', () => {
test('workflow checks for .continue-here.md with blocking anti-patterns', () => {
const content = fs.readFileSync(DISCUSS_PHASE, 'utf-8');
const hasCheck =
content.includes('.continue-here.md') &&
(content.includes('blocking') || content.includes('anti-pattern'));
assert.ok(
hasCheck,
'discuss-phase.md must check for .continue-here.md blocking anti-patterns before proceeding'
);
});
test('workflow includes mandatory understanding verification for blocking anti-patterns', () => {
const content = fs.readFileSync(DISCUSS_PHASE, 'utf-8');
const hasVerification =
content.includes('understanding') ||
content.includes('understanding check') ||
content.includes('demonstrate understanding');
assert.ok(
hasVerification,
'discuss-phase.md must include a mandatory understanding verification step for blocking anti-patterns'
);
});
test('workflow specifies the three understanding check questions', () => {
const content = fs.readFileSync(DISCUSS_PHASE, 'utf-8');
// The three questions required by the issue
const hasWhatIs =
content.includes('What is this anti-pattern') ||
content.includes('what is this anti-pattern') ||
content.includes('What is the anti-pattern');
const hasHowManifest =
content.includes('How did it manifest') ||
content.includes('how did it manifest') ||
content.includes('manifest');
const hasPreventMechanism =
content.includes('structural mechanism') ||
content.includes('prevention') ||
content.includes('Prevention');
assert.ok(
hasWhatIs && hasHowManifest && hasPreventMechanism,
'discuss-phase.md must include the three understanding check questions: ' +
'"What is this anti-pattern?", "How did it manifest?", "What structural mechanism prevents it?"'
);
});
test('understanding check cannot be skipped (must be mandatory)', () => {
const content = fs.readFileSync(DISCUSS_PHASE, 'utf-8');
const hasMandatory =
content.includes('cannot be skipped') ||
content.includes('must not be skipped') ||
content.includes('mandatory') ||
content.includes('MANDATORY') ||
content.includes('required before');
assert.ok(
hasMandatory,
'discuss-phase.md must indicate that the blocking anti-pattern understanding check cannot be skipped'
);
});
});
describe('execute-phase.md — blocking anti-pattern understanding check', () => {
test('workflow checks for .continue-here.md with blocking anti-patterns', () => {
const content = fs.readFileSync(EXECUTE_PHASE, 'utf-8');
const hasCheck =
content.includes('.continue-here.md') &&
(content.includes('blocking') || content.includes('anti-pattern'));
assert.ok(
hasCheck,
'execute-phase.md must check for .continue-here.md blocking anti-patterns before proceeding'
);
});
test('workflow includes mandatory understanding verification for blocking anti-patterns', () => {
const content = fs.readFileSync(EXECUTE_PHASE, 'utf-8');
const hasVerification =
content.includes('understanding') ||
content.includes('understanding check') ||
content.includes('demonstrate understanding');
assert.ok(
hasVerification,
'execute-phase.md must include a mandatory understanding verification step for blocking anti-patterns'
);
});
test('workflow specifies the three understanding check questions', () => {
const content = fs.readFileSync(EXECUTE_PHASE, 'utf-8');
const hasWhatIs =
content.includes('What is this anti-pattern') ||
content.includes('what is this anti-pattern') ||
content.includes('What is the anti-pattern');
const hasHowManifest =
content.includes('How did it manifest') ||
content.includes('how did it manifest') ||
content.includes('manifest');
const hasPreventMechanism =
content.includes('structural mechanism') ||
content.includes('prevention') ||
content.includes('Prevention');
assert.ok(
hasWhatIs && hasHowManifest && hasPreventMechanism,
'execute-phase.md must include the three understanding check questions: ' +
'"What is this anti-pattern?", "How did it manifest?", "What structural mechanism prevents it?"'
);
});
test('understanding check cannot be skipped (must be mandatory)', () => {
const content = fs.readFileSync(EXECUTE_PHASE, 'utf-8');
const hasMandatory =
content.includes('cannot be skipped') ||
content.includes('must not be skipped') ||
content.includes('mandatory') ||
content.includes('MANDATORY') ||
content.includes('required before');
assert.ok(
hasMandatory,
'execute-phase.md must indicate that the blocking anti-pattern understanding check cannot be skipped'
);
});
});