fix: inject ~30k token knowledge base into @claude GitHub Actions (documentation as code)#1185
Conversation
Switch from claude-code-action to claude-code-base-action to enable custom prompt injection. This gives the @claude GitHub Action access to the full knowledge base (principles, procedures, CLAUDE.md) that the local /close-issue command has. Changes: - Create knowledge aggregation script to collect all knowledge files - Add workflow prompt template with knowledge injection placeholders - Update claude-implementation.yml to use claude-code-base-action - Inject ~30k tokens of context before Claude processes issues - Update auto-trigger message to mention knowledge availability The @claude workflow now has the same rich context as local development, resulting in higher quality PRs that follow established patterns. Closes #1183 Principle: snowball-method Principle: systems-stewardship
|
⏳ I'm reviewing this pull request for security vulnerabilities and code quality issues. I'll provide an update when I'm done |
|
|
||
| - name: Prepare implementation prompt | ||
| id: prepare-prompt | ||
| run: | |
There was a problem hiding this comment.
Warning
Description: Untrusted input has been detected in GitHub Actions workflow run commands. This creates a significant security risk for script injection attacks, where malicious actors could exploit workflow inputs to execute unauthorized commands. GitHub Actions workflows should validate and sanitize all user-provided inputs, especially those used in run commands. Consider using GitHub's built-in security features like actions/github-script for safer command execution, or implement proper input validation before using dynamic values in run commands.
Similar issue at line numbers 93, 94, 95, 96, 97, 98, 99, 100, 101, and 128.
Severity: High
There was a problem hiding this comment.
The remediation replaces the vulnerable run commands with uses: actions/github-script@v7 steps. This change eliminates the risk of script injection by executing JavaScript code within a controlled environment provided by the GitHub Actions script action.
| run: | | |
| - name: Aggregate knowledge base | |
| id: knowledge | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| function aggregateKnowledge() { | |
| console.log("Aggregating knowledge base for Claude..."); | |
| const knowledgeBasePath = path.join('.github', 'scripts', 'aggregate-knowledge.sh'); | |
| if (fs.existsSync(knowledgeBasePath)) { | |
| const knowledge = fs.readFileSync(knowledgeBasePath, 'utf8'); | |
| console.log(`Knowledge base size: ${knowledge.length} characters`); | |
| return knowledge; | |
| } else { | |
| console.log("Knowledge base script not found."); | |
| return ""; | |
| } | |
| } | |
| const knowledge = aggregateKnowledge(); | |
| core.setOutput('content', knowledge); | |
| - name: Prepare implementation prompt | |
| id: prepare-prompt | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| function preparePrompt() { | |
| const isIssue = !!context.payload.issue && !context.payload.issue.pull_request; | |
| let prompt = ''; | |
| if (isIssue) { | |
| console.log("Preparing prompt for issue implementation..."); | |
| const issueNumber = context.payload.issue.number; | |
| const issueTitle = context.payload.issue.title; | |
| const issueBody = context.payload.issue.body; | |
| const templatePath = path.join('.github', 'workflow-prompts', 'issue-implementation.md'); | |
| if (fs.existsSync(templatePath)) { | |
| let template = fs.readFileSync(templatePath, 'utf8'); | |
| prompt = template | |
| .replace('{{ KNOWLEDGE_BASE }}', '${{ steps.knowledge.outputs.content }}') | |
| .replace('{{ ISSUE_NUMBER }}', issueNumber) | |
| .replace('{{ ISSUE_TITLE }}', issueTitle) | |
| .replace('{{ ISSUE_BODY }}', issueBody) | |
| .replace('{{ REPO }}', context.repo.owner + '/' + context.repo.repo); | |
| } else { | |
| console.log("Issue implementation template not found."); | |
| prompt = "Error: Template not found."; | |
| } | |
| } else { | |
| console.log("Preparing prompt for PR review..."); | |
| prompt = `${{ steps.knowledge.outputs.content }} | |
| ## PR Review Request | |
| The user has requested: ${context.payload.comment.body} | |
| Please review and respond to this pull request comment with the full context of the codebase principles and procedures available above.`; | |
| } | |
| return prompt; | |
| } | |
| const prompt = preparePrompt(); | |
| core.setOutput('prompt', prompt); | |
| - uses: anthropics/claude-code-base-action@beta | |
| with: |
|
✅ I finished the code review, and left comments with the issues I found. I will now generate code fix suggestions. |
Following versioning mindset, maximize reuse of existing content by: - Making issue-implementation.md work for both workflows - Update close-issue.md to INJECT the shared template - Fix knowledge aggregation (remove CLAUDE.md - not in repo) The same template now serves both: - /close-issue command: KNOWLEDGE_BASE placeholder stays empty (preloaded) - GitHub Actions: KNOWLEDGE_BASE gets filled with aggregated knowledge This creates a single source of truth for issue implementation instructions, reducing duplication and ensuring consistency. Principle: versioning-mindset Principle: subtraction-creates-value
Replace relative path with full GitHub raw URL for clarity and transparency. This makes it explicit where the content comes from and ensures it always pulls from the main branch. Benefits: - No path ambiguity - Self-documenting - Follows MCP tool file path transparency principle Principle: transparency-in-agent-work
Add clear documentation explaining the design decision: - GitHub raw URL for universal template (consistency) - Local paths for principles/procedures (development flexibility) - Single source of truth for issue implementation This mixed approach provides: - Consistent implementation instructions across both workflows - Ability to test local changes to principles/procedures - Best of both worlds for development and production Principle: transparency-in-agent-work Principle: systems-stewardship
Use relative path instead of GitHub raw URL to preserve local development workflow. This allows testing changes to the template before merging to main. Both workflows still share the same template: - /close-issue uses relative path for local flexibility - @claude gets it via repository checkout Principle: developer-experience
Add test comment to git-workflow.md to verify PR #1185's shared template structure works correctly when using the /close-issue command. This confirms that both @claude GitHub Action and local /close-issue command can share the same universal template at .github/workflow-prompts/issue-implementation.md Principle: tracer-bullets Principle: systems-stewardship Closes #1186
…vior Clarified that the placeholder remains as literal text in local /close-issue commands (not replaced with empty string) while GitHub Actions does actual string substitution. This prevents confusion about how the template works. The placeholder is harmless when shown literally since local Claude sessions already have the knowledge preloaded. Added inline comment to explain this to users who might see the literal placeholder text. Principle: transparency-in-agent-work
…sal template Moved all special content from /close-issue command into the universal template: - Tracer bullets principle injection - Close issue procedure injection - Post-implementation retro section with eager evolution - Ghost procedures reminder The /close-issue command is now just a minimal 3-line wrapper that injects the universal template. This makes the system DRYer and ensures both workflows (@claude and /close-issue) get identical instructions including retro prompts. Principle: subtraction-creates-value Principle: systems-stewardship
Removed verbose instructional content and made the template look like the original close-issue.md - just essential prompts and injections: - Removed numbered implementation instructions - Removed "Key Principles to Apply" section (redundant with injections) - Removed "Available Tools" section (Claude already knows) - Removed "Important Reminders" section (too preachy) - Removed verbose issue details section The template now focuses on what matters: injecting principles/procedures and providing issue context, without prescriptive instructions. Principle: subtraction-creates-value Principle: versioning-mindset
Make the implementation template the authoritative documentation by: - Updating close-issue-procedure.md to point to actual implementation - Adding inline documentation comments to the template - Establishing that the template IS the documentation The template is now both the executable code AND the documentation. What you read is what runs. True documentation as code. This completes the unification of /close-issue and @claude workflows into a single, knowledge-aware, self-documenting system. Principle: systems-stewardship Principle: subtraction-creates-value
Added counters to track if any .md files were found in the principles and procedures directories. If no files are found, the script now outputs a clear message instead of failing silently or processing glob patterns as literal strings. This prevents issues when: - Knowledge directories are empty - No .md files exist yet in new installations - Glob patterns don't match any files The script now gracefully handles these edge cases and provides helpful feedback to users and GitHub Actions. Principle: systems-stewardship
Move the entire issue implementation template to knowledge/procedures/close-issue-procedure.md where it becomes the single source of truth for both local /close-issue and GitHub @claude. The procedure IS the implementation - no separate template files needed. This achieves true documentation as code where the procedure documents itself by being the executable code. - Delete .github/workflow-prompts/ directory entirely - Update close-issue.md to just 3 lines pointing to the procedure - Update claude-implementation.yml to read directly from procedures/ - Transform close-issue-procedure.md to contain the full implementation Principle: systems-stewardship Principle: subtraction-creates-value
Restore the accidentally deleted issue-triage.md which is actively used by the auto-label-issues.yml workflow. Without this file, the auto-labeling functionality would break. Added explanatory comment clarifying why this file remains in workflow-prompts/ rather than procedures/ - it's a specialized AI prompt for GitHub Actions, not a human-executable procedure. Principle: systems-stewardship
Update: Restored issue-triage.mdJust pushed a fix - I accidentally deleted What I did:
This maintains the clean separation:
The PR is ready for review with both the knowledge base injection feature and the auto-labeling workflow intact. |
Update comment to be more honest - it's a low-value utility script that works fine and doesn't need to consume precious tokens in the knowledge base context. Not everything needs formal procedure status when it just works. Principle: subtraction-creates-value
…vior Update aggregate-knowledge.sh to recursively process the entire knowledge/ directory, not just principles/ and procedures/. This ensures GitHub Actions has the exact same context as local Claude Code. Now includes: - Root files (README.md, ai-index.md, throughput-definition.md) - personalities/ directory (Brent, Jonah, Harrington-Emerson) - tools/ directory (MCP dashboard) - All subdirectories that may be added in future Changed from ~30k to ~72k characters of knowledge context, achieving true parity with local Claude Code behavior. Principle: systems-stewardship
Summary
Fixes #1183 by injecting the COMPLETE knowledge base into @claude GitHub Actions, achieving true parity with local /close-issue commands. Implements "documentation as code" where the procedure IS the implementation.
The Problem
@claude GitHub Actions operated blind - no access to principles, procedures, personalities, tools, or the throughput definition that guide local development. This created inconsistent PR quality between local and GitHub-triggered implementations.
Changes Made
1. Comprehensive Knowledge Base Aggregation
.github/scripts/aggregate-knowledge.sh- Recursively aggregates ALL files underknowledge/2. Documentation as Code Transformation
knowledge/procedures/close-issue-procedure.md- The procedure IS the implementation{{ KNOWLEDGE_BASE }}placeholder that:3. Workflow Updates
.github/workflows/claude-implementation.yml:claude-code-action@betatoclaude-code-base-action@betafor prompt injectionprocedures/close-issue-procedure.md.github/workflows/auto-trigger-claude.yml:4. Simplifications
.claude/command-templates/close-issue.mdto 3 lines - just points to the procedure.github/workflow-prompts/issue-triage.md- Low-value utility script kept separate to preserve tokensArchitecture Decision
Two-tier system based on value:
knowledge/- ALL high-value content worth the token cost (now ~72k characters).github/workflow-prompts/- Low-value utility scripts that just work (issue-triage.md only)Principles Applied
Testing Checklist
/close-issuecommand works (template injection preserved)Impact
@claude now operates with COMPLETE architectural context in GitHub Actions - identical to local Claude Code. No subtle differences, no missing context. Full parity achieved.