Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
trim_trailing_whitespace = true

[*.py]
indent_size = 4

[Makefile]
indent_style = tab
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @MPIsaac-Per
50 changes: 50 additions & 0 deletions .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Bug report
description: Report reproducible incorrect behavior in a sample or tool.
title: "bug: "
labels: [bug, triage]
body:
- type: markdown
attributes:
value: Do not include API keys, credentials, private transcripts, or customer data.
- type: input
id: pattern
attributes:
label: Pattern or file
placeholder: 03-verification-gate/verify.py
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Reproduction
description: Include the smallest command, configuration, and input needed to reproduce the problem.
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behavior
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual behavior
validations:
required: true
- type: input
id: environment
attributes:
label: Environment
placeholder: macOS 15, Python 3.13, Claude Code 2.x
validations:
required: true
- type: checkboxes
id: checks
attributes:
label: Pre-submission checks
options:
- label: I removed secrets and private data from this report.
required: true
- label: I searched existing issues for the same behavior.
required: true
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Security vulnerability
url: https://github.com/MPIsaac-Per/claude-code-loop-patterns/security/advisories/new
about: Report vulnerabilities privately. Do not open a public issue.
- name: Usage questions
url: https://github.com/MPIsaac-Per/claude-code-loop-patterns/discussions
about: Ask implementation and integration questions in Discussions.
26 changes: 26 additions & 0 deletions .github/ISSUE_TEMPLATE/feature.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Pattern proposal
description: Propose a bounded addition or improvement to the collection.
title: "proposal: "
labels: [enhancement, triage]
body:
- type: textarea
id: problem
attributes:
label: Failure mode
description: Describe the loop failure or maintenance problem this pattern should address.
validations:
required: true
- type: textarea
id: proposal
attributes:
label: Proposed pattern
description: Explain the behavior, interface, and evidence that would validate it.
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Existing tools or prior art
description: Link established implementations that contributors should evaluate first.
validations:
required: true
21 changes: 21 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
groups:
github-actions:
patterns: ["*"]
labels: [dependencies]
open-pull-requests-limit: 5

- package-ecosystem: pip
directory: /
schedule:
interval: weekly
groups:
development-dependencies:
dependency-type: development
labels: [dependencies, python]
open-pull-requests-limit: 5
14 changes: 14 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
## Change

Describe the behavior or documentation changed.

## Verification

- [ ] `uv run ruff check .`
- [ ] `uv run ruff format --check .`
- [ ] `uv run pytest --cov=. --cov-report=term-missing`
- [ ] Documentation and examples match the implemented behavior

## Risk

List compatibility, security, or rollout concerns. Write `None` when there are none.
84 changes: 84 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: CI

on:
push:
branches: [main]
pull_request:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
quality:
name: Quality
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Install uv
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
with:
enable-cache: true
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.14"
- name: Install locked dependencies
run: uv sync --locked --dev
- name: Lint
run: uv run ruff check .
- name: Check formatting
run: uv run ruff format --check .
- name: Type-check runtime files
run: >-
uv run mypy
01-structured-shell/run_loud.py
02-structured-tests/pytest_jsonl_reporter.py
03-verification-gate/check_evidence.py
03-verification-gate/verify.py
04-stop-hook/no_completion_without_evidence.py
05-prompt-cache/cacheable_prompt.py
- name: Audit Python dependencies
run: uv run pip-audit

test:
name: Test (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.14"]
steps:
- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Install uv
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
with:
enable-cache: true
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: ${{ matrix.python-version }}
- name: Install locked dependencies
run: uv sync --locked --dev
- name: Test
run: uv run pytest --cov=. --cov-report=term-missing --cov-report=xml
- name: Upload coverage report
if: matrix.python-version == '3.14'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: coverage-report
path: coverage.xml
if-no-files-found: error
retention-days: 14
38 changes: 38 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: CodeQL

on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: "17 6 * * 1"
workflow_dispatch:

permissions:
contents: read

concurrency:
group: codeql-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
analyze:
name: Analyze Python
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
security-events: write # Upload CodeQL findings to code scanning.
steps:
- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
with:
languages: python
queries: security-extended
- name: Analyze
uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
25 changes: 25 additions & 0 deletions .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Dependency review

on:
pull_request:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: dependency-review-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
review:
name: Review dependencies
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Review dependency changes
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
48 changes: 48 additions & 0 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: OpenSSF Scorecard

on:
branch_protection_rule:
schedule:
- cron: "31 6 * * 2"
push:
branches: [main]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: scorecard-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
analysis:
name: Analyze supply-chain posture
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
id-token: write # Publish signed Scorecard results to the OpenSSF API.
security-events: write # Upload Scorecard findings to code scanning.
steps:
- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Run Scorecard
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with:
results_file: results.sarif
results_format: sarif
publish_results: true
- name: Upload Scorecard artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: scorecard-results
path: results.sarif
if-no-files-found: error
retention-days: 5
- name: Upload Scorecard results to code scanning
uses: github/codeql-action/upload-sarif@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
with:
sarif_file: results.sarif
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ __pycache__/
.evidence/
*.log
.pytest_cache/
.coverage
coverage.xml
htmlcov/
.DS_Store
5 changes: 4 additions & 1 deletion 01-structured-shell/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ python3 run_loud.py --tag test pytest -q

# Machine-readable JSON, for downstream tools
python3 run_loud.py --tag build --json npm run build

# Bound a command that may hang
python3 run_loud.py --timeout-seconds 120 --tag test pytest -q
```

The exit code of `run_loud.py` matches the wrapped command, so you can drop it into any pipeline that already checks `$?`.

## Why

The article's first lesson: most "user" rows in a Claude Code transcript are tool-result carriers, not human prompts. Improving those tool results is the highest-leverage thing you can do for a long-running agent.
Most "user" rows in a Claude Code transcript are tool-result carriers rather than human prompts. Clear tool results give the next loop iteration usable state.

Article references: §1 (the user is not always the user), §5 (errors are the work).
Loading
Loading