Skip to content

Process Guard

Quick reference for lint-process validation rules, error fixes, and escape hatches.

Process Guard validates delivery workflow changes at commit time. For FSM concepts and state definitions, see METHODOLOGY.md.


StatusLevelAllowedBlocked
roadmapnoneFull editing-
deferrednoneFull editing-
activescopeEdit existing deliverablesAdding new deliverables
completedhardNothingAny change without @*-unlock-reason
FromToNotes
roadmapactive, deferredStart work or postpone
activecompleted, roadmapFinish or regress if blocked
deferredroadmapResume planning
completed(none)Terminal — use unlock to modify
SituationSolutionExample
Fix bug in completed specAdd @*-unlock-reason:'reason'@libar-docs-unlock-reason:'Fix typo'
Modify outside session scope--ignore-session flaglint-process --staged --ignore-session
CI treats warnings as errors--strict flaglint-process --all --strict
Skip workflow (legacy import)Multiple transitions in one commitSet roadmap then completed in same commit

Error:

[ERROR] specs/phase-state-machine.feature
Cannot modify completed spec without unlock reason
Suggestion: Add @libar-docs-unlock-reason:'reason for modification'

Cause: File has @libar-docs-status:completed but no unlock annotation.

Fix: Add unlock reason explaining why modification is necessary:

@libar-docs
@libar-docs-pattern:PhaseStateMachine
@libar-docs-status:completed
@libar-docs-unlock-reason:'Fix incorrect FSM diagram in documentation'
Feature: Phase State Machine

Unlock reason requirements:

  • Minimum 10 characters (short reasons like “fix” are rejected)
  • Cannot be a placeholder: test, xxx, bypass, temp, todo, fixme
  • If the reason is invalid, the error still fires — Process Guard treats it as no unlock reason

Alternative: If this should be new work, create a new spec instead of modifying completed work.


Error:

[ERROR] specs/my-feature.feature
Invalid status transition: roadmap -> completed
Suggestion: Valid transitions from roadmap: active, deferred

Cause: Attempted to skip active phase.

Fix: Follow the FSM path:

# Step 1: Move to active
@libar-docs-status:active
# Step 2: After implementation complete, move to completed
@libar-docs-status:completed

Common invalid transitions:

AttemptedWhy InvalidValid Path
roadmap->completedMust go through activeroadmap->active->completed
deferred->activeMust return to roadmap firstdeferred->roadmap->active
deferred->completedCannot skip two statesdeferred->roadmap->active->completed
completed->*Terminal stateUse @*-unlock-reason to modify

Error:

[ERROR] specs/process-guard-linter.feature
Cannot add deliverables to active spec: "New unplanned feature"
Suggestion: Remove new deliverable or revert status to roadmap

Cause: Added a row to the deliverables table while status is active.

Fix options:

  1. Remove the new deliverable — Keep scope locked during implementation
  2. Revert to roadmap — If scope genuinely needs to expand:
    @libar-docs-status:roadmap # Temporarily revert
    # Add deliverable, then:
    @libar-docs-status:active # Resume implementation

Why this rule exists: Prevents scope creep during implementation. Plan fully before starting; implement what was planned.


Warning:

[WARN] specs/unrelated-feature.feature
File not in active session scope
Suggestion: Add to session scope or use --ignore-session

Cause: Modifying a file not listed in the current session’s scopedSpecs.

Fix options:

  1. Add to session scope — If this file should be in scope
  2. Use --ignore-session — For intentional out-of-scope changes:
    Terminal window
    lint-process --staged --ignore-session

Error:

[ERROR] specs/legacy-feature.feature
File is explicitly excluded from session
Suggestion: Remove from exclusion list or use --ignore-session

Cause: File is in the session’s excludedSpecs list.

Fix options:

  1. Remove from exclusion list — If exclusion was a mistake
  2. Use --ignore-session — For emergency changes:
    Terminal window
    lint-process --staged --ignore-session

Warning:

[WARN] specs/active-feature.feature
Deliverable removed: "Unit tests"
Suggestion: Document if descoped or completed elsewhere

Cause: A deliverable was removed from an active spec.

Fix: This is informational. If intentional, no action needed. Consider documenting why in a commit message.


Terminal window
lint-process [options]
FlagDescriptionUse Case
--stagedValidate staged changes (default)Pre-commit hooks
--allValidate all changes vs mainCI/CD pipelines
--filesValidate specific filesDevelopment checks
FlagDescription
--strictTreat warnings as errors (exit 1)
--ignore-sessionSkip session scope rules
--show-stateDebug: show derived process state
--format jsonMachine-readable output
-f, --file <path>Specific file to validate (repeatable)
-b, --base-dirBase directory for file resolution
CodeMeaning
0No errors (warnings allowed unless —strict)
1Errors found
Terminal window
# Pre-commit hook (recommended)
lint-process --staged
# CI pipeline with strict mode
lint-process --all --strict
# Validate specific file
lint-process --file specs/my-feature.feature
# Debug: see what state was derived
lint-process --staged --show-state
# Override session scope for emergency fix
lint-process --staged --ignore-session

.husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-process --staged
{
"scripts": {
"lint:process": "lint-process --staged",
"lint:process:ci": "lint-process --all --strict"
}
}

import {
deriveProcessState,
detectStagedChanges,
validateChanges,
hasErrors,
summarizeResult,
} from '@libar-dev/delivery-process/lint';
// 1. Derive state from annotations
const state = (await deriveProcessState({ baseDir: '.' })).value;
// 2. Detect changes
const changes = detectStagedChanges('.').value;
// 3. Validate
const { result } = validateChanges({
state,
changes,
options: { strict: false, ignoreSession: false },
});
// 4. Handle results
if (hasErrors(result)) {
console.log(summarizeResult(result));
for (const v of result.violations) {
console.log(`[${v.rule}] ${v.file}: ${v.message}`);
if (v.suggestion) console.log(` Fix: ${v.suggestion}`);
}
process.exit(1);
}
CategoryFunctionDescription
StatederiveProcessState(cfg)Build state from file annotations
ChangesdetectStagedChanges(dir)Parse staged git diff
ChangesdetectBranchChanges(dir)Parse all changes vs main
ChangesdetectFileChanges(dir, f)Parse specific files
ValidatevalidateChanges(input)Run all validation rules
ResultshasErrors(result)Check for blocking errors
ResultshasWarnings(result)Check for warnings
ResultssummarizeResult(result)Human-readable summary

Process Guard uses the Decider pattern: pure functions with no I/O.

deriveProcessState() ─┐
├─► validateChanges() ─► ValidationResult
detectChanges() ─────┘

State is derived from file annotations — there is no separate state file to maintain.


DocumentContent
METHODOLOGY.mdFSM concepts, state definitions
README.mdPackage overview, quick start
TAXONOMY.mdTag taxonomy concepts and API