@skj1724/oh-my-opencode 3.18.5 → 3.18.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1 -1
- package/dist/features/builtin-skills/skills/git-master-sections/commit-workflow.d.ts +1 -1
- package/dist/hooks/atlas/boulder-continuation-injector.d.ts +0 -1
- package/dist/hooks/atlas/tool-execute-after.d.ts +0 -1
- package/dist/hooks/atlas/tool-execute-before.d.ts +0 -1
- package/dist/hooks/atlas/types.d.ts +1 -1
- package/dist/hooks/compaction-context-injector/hook.d.ts +0 -1
- package/dist/hooks/context-window-monitor.d.ts +1 -1
- package/dist/hooks/prometheus-md-only/hook.d.ts +1 -1
- package/dist/hooks/todo-continuation-enforcer/continuation-injection.d.ts +0 -1
- package/dist/hooks/todo-continuation-enforcer/countdown.d.ts +0 -1
- package/dist/hooks/todo-continuation-enforcer/handler.d.ts +0 -1
- package/dist/hooks/todo-continuation-enforcer/idle-event.d.ts +0 -1
- package/dist/hooks/todo-continuation-enforcer/types.d.ts +0 -1
- package/dist/index.js +83 -92
- package/dist/tools/call-omo-agent/constants.d.ts +1 -1
- package/package.json +1 -1
- package/dist/shared/locales/zh-CN/system-directive.d.ts +0 -5
package/dist/cli/index.js
CHANGED
|
@@ -53770,7 +53770,7 @@ var {
|
|
|
53770
53770
|
// package.json
|
|
53771
53771
|
var package_default = {
|
|
53772
53772
|
name: "@skj1724/oh-my-opencode",
|
|
53773
|
-
version: "3.18.
|
|
53773
|
+
version: "3.18.7",
|
|
53774
53774
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
53775
53775
|
main: "./dist/index.js",
|
|
53776
53776
|
types: "dist/index.d.ts",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const GIT_MASTER_COMMIT_WORKFLOW_SECTION = "## PHASE 0: Parallel Context Gathering (MANDATORY FIRST STEP)\n\n<parallel_analysis>\n**Execute ALL of the following commands IN PARALLEL to minimize latency:**\n\n```bash\n# Group 1: Current state\ngit status\ngit diff --staged --stat\ngit diff --stat\n\n# Group 2: History context \ngit log -30 --oneline\ngit log -30 --pretty=format:\"%s\"\n\n# Group 3: Branch context\ngit branch --show-current\ngit merge-base HEAD main 2>/dev/null || git merge-base HEAD master 2>/dev/null\ngit rev-parse --abbrev-ref @{upstream} 2>/dev/null || echo \"NO_UPSTREAM\"\ngit log --oneline $(git merge-base HEAD main 2>/dev/null || git merge-base HEAD master 2>/dev/null)..HEAD 2>/dev/null\n```\n\n**Capture these data points simultaneously:**\n1. What files changed (staged vs unstaged)\n2. Recent 30 commit messages for style detection\n3. Branch position relative to main/master\n4. Whether branch has upstream tracking\n5. Commits that would go in PR (local only)\n</parallel_analysis>\n\n---\n\n## PHASE 1: Style Detection (BLOCKING - MUST OUTPUT BEFORE PROCEEDING)\n\n<style_detection>\n**THIS PHASE HAS MANDATORY OUTPUT** - You MUST print the analysis result before moving to Phase 2.\n\n### 1.1 Language Detection\n\n```\nCount from git log -30:\n- Korean characters: N commits\n- English only: M commits\n- Mixed: K commits\n\nDECISION:\n- If Korean >= 50% -> KOREAN\n- If English >= 50% -> ENGLISH \n- If Mixed -> Use MAJORITY language\n```\n\n### 1.2 Commit Style Classification\n\n| Style | Pattern | Example | Detection Regex |\n|-------|---------|---------|-----------------|\n| `SEMANTIC` | `type: message` or `type(scope): message` | `feat: add login` | `/^(feat\\|fix\\|chore\\|refactor\\|docs\\|test\\|ci\\|style\\|perf\\|build)(\\(.+\\))?:/` |\n| `PLAIN` | Just description, no prefix | `Add login feature` | No conventional prefix, >3 words |\n| `SENTENCE` | Full sentence style | `Implemented the new login flow` | Complete grammatical sentence |\n| `SHORT` | Minimal keywords | `format`, `lint` | 1-3 words only |\n\n**Detection Algorithm:**\n```\nsemantic_count = commits matching semantic regex\nplain_count = non-semantic commits with >3 words\nshort_count = commits with <=3 words\n\nIF semantic_count >= 15 (50%): STYLE = SEMANTIC\nELSE IF plain_count >= 15: STYLE = PLAIN \nELSE IF short_count >= 10: STYLE = SHORT\nELSE: STYLE = PLAIN (safe default)\n```\n\n### 1.3 MANDATORY OUTPUT (BLOCKING)\n\n**You MUST output this block before proceeding to Phase 2. NO EXCEPTIONS.**\n\n```\nSTYLE DETECTION RESULT\n======================\nAnalyzed: 30 commits from git log\n\nLanguage: [KOREAN | ENGLISH]\n - Korean commits: N (X%)\n - English commits: M (Y%)\n\nStyle: [SEMANTIC | PLAIN | SENTENCE | SHORT]\n - Semantic (feat:, fix:, etc): N (X%)\n - Plain: M (Y%)\n - Short: K (Z%)\n\nReference examples from repo:\n 1. \"actual commit message from log\"\n 2. \"actual commit message from log\"\n 3. \"actual commit message from log\"\n\nAll commits will follow: [LANGUAGE] + [STYLE]\n```\n\n**IF YOU SKIP THIS OUTPUT, YOUR COMMITS WILL BE WRONG. STOP AND REDO.**\n</style_detection>\n\n---\n\n## PHASE 2: Branch Context Analysis\n\n<branch_analysis>\n### 2.1 Determine Branch State\n\n```\nBRANCH_STATE:\n current_branch: <name>\n has_upstream: true | false\n commits_ahead: N # Local-only commits\n merge_base: <hash>\n \nREWRITE_SAFETY:\n - If has_upstream AND commits_ahead > 0 AND already pushed:\n -> WARN before force push\n - If no upstream OR all commits local:\n -> Safe for aggressive rewrite (fixup, reset, rebase)\n - If on main/master:\n -> NEVER rewrite, only new commits\n```\n\n### 2.2 History Rewrite Strategy Decision\n\n```\nIF current_branch == main OR current_branch == master:\n -> STRATEGY = NEW_COMMITS_ONLY\n -> Never fixup, never rebase\n\nELSE IF commits_ahead == 0:\n -> STRATEGY = NEW_COMMITS_ONLY\n -> No history to rewrite\n\nELSE IF all commits are local (not pushed):\n -> STRATEGY = AGGRESSIVE_REWRITE\n -> Fixup freely, reset if needed, rebase to clean\n\nELSE IF pushed but not merged:\n -> STRATEGY = CAREFUL_REWRITE \n -> Fixup OK but warn about force push\n```\n</branch_analysis>\n\n---\n\n## PHASE 3: Atomic Unit Planning (BLOCKING - MUST OUTPUT BEFORE PROCEEDING)\n\n<atomic_planning>\n**THIS PHASE HAS MANDATORY OUTPUT** - You MUST print the commit plan before moving to Phase 4.\n\n### 3.0 Calculate Minimum Commit Count FIRST\n\n```\nFORMULA: min_commits = ceil(file_count / 3)\n\n 3 files -> min 1 commit\n 5 files -> min 2 commits\n 9 files -> min 3 commits\n15 files -> min 5 commits\n```\n\n**If your planned commit count < min_commits -> WRONG. SPLIT MORE.**\n\n### 3.1 Split by Directory/Module FIRST (Primary Split)\n\n**RULE: Different directories = Different commits (almost always)**\n\n```\nExample: 8 changed files\n - app/[locale]/page.tsx\n - app/[locale]/layout.tsx\n - components/demo/browser-frame.tsx\n - components/demo/shopify-full-site.tsx\n - components/pricing/pricing-table.tsx\n - e2e/navbar.spec.ts\n - messages/en.json\n - messages/ko.json\n\nWRONG: 1 commit \"Update landing page\" (LAZY, WRONG)\nWRONG: 2 commits (still too few)\n\nCORRECT: Split by directory/concern:\n - Commit 1: app/[locale]/page.tsx + layout.tsx (app layer)\n - Commit 2: components/demo/* (demo components)\n - Commit 3: components/pricing/* (pricing components)\n - Commit 4: e2e/* (tests)\n - Commit 5: messages/* (i18n)\n = 5 commits from 8 files (CORRECT)\n```\n\n### 3.2 Split by Concern SECOND (Secondary Split)\n\n**Within same directory, split by logical concern:**\n\n```\nExample: components/demo/ has 4 files\n - browser-frame.tsx (UI frame)\n - shopify-full-site.tsx (specific demo)\n - review-dashboard.tsx (NEW - specific demo)\n - tone-settings.tsx (NEW - specific demo)\n\nOption A (acceptable): 1 commit if ALL tightly coupled\nOption B (preferred): 2 commits\n - Commit: \"Update existing demo components\" (browser-frame, shopify)\n - Commit: \"Add new demo components\" (review-dashboard, tone-settings)\n```\n\n### 3.3 NEVER Do This (Anti-Pattern Examples)\n\n```\nWRONG: \"Refactor entire landing page\" - 1 commit with 15 files\nWRONG: \"Update components and tests\" - 1 commit mixing concerns\nWRONG: \"Big update\" - Any commit touching 5+ unrelated files\n\nRIGHT: Multiple focused commits, each 1-4 files max\nRIGHT: Each commit message describes ONE specific change\nRIGHT: A reviewer can understand each commit in 30 seconds\n```\n\n### 3.4 Implementation + Test Pairing (MANDATORY)\n\n```\nRULE: Test files MUST be in same commit as implementation\n\nTest patterns to match:\n- test_*.py <-> *.py\n- *_test.py <-> *.py\n- *.test.ts <-> *.ts\n- *.spec.ts <-> *.ts\n- __tests__/*.ts <-> *.ts\n- tests/*.py <-> src/*.py\n```\n\n### 3.5 MANDATORY JUSTIFICATION (Before Creating Commit Plan)\n\n**NON-NEGOTIABLE: Before finalizing your commit plan, you MUST:**\n\n```\nFOR EACH planned commit with 3+ files:\n 1. List all files in this commit\n 2. Write ONE sentence explaining why they MUST be together\n 3. If you can't write that sentence -> SPLIT\n \nTEMPLATE:\n\"Commit N contains [files] because [specific reason they are inseparable].\"\n\nVALID reasons:\n VALID: \"implementation file + its direct test file\"\n VALID: \"type definition + the only file that uses it\"\n VALID: \"migration + model change (would break without both)\"\n \nINVALID reasons (MUST SPLIT instead):\n INVALID: \"all related to feature X\" (too vague)\n INVALID: \"part of the same PR\" (not a reason)\n INVALID: \"they were changed together\" (not a reason)\n INVALID: \"makes sense to group\" (not a reason)\n```\n\n**OUTPUT THIS JUSTIFICATION in your analysis before executing commits.**\n\n### 3.7 Dependency Ordering\n\n```\nLevel 0: Utilities, constants, type definitions\nLevel 1: Models, schemas, interfaces\nLevel 2: Services, business logic\nLevel 3: API endpoints, controllers\nLevel 4: Configuration, infrastructure\n\nCOMMIT ORDER: Level 0 -> Level 1 -> Level 2 -> Level 3 -> Level 4\n```\n\n### 3.8 Create Commit Groups\n\nFor each logical feature/change:\n```yaml\n- group_id: 1\n feature: \"Add Shopify discount deletion\"\n files:\n - errors/shopify_error.py\n - types/delete_input.py\n - mutations/update_contract.py\n - tests/test_update_contract.py\n dependency_level: 2\n target_commit: null | <existing-hash> # null = new, hash = fixup\n```\n\n### 3.9 MANDATORY OUTPUT (BLOCKING)\n\n**You MUST output this block before proceeding to Phase 4. NO EXCEPTIONS.**\n\n```\nCOMMIT PLAN\n===========\nFiles changed: N\nMinimum commits required: ceil(N/3) = M\nPlanned commits: K\nStatus: K >= M (PASS) | K < M (FAIL - must split more)\n\nCOMMIT 1: [message in detected style]\n - path/to/file1.py\n - path/to/file1_test.py\n Justification: implementation + its test\n\nCOMMIT 2: [message in detected style]\n - path/to/file2.py\n Justification: independent utility function\n\nCOMMIT 3: [message in detected style]\n - config/settings.py\n - config/constants.py\n Justification: tightly coupled config changes\n\nExecution order: Commit 1 -> Commit 2 -> Commit 3\n(follows dependency: Level 0 -> Level 1 -> Level 2 -> ...)\n```\n\n**VALIDATION BEFORE EXECUTION:**\n- Each commit has <=4 files (or justified)\n- Each commit message matches detected STYLE + LANGUAGE\n- Test files paired with implementation\n- Different directories = different commits (or justified)\n- Total commits >= min_commits\n\n**IF ANY CHECK FAILS, DO NOT PROCEED. REPLAN.**\n</atomic_planning>\n\n---\n\n## PHASE 4: Commit Strategy Decision\n\n<strategy_decision>\n### 4.1 For Each Commit Group, Decide:\n\n```\nFIXUP if:\n - Change complements existing commit's intent\n - Same feature, fixing bugs or adding missing parts\n - Review feedback incorporation\n - Target commit exists in local history\n\nNEW COMMIT if:\n - New feature or capability\n - Independent logical unit\n - Different issue/ticket\n - No suitable target commit exists\n```\n\n### 4.2 History Rebuild Decision (Aggressive Option)\n\n```\nCONSIDER RESET & REBUILD when:\n - History is messy (many small fixups already)\n - Commits are not atomic (mixed concerns)\n - Dependency order is wrong\n \nRESET WORKFLOW:\n 1. git reset --soft $(git merge-base HEAD main)\n 2. All changes now staged\n 3. Re-commit in proper atomic units\n 4. Clean history from scratch\n \nONLY IF:\n - All commits are local (not pushed)\n - User explicitly allows OR branch is clearly WIP\n```\n\n### 4.3 Final Plan Summary\n\n```yaml\nEXECUTION_PLAN:\n strategy: FIXUP_THEN_NEW | NEW_ONLY | RESET_REBUILD\n fixup_commits:\n - files: [...]\n target: <hash>\n new_commits:\n - files: [...]\n message: \"...\"\n level: N\n requires_force_push: true | false\n```\n</strategy_decision>\n\n---\n\n## PHASE 5: Commit Execution\n\n<execution>\n### 5.1 Register TODO Items\n\nUse TodoWrite to register each commit as a trackable item:\n```\n- [ ] Fixup: <description> -> <target-hash>\n- [ ] New: <description>\n- [ ] Rebase autosquash\n- [ ] Final verification\n```\n\n### 5.2 Fixup Commits (If Any)\n\n```bash\n# Stage files for each fixup\ngit add <files>\ngit commit --fixup=<target-hash>\n\n# Repeat for all fixups...\n\n# Single autosquash rebase at the end\nMERGE_BASE=$(git merge-base HEAD main 2>/dev/null || git merge-base HEAD master)\nGIT_SEQUENCE_EDITOR=: git rebase -i --autosquash $MERGE_BASE\n```\n\n### 5.3 New Commits (After Fixups)\n\nFor each new commit group, in dependency order:\n\n```bash\n# Stage files\ngit add <file1> <file2> ...\n\n# Verify staging\ngit diff --staged --stat\n\n# Commit with detected style\ngit commit -m \"<message-matching-COMMIT_CONFIG>\"\n\n# Verify\ngit log -1 --oneline\n```\n\n### 5.4 Commit Message Generation\n\n**Based on COMMIT_CONFIG from Phase 1:**\n\n```\nIF style == SEMANTIC AND language == KOREAN:\n -> \"feat: \uB85C\uADF8\uC778 \uAE30\uB2A5 \uCD94\uAC00\"\n \nIF style == SEMANTIC AND language == ENGLISH:\n -> \"feat: add login feature\"\n \nIF style == PLAIN AND language == KOREAN:\n -> \"\uB85C\uADF8\uC778 \uAE30\uB2A5 \uCD94\uAC00\"\n \nIF style == PLAIN AND language == ENGLISH:\n -> \"Add login feature\"\n \nIF style == SHORT:\n -> \"format\" / \"type fix\" / \"lint\"\n```\n\n**VALIDATION before each commit:**\n1. Does message match detected style?\n2. Does language match detected language?\n3. Is it similar to examples from git log?\n\nIf ANY check fails -> REWRITE message.\n```\n</execution>\n\n---\n\n## PHASE 6: Verification & Cleanup\n\n<verification>\n### 6.1 Post-Commit Verification\n\n```bash\n# Check working directory clean\ngit status\n\n# Review new history\ngit log --oneline $(git merge-base HEAD main 2>/dev/null || git merge-base HEAD master)..HEAD\n\n# Verify each commit is atomic\n# (mentally check: can each be reverted independently?)\n```\n\n### 6.2 Force Push Decision\n\n```\nIF fixup was used AND branch has upstream:\n -> Requires: git push --force-with-lease\n -> WARN user about force push implications\n \nIF only new commits:\n -> Regular: git push\n```\n\n### 6.3 Final Report\n\n```\nCOMMIT SUMMARY:\n Strategy: <what was done>\n Commits created: N\n Fixups merged: M\n \nHISTORY:\n <hash1> <message1>\n <hash2> <message2>\n ...\n\nNEXT STEPS:\n - git push [--force-with-lease]\n - Create PR if ready\n```\n</verification>";
|
|
1
|
+
export declare const GIT_MASTER_COMMIT_WORKFLOW_SECTION = "## PHASE 0: Parallel Context Gathering (MANDATORY FIRST STEP)\n\n<parallel_analysis>\n**Execute ALL of the following commands IN PARALLEL to minimize latency:**\n\n```bash\n# Group 1: Current state\ngit status\ngit diff --staged --stat\ngit diff --stat\n\n# Group 2: History context \ngit log -30 --oneline\ngit log -30 --pretty=format:\"%s\"\n\n# Group 3: Branch context\ngit branch --show-current\ngit merge-base HEAD main 2>/dev/null || git merge-base HEAD master 2>/dev/null\ngit rev-parse --abbrev-ref @{upstream} 2>/dev/null || echo \"NO_UPSTREAM\"\ngit log --oneline $(git merge-base HEAD main 2>/dev/null || git merge-base HEAD master 2>/dev/null)..HEAD 2>/dev/null\n```\n\n**Capture these data points simultaneously:**\n1. What files changed (staged vs unstaged)\n2. Recent 30 commit messages for style detection\n3. Branch position relative to main/master\n4. Whether branch has upstream tracking\n5. Commits that would go in PR (local only)\n</parallel_analysis>\n\n---\n\n## PHASE 1: Style Detection (BLOCKING - MUST OUTPUT BEFORE PROCEEDING)\n\n<style_detection>\n**THIS PHASE HAS MANDATORY OUTPUT** - You MUST print the analysis result before moving to Phase 2.\n\n### 1.1 Language Detection\n\n```\nCount from git log -30:\n- Chinese characters (\\u4e00-\\u9fff): N commits\n- English only: K commits\n- Mixed: L commits\n\nDECISION:\n- If Chinese >= 50% -> CHINESE\n- If English >= 50% -> ENGLISH\n- If Mixed -> Use MAJORITY language\n```\n\n### 1.2 Commit Style Classification\n\n| Style | Pattern | Example | Detection Regex |\n|-------|---------|---------|-----------------|\n| `SEMANTIC` | `type: message` or `type(scope): message` | `feat: add login` | `/^(feat\\|fix\\|chore\\|refactor\\|docs\\|test\\|ci\\|style\\|perf\\|build)(\\(.+\\))?:/` |\n| `PLAIN` | Just description, no prefix | `Add login feature` | No conventional prefix, >3 words |\n| `SENTENCE` | Full sentence style | `Implemented the new login flow` | Complete grammatical sentence |\n| `SHORT` | Minimal keywords | `format`, `lint` | 1-3 words only |\n\n**Detection Algorithm:**\n```\nsemantic_count = commits matching semantic regex\nplain_count = non-semantic commits with >3 words\nshort_count = commits with <=3 words\n\nIF semantic_count >= 15 (50%): STYLE = SEMANTIC\nELSE IF plain_count >= 15: STYLE = PLAIN \nELSE IF short_count >= 10: STYLE = SHORT\nELSE: STYLE = PLAIN (safe default)\n```\n\n### 1.3 MANDATORY OUTPUT (BLOCKING)\n\n**You MUST output this block before proceeding to Phase 2. NO EXCEPTIONS.**\n\n```\nSTYLE DETECTION RESULT\n======================\nAnalyzed: 30 commits from git log\n\nLanguage: [CHINESE | ENGLISH]\n - Chinese commits: N (X%)\n - English commits: K (Z%)\n\nStyle: [SEMANTIC | PLAIN | SENTENCE | SHORT]\n - Semantic (feat:, fix:, etc): N (X%)\n - Plain: M (Y%)\n - Short: K (Z%)\n\nReference examples from repo:\n 1. \"actual commit message from log\"\n 2. \"actual commit message from log\"\n 3. \"actual commit message from log\"\n\nAll commits will follow: [LANGUAGE] + [STYLE]\n```\n\n**IF YOU SKIP THIS OUTPUT, YOUR COMMITS WILL BE WRONG. STOP AND REDO.**\n</style_detection>\n\n---\n\n## PHASE 2: Branch Context Analysis\n\n<branch_analysis>\n### 2.1 Determine Branch State\n\n```\nBRANCH_STATE:\n current_branch: <name>\n has_upstream: true | false\n commits_ahead: N # Local-only commits\n merge_base: <hash>\n \nREWRITE_SAFETY:\n - If has_upstream AND commits_ahead > 0 AND already pushed:\n -> WARN before force push\n - If no upstream OR all commits local:\n -> Safe for aggressive rewrite (fixup, reset, rebase)\n - If on main/master:\n -> NEVER rewrite, only new commits\n```\n\n### 2.2 History Rewrite Strategy Decision\n\n```\nIF current_branch == main OR current_branch == master:\n -> STRATEGY = NEW_COMMITS_ONLY\n -> Never fixup, never rebase\n\nELSE IF commits_ahead == 0:\n -> STRATEGY = NEW_COMMITS_ONLY\n -> No history to rewrite\n\nELSE IF all commits are local (not pushed):\n -> STRATEGY = AGGRESSIVE_REWRITE\n -> Fixup freely, reset if needed, rebase to clean\n\nELSE IF pushed but not merged:\n -> STRATEGY = CAREFUL_REWRITE \n -> Fixup OK but warn about force push\n```\n</branch_analysis>\n\n---\n\n## PHASE 3: Atomic Unit Planning (BLOCKING - MUST OUTPUT BEFORE PROCEEDING)\n\n<atomic_planning>\n**THIS PHASE HAS MANDATORY OUTPUT** - You MUST print the commit plan before moving to Phase 4.\n\n### 3.0 Calculate Minimum Commit Count FIRST\n\n```\nFORMULA: min_commits = ceil(file_count / 3)\n\n 3 files -> min 1 commit\n 5 files -> min 2 commits\n 9 files -> min 3 commits\n15 files -> min 5 commits\n```\n\n**If your planned commit count < min_commits -> WRONG. SPLIT MORE.**\n\n### 3.1 Split by Directory/Module FIRST (Primary Split)\n\n**RULE: Different directories = Different commits (almost always)**\n\n```\nExample: 8 changed files\n - app/[locale]/page.tsx\n - app/[locale]/layout.tsx\n - components/demo/browser-frame.tsx\n - components/demo/shopify-full-site.tsx\n - components/pricing/pricing-table.tsx\n - e2e/navbar.spec.ts\n - messages/en.json\n - messages/ko.json\n\nWRONG: 1 commit \"Update landing page\" (LAZY, WRONG)\nWRONG: 2 commits (still too few)\n\nCORRECT: Split by directory/concern:\n - Commit 1: app/[locale]/page.tsx + layout.tsx (app layer)\n - Commit 2: components/demo/* (demo components)\n - Commit 3: components/pricing/* (pricing components)\n - Commit 4: e2e/* (tests)\n - Commit 5: messages/* (i18n)\n = 5 commits from 8 files (CORRECT)\n```\n\n### 3.2 Split by Concern SECOND (Secondary Split)\n\n**Within same directory, split by logical concern:**\n\n```\nExample: components/demo/ has 4 files\n - browser-frame.tsx (UI frame)\n - shopify-full-site.tsx (specific demo)\n - review-dashboard.tsx (NEW - specific demo)\n - tone-settings.tsx (NEW - specific demo)\n\nOption A (acceptable): 1 commit if ALL tightly coupled\nOption B (preferred): 2 commits\n - Commit: \"Update existing demo components\" (browser-frame, shopify)\n - Commit: \"Add new demo components\" (review-dashboard, tone-settings)\n```\n\n### 3.3 NEVER Do This (Anti-Pattern Examples)\n\n```\nWRONG: \"Refactor entire landing page\" - 1 commit with 15 files\nWRONG: \"Update components and tests\" - 1 commit mixing concerns\nWRONG: \"Big update\" - Any commit touching 5+ unrelated files\n\nRIGHT: Multiple focused commits, each 1-4 files max\nRIGHT: Each commit message describes ONE specific change\nRIGHT: A reviewer can understand each commit in 30 seconds\n```\n\n### 3.4 Implementation + Test Pairing (MANDATORY)\n\n```\nRULE: Test files MUST be in same commit as implementation\n\nTest patterns to match:\n- test_*.py <-> *.py\n- *_test.py <-> *.py\n- *.test.ts <-> *.ts\n- *.spec.ts <-> *.ts\n- __tests__/*.ts <-> *.ts\n- tests/*.py <-> src/*.py\n```\n\n### 3.5 MANDATORY JUSTIFICATION (Before Creating Commit Plan)\n\n**NON-NEGOTIABLE: Before finalizing your commit plan, you MUST:**\n\n```\nFOR EACH planned commit with 3+ files:\n 1. List all files in this commit\n 2. Write ONE sentence explaining why they MUST be together\n 3. If you can't write that sentence -> SPLIT\n \nTEMPLATE:\n\"Commit N contains [files] because [specific reason they are inseparable].\"\n\nVALID reasons:\n VALID: \"implementation file + its direct test file\"\n VALID: \"type definition + the only file that uses it\"\n VALID: \"migration + model change (would break without both)\"\n \nINVALID reasons (MUST SPLIT instead):\n INVALID: \"all related to feature X\" (too vague)\n INVALID: \"part of the same PR\" (not a reason)\n INVALID: \"they were changed together\" (not a reason)\n INVALID: \"makes sense to group\" (not a reason)\n```\n\n**OUTPUT THIS JUSTIFICATION in your analysis before executing commits.**\n\n### 3.7 Dependency Ordering\n\n```\nLevel 0: Utilities, constants, type definitions\nLevel 1: Models, schemas, interfaces\nLevel 2: Services, business logic\nLevel 3: API endpoints, controllers\nLevel 4: Configuration, infrastructure\n\nCOMMIT ORDER: Level 0 -> Level 1 -> Level 2 -> Level 3 -> Level 4\n```\n\n### 3.8 Create Commit Groups\n\nFor each logical feature/change:\n```yaml\n- group_id: 1\n feature: \"Add Shopify discount deletion\"\n files:\n - errors/shopify_error.py\n - types/delete_input.py\n - mutations/update_contract.py\n - tests/test_update_contract.py\n dependency_level: 2\n target_commit: null | <existing-hash> # null = new, hash = fixup\n```\n\n### 3.9 MANDATORY OUTPUT (BLOCKING)\n\n**You MUST output this block before proceeding to Phase 4. NO EXCEPTIONS.**\n\n```\nCOMMIT PLAN\n===========\nFiles changed: N\nMinimum commits required: ceil(N/3) = M\nPlanned commits: K\nStatus: K >= M (PASS) | K < M (FAIL - must split more)\n\nCOMMIT 1: [message in detected style]\n - path/to/file1.py\n - path/to/file1_test.py\n Justification: implementation + its test\n\nCOMMIT 2: [message in detected style]\n - path/to/file2.py\n Justification: independent utility function\n\nCOMMIT 3: [message in detected style]\n - config/settings.py\n - config/constants.py\n Justification: tightly coupled config changes\n\nExecution order: Commit 1 -> Commit 2 -> Commit 3\n(follows dependency: Level 0 -> Level 1 -> Level 2 -> ...)\n```\n\n**VALIDATION BEFORE EXECUTION:**\n- Each commit has <=4 files (or justified)\n- Each commit message matches detected STYLE + LANGUAGE\n- Test files paired with implementation\n- Different directories = different commits (or justified)\n- Total commits >= min_commits\n\n**IF ANY CHECK FAILS, DO NOT PROCEED. REPLAN.**\n</atomic_planning>\n\n---\n\n## PHASE 4: Commit Strategy Decision\n\n<strategy_decision>\n### 4.1 For Each Commit Group, Decide:\n\n```\nFIXUP if:\n - Change complements existing commit's intent\n - Same feature, fixing bugs or adding missing parts\n - Review feedback incorporation\n - Target commit exists in local history\n\nNEW COMMIT if:\n - New feature or capability\n - Independent logical unit\n - Different issue/ticket\n - No suitable target commit exists\n```\n\n### 4.2 History Rebuild Decision (Aggressive Option)\n\n```\nCONSIDER RESET & REBUILD when:\n - History is messy (many small fixups already)\n - Commits are not atomic (mixed concerns)\n - Dependency order is wrong\n \nRESET WORKFLOW:\n 1. git reset --soft $(git merge-base HEAD main)\n 2. All changes now staged\n 3. Re-commit in proper atomic units\n 4. Clean history from scratch\n \nONLY IF:\n - All commits are local (not pushed)\n - User explicitly allows OR branch is clearly WIP\n```\n\n### 4.3 Final Plan Summary\n\n```yaml\nEXECUTION_PLAN:\n strategy: FIXUP_THEN_NEW | NEW_ONLY | RESET_REBUILD\n fixup_commits:\n - files: [...]\n target: <hash>\n new_commits:\n - files: [...]\n message: \"...\"\n level: N\n requires_force_push: true | false\n```\n</strategy_decision>\n\n---\n\n## PHASE 5: Commit Execution\n\n<execution>\n### 5.1 Register TODO Items\n\nUse TodoWrite to register each commit as a trackable item:\n```\n- [ ] Fixup: <description> -> <target-hash>\n- [ ] New: <description>\n- [ ] Rebase autosquash\n- [ ] Final verification\n```\n\n### 5.2 Fixup Commits (If Any)\n\n```bash\n# Stage files for each fixup\ngit add <files>\ngit commit --fixup=<target-hash>\n\n# Repeat for all fixups...\n\n# Single autosquash rebase at the end\nMERGE_BASE=$(git merge-base HEAD main 2>/dev/null || git merge-base HEAD master)\nGIT_SEQUENCE_EDITOR=: git rebase -i --autosquash $MERGE_BASE\n```\n\n### 5.3 New Commits (After Fixups)\n\nFor each new commit group, in dependency order:\n\n```bash\n# Stage files\ngit add <file1> <file2> ...\n\n# Verify staging\ngit diff --staged --stat\n\n# Commit with detected style\ngit commit -m \"<message-matching-COMMIT_CONFIG>\"\n\n# Verify\ngit log -1 --oneline\n```\n\n### 5.4 Commit Message Generation\n\n**Based on COMMIT_CONFIG from Phase 1:**\n\n```\nIF style == SEMANTIC AND language == CHINESE:\n -> \"feat: \u6DFB\u52A0\u767B\u5F55\u529F\u80FD\"\n \nIF style == SEMANTIC AND language == ENGLISH:\n -> \"feat: add login feature\"\n\nIF style == PLAIN AND language == CHINESE:\n -> \"\u6DFB\u52A0\u767B\u5F55\u529F\u80FD\"\n\nIF style == PLAIN AND language == ENGLISH:\n -> \"Add login feature\"\n\nIF style == SHORT:\n -> \"format\" / \"type fix\" / \"lint\"\n```\n\n**VALIDATION before each commit:**\n1. Does message match detected style?\n2. Does language match detected language?\n3. Is it similar to examples from git log?\n\nIf ANY check fails -> REWRITE message.\n```\n</execution>\n\n---\n\n## PHASE 6: Verification & Cleanup\n\n<verification>\n### 6.1 Post-Commit Verification\n\n```bash\n# Check working directory clean\ngit status\n\n# Review new history\ngit log --oneline $(git merge-base HEAD main 2>/dev/null || git merge-base HEAD master)..HEAD\n\n# Verify each commit is atomic\n# (mentally check: can each be reverted independently?)\n```\n\n### 6.2 Force Push Decision\n\n```\nIF fixup was used AND branch has upstream:\n -> Requires: git push --force-with-lease\n -> WARN user about force push implications\n \nIF only new commits:\n -> Regular: git push\n```\n\n### 6.3 Final Report\n\n```\nCOMMIT SUMMARY:\n Strategy: <what was done>\n Commits created: N\n Fixups merged: M\n \nHISTORY:\n <hash1> <message1>\n <hash2> <message2>\n ...\n\nNEXT STEPS:\n - git push [--force-with-lease]\n - Create PR if ready\n```\n</verification>";
|
|
@@ -7,5 +7,4 @@ export declare function createToolExecuteAfterHandler(input: {
|
|
|
7
7
|
pendingTaskRefs: Map<string, PendingTaskRef>;
|
|
8
8
|
autoCommit: boolean;
|
|
9
9
|
getState: (sessionID: string) => SessionState;
|
|
10
|
-
language?: string;
|
|
11
10
|
}): (toolInput: ToolExecuteAfterInput, toolOutput: ToolExecuteAfterOutput) => Promise<void>;
|
|
@@ -11,8 +11,8 @@ export interface AtlasHookOptions {
|
|
|
11
11
|
backgroundManager?: BackgroundManager;
|
|
12
12
|
isContinuationStopped?: (sessionID: string) => boolean;
|
|
13
13
|
agentOverrides?: AgentOverrides;
|
|
14
|
+
/** Enable auto-commit after each atomic task completion (default: true) */
|
|
14
15
|
autoCommit?: boolean;
|
|
15
|
-
language?: string;
|
|
16
16
|
}
|
|
17
17
|
export interface ToolExecuteAfterInput {
|
|
18
18
|
tool: string;
|
|
@@ -3,5 +3,4 @@ import type { CompactionContextClient, CompactionContextInjector } from "./types
|
|
|
3
3
|
export declare function createCompactionContextInjector(options?: {
|
|
4
4
|
ctx?: CompactionContextClient;
|
|
5
5
|
backgroundManager?: BackgroundManager;
|
|
6
|
-
language?: string;
|
|
7
6
|
}): CompactionContextInjector;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PluginInput } from "@opencode-ai/plugin";
|
|
2
2
|
import { type ContextLimitModelCacheState } from "../shared/context-limit-resolver";
|
|
3
|
-
export declare function createContextWindowMonitorHook(_ctx: PluginInput, modelCacheState?: ContextLimitModelCacheState
|
|
3
|
+
export declare function createContextWindowMonitorHook(_ctx: PluginInput, modelCacheState?: ContextLimitModelCacheState): {
|
|
4
4
|
"tool.execute.after": (input: {
|
|
5
5
|
tool: string;
|
|
6
6
|
sessionID: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PluginInput } from "@opencode-ai/plugin";
|
|
2
|
-
export declare function createPrometheusMdOnlyHook(ctx: PluginInput
|
|
2
|
+
export declare function createPrometheusMdOnlyHook(ctx: PluginInput): {
|
|
3
3
|
"tool.execute.before": (input: {
|
|
4
4
|
tool: string;
|
|
5
5
|
sessionID: string;
|
package/dist/index.js
CHANGED
|
@@ -66321,7 +66321,7 @@ async function injectContinuation(args) {
|
|
|
66321
66321
|
const incompleteTodos = todos.filter((todo) => todo.status !== "completed" && todo.status !== "cancelled");
|
|
66322
66322
|
const todoList = incompleteTodos.map((todo) => `- [${todo.status}] ${todo.content}`).join(`
|
|
66323
66323
|
`);
|
|
66324
|
-
const prompt = `${getContinuationPrompt(
|
|
66324
|
+
const prompt = `${getContinuationPrompt()}
|
|
66325
66325
|
|
|
66326
66326
|
[Status: ${todos.length - freshIncompleteCount}/${todos.length} completed, ${freshIncompleteCount} remaining]
|
|
66327
66327
|
|
|
@@ -66420,8 +66420,7 @@ function startCountdown(args) {
|
|
|
66420
66420
|
skipAgents,
|
|
66421
66421
|
resolvedInfo,
|
|
66422
66422
|
sessionStateStore,
|
|
66423
|
-
isContinuationStopped
|
|
66424
|
-
language: args.language
|
|
66423
|
+
isContinuationStopped
|
|
66425
66424
|
});
|
|
66426
66425
|
}, COUNTDOWN_SECONDS * 1000);
|
|
66427
66426
|
log(`[${HOOK_NAME}] Countdown started`, {
|
|
@@ -66445,8 +66444,7 @@ async function handleSessionIdle(args) {
|
|
|
66445
66444
|
sessionStateStore,
|
|
66446
66445
|
backgroundManager,
|
|
66447
66446
|
skipAgents = DEFAULT_SKIP_AGENTS,
|
|
66448
|
-
isContinuationStopped
|
|
66449
|
-
language
|
|
66447
|
+
isContinuationStopped
|
|
66450
66448
|
} = args;
|
|
66451
66449
|
log(`[${HOOK_NAME}] session.idle`, { sessionID });
|
|
66452
66450
|
const state2 = sessionStateStore.getState(sessionID);
|
|
@@ -66593,8 +66591,7 @@ async function handleSessionIdle(args) {
|
|
|
66593
66591
|
backgroundManager,
|
|
66594
66592
|
skipAgents,
|
|
66595
66593
|
sessionStateStore,
|
|
66596
|
-
isContinuationStopped
|
|
66597
|
-
language
|
|
66594
|
+
isContinuationStopped
|
|
66598
66595
|
});
|
|
66599
66596
|
}
|
|
66600
66597
|
|
|
@@ -66735,8 +66732,7 @@ function createTodoContinuationHandler(args) {
|
|
|
66735
66732
|
sessionStateStore,
|
|
66736
66733
|
backgroundManager,
|
|
66737
66734
|
skipAgents,
|
|
66738
|
-
isContinuationStopped
|
|
66739
|
-
language: args.language
|
|
66735
|
+
isContinuationStopped
|
|
66740
66736
|
});
|
|
66741
66737
|
return;
|
|
66742
66738
|
}
|
|
@@ -66970,8 +66966,7 @@ function createTodoContinuationEnforcer(ctx, options = {}) {
|
|
|
66970
66966
|
const {
|
|
66971
66967
|
backgroundManager,
|
|
66972
66968
|
skipAgents = DEFAULT_SKIP_AGENTS,
|
|
66973
|
-
isContinuationStopped
|
|
66974
|
-
language
|
|
66969
|
+
isContinuationStopped
|
|
66975
66970
|
} = options;
|
|
66976
66971
|
const sessionStateStore = createSessionStateStore();
|
|
66977
66972
|
const markRecovering = (sessionID) => {
|
|
@@ -66992,8 +66987,7 @@ function createTodoContinuationEnforcer(ctx, options = {}) {
|
|
|
66992
66987
|
sessionStateStore,
|
|
66993
66988
|
backgroundManager,
|
|
66994
66989
|
skipAgents,
|
|
66995
|
-
isContinuationStopped
|
|
66996
|
-
language
|
|
66990
|
+
isContinuationStopped
|
|
66997
66991
|
});
|
|
66998
66992
|
const cancelAllCountdowns = () => {
|
|
66999
66993
|
sessionStateStore.cancelAllCountdowns();
|
|
@@ -67024,7 +67018,7 @@ Complete your work thoroughly and methodically.`;
|
|
|
67024
67018
|
|
|
67025
67019
|
${reminderText}`;
|
|
67026
67020
|
}
|
|
67027
|
-
function createContextWindowMonitorHook(_ctx, modelCacheState
|
|
67021
|
+
function createContextWindowMonitorHook(_ctx, modelCacheState) {
|
|
67028
67022
|
const remindedSessions = new Set;
|
|
67029
67023
|
const tokenCache = new Map;
|
|
67030
67024
|
const toolExecuteAfter = async (input, output) => {
|
|
@@ -67049,7 +67043,7 @@ function createContextWindowMonitorHook(_ctx, modelCacheState, language) {
|
|
|
67049
67043
|
const limitTokens = actualLimit.toLocaleString();
|
|
67050
67044
|
output.output += `
|
|
67051
67045
|
|
|
67052
|
-
${createContextReminder(actualLimit
|
|
67046
|
+
${createContextReminder(actualLimit)}
|
|
67053
67047
|
[Context Status: ${usedPct}% used (${usedTokens}/${limitTokens} tokens), ${remainingPct}% remaining]`;
|
|
67054
67048
|
};
|
|
67055
67049
|
const eventHandler = async ({ event }) => {
|
|
@@ -71155,6 +71149,7 @@ function createAnthropicContextWindowLimitRecoveryHook(ctx, options) {
|
|
|
71155
71149
|
}
|
|
71156
71150
|
// src/hooks/think-mode/detector.ts
|
|
71157
71151
|
var MULTILINGUAL_KEYWORDS = [
|
|
71152
|
+
"\u6DF1\u601D\u719F\u8651",
|
|
71158
71153
|
"\uC0DD\uAC01",
|
|
71159
71154
|
"\uAC80\uD1A0",
|
|
71160
71155
|
"\uC81C\uB300\uB85C",
|
|
@@ -79518,13 +79513,13 @@ git log --oneline $(git merge-base HEAD main 2>/dev/null || git merge-base HEAD
|
|
|
79518
79513
|
|
|
79519
79514
|
\`\`\`
|
|
79520
79515
|
Count from git log -30:
|
|
79521
|
-
-
|
|
79522
|
-
- English only:
|
|
79523
|
-
- Mixed:
|
|
79516
|
+
- Chinese characters (\\u4e00-\\u9fff): N commits
|
|
79517
|
+
- English only: K commits
|
|
79518
|
+
- Mixed: L commits
|
|
79524
79519
|
|
|
79525
79520
|
DECISION:
|
|
79526
|
-
- If
|
|
79527
|
-
- If English >= 50% -> ENGLISH
|
|
79521
|
+
- If Chinese >= 50% -> CHINESE
|
|
79522
|
+
- If English >= 50% -> ENGLISH
|
|
79528
79523
|
- If Mixed -> Use MAJORITY language
|
|
79529
79524
|
\`\`\`
|
|
79530
79525
|
|
|
@@ -79558,9 +79553,9 @@ STYLE DETECTION RESULT
|
|
|
79558
79553
|
======================
|
|
79559
79554
|
Analyzed: 30 commits from git log
|
|
79560
79555
|
|
|
79561
|
-
Language: [
|
|
79562
|
-
-
|
|
79563
|
-
- English commits:
|
|
79556
|
+
Language: [CHINESE | ENGLISH]
|
|
79557
|
+
- Chinese commits: N (X%)
|
|
79558
|
+
- English commits: K (Z%)
|
|
79564
79559
|
|
|
79565
79560
|
Style: [SEMANTIC | PLAIN | SENTENCE | SHORT]
|
|
79566
79561
|
- Semantic (feat:, fix:, etc): N (X%)
|
|
@@ -79914,18 +79909,18 @@ git log -1 --oneline
|
|
|
79914
79909
|
**Based on COMMIT_CONFIG from Phase 1:**
|
|
79915
79910
|
|
|
79916
79911
|
\`\`\`
|
|
79917
|
-
IF style == SEMANTIC AND language ==
|
|
79918
|
-
-> "feat: \
|
|
79912
|
+
IF style == SEMANTIC AND language == CHINESE:
|
|
79913
|
+
-> "feat: \u6DFB\u52A0\u767B\u5F55\u529F\u80FD"
|
|
79919
79914
|
|
|
79920
79915
|
IF style == SEMANTIC AND language == ENGLISH:
|
|
79921
79916
|
-> "feat: add login feature"
|
|
79922
|
-
|
|
79923
|
-
IF style == PLAIN AND language ==
|
|
79924
|
-
-> "\
|
|
79925
|
-
|
|
79917
|
+
|
|
79918
|
+
IF style == PLAIN AND language == CHINESE:
|
|
79919
|
+
-> "\u6DFB\u52A0\u767B\u5F55\u529F\u80FD"
|
|
79920
|
+
|
|
79926
79921
|
IF style == PLAIN AND language == ENGLISH:
|
|
79927
79922
|
-> "Add login feature"
|
|
79928
|
-
|
|
79923
|
+
|
|
79929
79924
|
IF style == SHORT:
|
|
79930
79925
|
-> "format" / "type fix" / "lint"
|
|
79931
79926
|
\`\`\`
|
|
@@ -84959,7 +84954,7 @@ function isAllowedFile(filePath, workspaceRoot) {
|
|
|
84959
84954
|
|
|
84960
84955
|
// src/hooks/prometheus-md-only/hook.ts
|
|
84961
84956
|
var TASK_TOOLS = ["task", "call_omo_agent"];
|
|
84962
|
-
function createPrometheusMdOnlyHook(ctx
|
|
84957
|
+
function createPrometheusMdOnlyHook(ctx) {
|
|
84963
84958
|
return {
|
|
84964
84959
|
"tool.execute.before": async (input, output) => {
|
|
84965
84960
|
const agentName = await getAgentFromSession(input.sessionID, ctx.directory, ctx.client);
|
|
@@ -84970,7 +84965,7 @@ function createPrometheusMdOnlyHook(ctx, language) {
|
|
|
84970
84965
|
if (TASK_TOOLS.includes(toolName)) {
|
|
84971
84966
|
const prompt = output.args.prompt;
|
|
84972
84967
|
if (prompt && !prompt.includes(SYSTEM_DIRECTIVE_PREFIX)) {
|
|
84973
|
-
output.args.prompt = getPlanningConsultWarning(
|
|
84968
|
+
output.args.prompt = getPlanningConsultWarning() + prompt;
|
|
84974
84969
|
log(`[${HOOK_NAME4}] Injected planning warning to ${toolName}`, {
|
|
84975
84970
|
sessionID: input.sessionID,
|
|
84976
84971
|
tool: toolName,
|
|
@@ -85003,7 +84998,7 @@ function createPrometheusMdOnlyHook(ctx, language) {
|
|
|
85003
84998
|
filePath,
|
|
85004
84999
|
agent: agentName
|
|
85005
85000
|
});
|
|
85006
|
-
output.message = (output.message || "") + getPrometheusWorkflowReminder(
|
|
85001
|
+
output.message = (output.message || "") + getPrometheusWorkflowReminder();
|
|
85007
85002
|
}
|
|
85008
85003
|
log(`[${HOOK_NAME4}] Allowed: .sisyphus/*.md write permitted`, {
|
|
85009
85004
|
sessionID: input.sessionID,
|
|
@@ -85963,7 +85958,7 @@ async function injectBoulderContinuation(input) {
|
|
|
85963
85958
|
const preferredSessionContext = preferredTaskSessionId ? `
|
|
85964
85959
|
|
|
85965
85960
|
[Preferred reuse session for current top-level plan task${preferredTaskTitle ? `: ${preferredTaskTitle}` : ""}: ${preferredTaskSessionId}]` : "";
|
|
85966
|
-
const prompt = getBoulderContinuationPrompt(
|
|
85961
|
+
const prompt = getBoulderContinuationPrompt().replace(/{PLAN_NAME}/g, planName) + `
|
|
85967
85962
|
|
|
85968
85963
|
[Status: ${total - remaining}/${total} completed, ${remaining} remaining]` + preferredSessionContext + worktreeContext;
|
|
85969
85964
|
const continuationAgent = resolveRegisteredAgentName(agent ?? (isAgentRegistered("atlas") ? "atlas" : undefined));
|
|
@@ -86075,8 +86070,7 @@ async function injectContinuation2(input) {
|
|
|
86075
86070
|
preferredTaskSessionId: preferredTaskSession?.session_id,
|
|
86076
86071
|
preferredTaskTitle: preferredTaskSession?.task_title,
|
|
86077
86072
|
backgroundManager: input.options?.backgroundManager,
|
|
86078
|
-
sessionState: input.sessionState
|
|
86079
|
-
language: input.options?.language
|
|
86073
|
+
sessionState: input.sessionState
|
|
86080
86074
|
});
|
|
86081
86075
|
if (result === "injected") {
|
|
86082
86076
|
if (input.sessionState.pendingRetryTimer) {
|
|
@@ -86772,7 +86766,7 @@ function createToolExecuteAfterHandler2(input) {
|
|
|
86772
86766
|
filePath = toolOutput.metadata?.filePath;
|
|
86773
86767
|
}
|
|
86774
86768
|
if (filePath && !isSisyphusPath(filePath)) {
|
|
86775
|
-
toolOutput.output = (toolOutput.output || "") + getDirectWorkReminder(
|
|
86769
|
+
toolOutput.output = (toolOutput.output || "") + getDirectWorkReminder();
|
|
86776
86770
|
log(`[${HOOK_NAME7}] Direct work reminder appended`, {
|
|
86777
86771
|
sessionID: toolInput.sessionID,
|
|
86778
86772
|
tool: toolInput.tool,
|
|
@@ -86914,7 +86908,7 @@ function createToolExecuteBeforeHandler2(input) {
|
|
|
86914
86908
|
if (toolInput.callID) {
|
|
86915
86909
|
pendingFilePaths.set(toolInput.callID, filePath);
|
|
86916
86910
|
}
|
|
86917
|
-
const warning = getOrchestratorDelegationRequired(
|
|
86911
|
+
const warning = getOrchestratorDelegationRequired().replace("$FILE_PATH", filePath);
|
|
86918
86912
|
toolOutput.message = (toolOutput.message || "") + warning;
|
|
86919
86913
|
log(`[${HOOK_NAME7}] Injected delegation warning for direct file modification`, {
|
|
86920
86914
|
sessionID: toolInput.sessionID,
|
|
@@ -86961,7 +86955,7 @@ function createToolExecuteBeforeHandler2(input) {
|
|
|
86961
86955
|
}
|
|
86962
86956
|
const prompt = toolOutput.args.prompt;
|
|
86963
86957
|
if (prompt && !prompt.includes(SYSTEM_DIRECTIVE_PREFIX)) {
|
|
86964
|
-
toolOutput.args.prompt = `<system-reminder>${getSingleTaskDirective(
|
|
86958
|
+
toolOutput.args.prompt = `<system-reminder>${getSingleTaskDirective()}</system-reminder>
|
|
86965
86959
|
` + prompt;
|
|
86966
86960
|
log(`[${HOOK_NAME7}] Injected single-task directive to task`, {
|
|
86967
86961
|
sessionID: toolInput.sessionID
|
|
@@ -86987,8 +86981,8 @@ function createAtlasHook(ctx, options) {
|
|
|
86987
86981
|
}
|
|
86988
86982
|
return {
|
|
86989
86983
|
handler: createAtlasEventHandler({ ctx, options, sessions, getState }),
|
|
86990
|
-
"tool.execute.before": createToolExecuteBeforeHandler2({ ctx, pendingFilePaths, pendingTaskRefs
|
|
86991
|
-
"tool.execute.after": createToolExecuteAfterHandler2({ ctx, pendingFilePaths, pendingTaskRefs, autoCommit, getState
|
|
86984
|
+
"tool.execute.before": createToolExecuteBeforeHandler2({ ctx, pendingFilePaths, pendingTaskRefs }),
|
|
86985
|
+
"tool.execute.after": createToolExecuteAfterHandler2({ ctx, pendingFilePaths, pendingTaskRefs, autoCommit, getState })
|
|
86992
86986
|
};
|
|
86993
86987
|
}
|
|
86994
86988
|
// src/hooks/delegate-task-retry/patterns.ts
|
|
@@ -87652,7 +87646,6 @@ function createRecoveryLogic(ctx, getTailState) {
|
|
|
87652
87646
|
function createCompactionContextInjector(options) {
|
|
87653
87647
|
const ctx = options?.ctx;
|
|
87654
87648
|
const backgroundManager = options?.backgroundManager;
|
|
87655
|
-
const language = options?.language;
|
|
87656
87649
|
const tailStates = new Map;
|
|
87657
87650
|
const getTailState = (sessionID) => {
|
|
87658
87651
|
const existing = tailStates.get(sessionID);
|
|
@@ -87684,7 +87677,7 @@ function createCompactionContextInjector(options) {
|
|
|
87684
87677
|
});
|
|
87685
87678
|
};
|
|
87686
87679
|
const inject = (sessionID) => {
|
|
87687
|
-
let prompt = getCompactionContextPrompt(
|
|
87680
|
+
let prompt = getCompactionContextPrompt();
|
|
87688
87681
|
if (backgroundManager && sessionID) {
|
|
87689
87682
|
const history = backgroundManager.taskHistory.formatForCompaction(sessionID);
|
|
87690
87683
|
if (history) {
|
|
@@ -96888,14 +96881,14 @@ var ALLOWED_AGENTS = [
|
|
|
96888
96881
|
"momus",
|
|
96889
96882
|
"multimodal-looker"
|
|
96890
96883
|
];
|
|
96891
|
-
var CALL_OMO_AGENT_DESCRIPTION =
|
|
96884
|
+
var CALL_OMO_AGENT_DESCRIPTION = `\u542F\u52A8 explore/librarian \u4EE3\u7406\u6216\u81EA\u5B9A\u4E49\u4EE3\u7406\u3002\u5FC5\u987B\u63D0\u4F9B run_in_background (true=\u5F02\u6B65\u8FD4\u56DE task_id, false=\u540C\u6B65)\u3002
|
|
96892
96885
|
|
|
96893
|
-
|
|
96886
|
+
\u5185\u7F6E\u4EE3\u7406:
|
|
96894
96887
|
{agents}
|
|
96895
96888
|
|
|
96896
|
-
|
|
96889
|
+
\u4E5F\u652F\u6301\u901A\u8FC7\u7528\u6237\u6216\u9879\u76EE\u4EE3\u7406\u76EE\u5F55\u6CE8\u518C\u7684\u81EA\u5B9A\u4E49\u4EE3\u7406\u3002
|
|
96897
96890
|
|
|
96898
|
-
|
|
96891
|
+
\u4F20\u9012 \`session_id=<id>\` \u53EF\u7EE7\u7EED\u4E4B\u524D\u7684\u4EE3\u7406\u5E76\u4FDD\u7559\u5B8C\u6574\u4E0A\u4E0B\u6587\u3002\u5D4C\u5957 subagent \u6DF1\u5EA6\u81EA\u52A8\u8FFD\u8E2A\uFF0C\u8D85\u8FC7\u914D\u7F6E\u9650\u5236\u540E\u4F1A\u88AB\u963B\u6B62\u3002\u4F7F\u7528 \`background_output\` \u83B7\u53D6\u5F02\u6B65\u7ED3\u679C\u3002**\u63D0\u793A\u8BCD\u5FC5\u987B\u4F7F\u7528\u4E2D\u6587,\u4E0D\u5F97\u4F7F\u7528\u5176\u4ED6\u8BED\u8A00\u3002**`;
|
|
96899
96892
|
// src/tools/call-omo-agent/tools.ts
|
|
96900
96893
|
init_agent_display_names();
|
|
96901
96894
|
|
|
@@ -98194,10 +98187,10 @@ var FREE_OR_LOCAL_PROMPT_TOKEN_LIMIT = 24000;
|
|
|
98194
98187
|
var PLAN_AGENT_PROMPT_BASE = `
|
|
98195
98188
|
|
|
98196
98189
|
Additional requirements for this planning request:
|
|
98197
|
-
-
|
|
98198
|
-
-
|
|
98199
|
-
-
|
|
98200
|
-
-
|
|
98190
|
+
- \u4F7F\u7528\u4E2D\u6587\u56DE\u7B54\u3002
|
|
98191
|
+
- \u4F7F\u7528\u4E2D\u6587\u64B0\u5199\u8BA1\u5212\u3002
|
|
98192
|
+
- \u4E3A\u9AD8\u6548\u5DE5\u4F5C\u505A\u597D\u89C4\u5212\u3002
|
|
98193
|
+
- \u5305\u542B\u6E05\u6670\u7684\u539F\u5B50\u5316\u63D0\u4EA4\u7B56\u7565\u3002`;
|
|
98201
98194
|
var TDD_LINE = "- Use TDD-oriented planning.";
|
|
98202
98195
|
function buildPlanAgentPromptAppend(tddEnabled) {
|
|
98203
98196
|
if (tddEnabled) {
|
|
@@ -100612,46 +100605,46 @@ function createDelegateTaskPresentation(options) {
|
|
|
100612
100605
|
return description2 ? ` - ${name}: ${description2}` : ` - ${name}`;
|
|
100613
100606
|
}).join(`
|
|
100614
100607
|
`);
|
|
100615
|
-
const description =
|
|
100616
|
-
|
|
100617
|
-
\u26A0\uFE0F
|
|
100618
|
-
|
|
100619
|
-
|
|
100608
|
+
const description = `\u57FA\u4E8E\u5206\u7C7B\u6216\u76F4\u63A5\u4EE3\u7406\u9009\u62E9\u7684\u4EFB\u52A1\u521B\u5EFA\u3002
|
|
100609
|
+
|
|
100610
|
+
\u26A0\uFE0F \u91CD\u8981: \u5FC5\u987B\u63D0\u4F9B category \u6216 subagent_type \u4E4B\u4E00\u3002\u4E24\u8005\u90FD\u7701\u7565\u5C06\u5BFC\u81F4\u5931\u8D25\u3002
|
|
100611
|
+
|
|
100612
|
+
**\u5E38\u89C1\u9519\u8BEF (\u8BF7\u52FF\u8FD9\u6837\u505A):**
|
|
100620
100613
|
\`\`\`
|
|
100621
|
-
task(description="...", prompt="...", run_in_background=false) // \u274C
|
|
100614
|
+
task(description="...", prompt="...", run_in_background=false) // \u274C \u5931\u8D25 - \u7F3A\u5C11 category \u548C subagent_type
|
|
100622
100615
|
\`\`\`
|
|
100623
|
-
|
|
100624
|
-
|
|
100616
|
+
|
|
100617
|
+
**\u6B63\u786E\u7528\u6CD5 - \u4F7F\u7528 category:**
|
|
100625
100618
|
\`\`\`
|
|
100626
|
-
task(category="quick", load_skills=[], description="
|
|
100619
|
+
task(category="quick", load_skills=[], description="\u4FEE\u590D\u7C7B\u578B\u9519\u8BEF", prompt="...", run_in_background=false)
|
|
100627
100620
|
\`\`\`
|
|
100628
|
-
|
|
100629
|
-
|
|
100621
|
+
|
|
100622
|
+
**\u6B63\u786E\u7528\u6CD5 - \u4F7F\u7528 subagent_type:**
|
|
100630
100623
|
\`\`\`
|
|
100631
|
-
task(subagent_type="explore", load_skills=[], description="
|
|
100624
|
+
task(subagent_type="explore", load_skills=[], description="\u67E5\u627E\u6A21\u5F0F", prompt="...", run_in_background=true)
|
|
100632
100625
|
\`\`\`
|
|
100633
|
-
|
|
100634
|
-
|
|
100635
|
-
- category:
|
|
100636
|
-
- subagent_type:
|
|
100637
|
-
|
|
100638
|
-
**
|
|
100639
|
-
|
|
100640
|
-
- load_skills:
|
|
100641
|
-
- category:
|
|
100642
|
-
|
|
100626
|
+
|
|
100627
|
+
\u5FC5\u987B\u63D0\u4F9B\u4EE5\u4E0B\u4E4B\u4E00:
|
|
100628
|
+
- category: \u4EFB\u52A1\u59D4\u6258 (\u4F7F\u7528 Sisyphus-Junior \u53CA\u5206\u7C7B\u4F18\u5316\u6A21\u578B)
|
|
100629
|
+
- subagent_type: \u76F4\u63A5\u8C03\u7528\u4EE3\u7406 (explore, librarian, oracle \u7B49)
|
|
100630
|
+
|
|
100631
|
+
**\u4E0D\u8981\u540C\u65F6\u63D0\u4F9B\u4E24\u8005\u3002** \u5982\u679C\u63D0\u4F9B\u4E86 category\uFF0C\u5219 subagent_type \u4F1A\u88AB\u5FFD\u7565\u3002
|
|
100632
|
+
|
|
100633
|
+
- load_skills: \u59CB\u7EC8\u5FC5\u987B\u3002\u65E0\u9700\u6280\u80FD\u65F6\u4F20\u9012 []\uFF0C\u5206\u7C7B\u4EFB\u52A1\u53EF\u4F20\u9012 ["skill-1", "skill-2"]\u3002
|
|
100634
|
+
- category: \u4F7F\u7528\u9884\u5B9A\u4E49\u5206\u7C7B \u2192 \u542F\u52A8 Sisyphus-Junior \u5E76\u5E94\u7528\u5206\u7C7B\u914D\u7F6E
|
|
100635
|
+
\u53EF\u7528\u5206\u7C7B:
|
|
100643
100636
|
${categoryList}
|
|
100644
|
-
- subagent_type:
|
|
100645
|
-
- run_in_background:
|
|
100646
|
-
- task_id:
|
|
100647
|
-
- command:
|
|
100648
|
-
|
|
100649
|
-
|
|
100650
|
-
-
|
|
100651
|
-
-
|
|
100652
|
-
-
|
|
100653
|
-
|
|
100654
|
-
|
|
100637
|
+
- subagent_type: \u76F4\u63A5\u4F7F\u7528\u6307\u5B9A\u4EE3\u7406 (explore, librarian, oracle, metis, momus)
|
|
100638
|
+
- run_in_background: \u5FC5\u987B\u63D0\u4F9B\u3002true=\u5F02\u6B65 (\u8FD4\u56DE task_id), false=\u540C\u6B65 (\u7B49\u5F85\u7ED3\u679C)\u3002\u4EC5\u5728\u5E76\u884C\u63A2\u7D22 (5+ \u4E2A\u72EC\u7ACB\u67E5\u8BE2) \u65F6\u4F7F\u7528 background=true\u3002
|
|
100639
|
+
- task_id: \u7EE7\u7EED\u73B0\u6709\u4EFB\u52A1 (\u6765\u81EA\u4E4B\u524D\u7684\u4EFB\u52A1\u8F93\u51FA)\u3002\u7EE7\u7EED\u540C\u4E00 subagent \u4F1A\u8BDD\uFF0C\u5B8C\u6574\u4FDD\u7559\u4E0A\u4E0B\u6587\u3002
|
|
100640
|
+
- command: \u89E6\u53D1\u6B64\u4EFB\u52A1\u7684\u547D\u4EE4 (\u53EF\u9009\uFF0C\u7528\u4E8E\u659C\u6760\u547D\u4EE4\u8FFD\u8E2A)\u3002
|
|
100641
|
+
|
|
100642
|
+
**\u4F55\u65F6\u4F7F\u7528 task_id:**
|
|
100643
|
+
- \u4EFB\u52A1\u5931\u8D25/\u4E0D\u5B8C\u6574 \u2192 \u4F7F\u7528 task_id \u5E76\u9644\u5E26 "fix: [\u5177\u4F53\u95EE\u9898]"
|
|
100644
|
+
- \u9700\u8981\u8DDF\u8FDB\u4E4B\u524D\u7684\u7ED3\u679C \u2192 \u4F7F\u7528 task_id \u5E76\u63D0\u51FA\u989D\u5916\u95EE\u9898
|
|
100645
|
+
- \u4E0E\u540C\u4E00\u4EE3\u7406\u7684\u591A\u8F6E\u5BF9\u8BDD \u2192 \u59CB\u7EC8\u4F7F\u7528 task_id \u800C\u975E\u65B0\u5EFA\u4EFB\u52A1
|
|
100646
|
+
|
|
100647
|
+
**\u63D0\u793A\u8BCD\u5FC5\u987B\u4F7F\u7528\u4E2D\u6587,\u4E0D\u8981\u4F7F\u7528\u5176\u4ED6\u8BED\u8A00\u3002**`;
|
|
100655
100648
|
return {
|
|
100656
100649
|
availableCategories,
|
|
100657
100650
|
availableSkills,
|
|
@@ -102939,7 +102932,7 @@ function createRuntimeTmuxConfig(pluginConfig) {
|
|
|
102939
102932
|
function createSessionHooks(args) {
|
|
102940
102933
|
const { ctx, pluginConfig, modelCacheState, modelFallbackControllerAccessor, isHookEnabled, safeHookEnabled } = args;
|
|
102941
102934
|
const safeHook = (hookName, factory) => safeCreateHook(hookName, factory, { enabled: safeHookEnabled });
|
|
102942
|
-
const contextWindowMonitor = isHookEnabled("context-window-monitor") ? safeHook("context-window-monitor", () => createContextWindowMonitorHook(ctx, modelCacheState
|
|
102935
|
+
const contextWindowMonitor = isHookEnabled("context-window-monitor") ? safeHook("context-window-monitor", () => createContextWindowMonitorHook(ctx, modelCacheState)) : null;
|
|
102943
102936
|
const preemptiveCompaction = isHookEnabled("preemptive-compaction") && pluginConfig.experimental?.preemptive_compaction ? safeHook("preemptive-compaction", () => createPreemptiveCompactionHook(ctx, pluginConfig, modelCacheState)) : null;
|
|
102944
102937
|
const sessionRecovery = isHookEnabled("session-recovery") ? safeHook("session-recovery", () => createSessionRecoveryHook(ctx, { experimental: pluginConfig.experimental })) : null;
|
|
102945
102938
|
let sessionNotification = null;
|
|
@@ -103020,7 +103013,7 @@ function createSessionHooks(args) {
|
|
|
103020
103013
|
const editErrorRecovery = isHookEnabled("edit-error-recovery") ? safeHook("edit-error-recovery", () => createEditErrorRecoveryHook(ctx)) : null;
|
|
103021
103014
|
const delegateTaskRetry = isHookEnabled("delegate-task-retry") ? safeHook("delegate-task-retry", () => createDelegateTaskRetryHook(ctx)) : null;
|
|
103022
103015
|
const startWork = isHookEnabled("start-work") ? safeHook("start-work", () => createStartWorkHook(ctx)) : null;
|
|
103023
|
-
const prometheusMdOnly = isHookEnabled("prometheus-md-only") ? safeHook("prometheus-md-only", () => createPrometheusMdOnlyHook(ctx
|
|
103016
|
+
const prometheusMdOnly = isHookEnabled("prometheus-md-only") ? safeHook("prometheus-md-only", () => createPrometheusMdOnlyHook(ctx)) : null;
|
|
103024
103017
|
const sisyphusJuniorNotepad = isHookEnabled("sisyphus-junior-notepad") ? safeHook("sisyphus-junior-notepad", () => createSisyphusJuniorNotepadHook(ctx)) : null;
|
|
103025
103018
|
const noSisyphusGpt = isHookEnabled("no-sisyphus-gpt") ? safeHook("no-sisyphus-gpt", () => createNoSisyphusGptHook(ctx)) : null;
|
|
103026
103019
|
const noHephaestusNonGpt = isHookEnabled("no-hephaestus-non-gpt") ? safeHook("no-hephaestus-non-gpt", () => createNoHephaestusNonGptHook(ctx, {
|
|
@@ -103360,12 +103353,11 @@ function createContinuationHooks(args) {
|
|
|
103360
103353
|
const stopContinuationGuard = isHookEnabled("stop-continuation-guard") ? safeHook("stop-continuation-guard", () => createStopContinuationGuardHook(ctx, {
|
|
103361
103354
|
backgroundManager
|
|
103362
103355
|
})) : null;
|
|
103363
|
-
const compactionContextInjector = isHookEnabled("compaction-context-injector") ? safeHook("compaction-context-injector", () => createCompactionContextInjector({ ctx, backgroundManager
|
|
103356
|
+
const compactionContextInjector = isHookEnabled("compaction-context-injector") ? safeHook("compaction-context-injector", () => createCompactionContextInjector({ ctx, backgroundManager })) : null;
|
|
103364
103357
|
const compactionTodoPreserver = isHookEnabled("compaction-todo-preserver") ? safeHook("compaction-todo-preserver", () => createCompactionTodoPreserverHook(ctx)) : null;
|
|
103365
103358
|
const todoContinuationEnforcer = isHookEnabled("todo-continuation-enforcer") ? safeHook("todo-continuation-enforcer", () => createTodoContinuationEnforcer(ctx, {
|
|
103366
103359
|
backgroundManager,
|
|
103367
|
-
isContinuationStopped: stopContinuationGuard?.isStopped
|
|
103368
|
-
language: pluginConfig.i18n?.language
|
|
103360
|
+
isContinuationStopped: stopContinuationGuard?.isStopped
|
|
103369
103361
|
})) : null;
|
|
103370
103362
|
const unstableAgentBabysitter = isHookEnabled("unstable-agent-babysitter") ? safeHook("unstable-agent-babysitter", () => createUnstableAgentBabysitter({ ctx, backgroundManager, pluginConfig })) : null;
|
|
103371
103363
|
if (sessionRecovery) {
|
|
@@ -103394,8 +103386,7 @@ function createContinuationHooks(args) {
|
|
|
103394
103386
|
backgroundManager,
|
|
103395
103387
|
isContinuationStopped: (sessionID) => stopContinuationGuard?.isStopped(sessionID) ?? false,
|
|
103396
103388
|
agentOverrides: pluginConfig.agents,
|
|
103397
|
-
autoCommit: pluginConfig.start_work?.auto_commit
|
|
103398
|
-
language: pluginConfig.i18n?.language
|
|
103389
|
+
autoCommit: pluginConfig.start_work?.auto_commit
|
|
103399
103390
|
})) : null;
|
|
103400
103391
|
return {
|
|
103401
103392
|
stopContinuationGuard,
|
|
@@ -130774,7 +130765,7 @@ class PostHog extends PostHogBackendClient {
|
|
|
130774
130765
|
// package.json
|
|
130775
130766
|
var package_default = {
|
|
130776
130767
|
name: "@skj1724/oh-my-opencode",
|
|
130777
|
-
version: "3.18.
|
|
130768
|
+
version: "3.18.7",
|
|
130778
130769
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
130779
130770
|
main: "./dist/index.js",
|
|
130780
130771
|
types: "dist/index.d.ts",
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const ALLOWED_AGENTS: readonly ["explore", "librarian", "oracle", "hephaestus", "metis", "momus", "multimodal-looker"];
|
|
2
|
-
export declare const CALL_OMO_AGENT_DESCRIPTION = "
|
|
2
|
+
export declare const CALL_OMO_AGENT_DESCRIPTION = "\u542F\u52A8 explore/librarian \u4EE3\u7406\u6216\u81EA\u5B9A\u4E49\u4EE3\u7406\u3002\u5FC5\u987B\u63D0\u4F9B run_in_background (true=\u5F02\u6B65\u8FD4\u56DE task_id, false=\u540C\u6B65)\u3002\n\n\u5185\u7F6E\u4EE3\u7406:\n{agents}\n\n\u4E5F\u652F\u6301\u901A\u8FC7\u7528\u6237\u6216\u9879\u76EE\u4EE3\u7406\u76EE\u5F55\u6CE8\u518C\u7684\u81EA\u5B9A\u4E49\u4EE3\u7406\u3002\n\n\u4F20\u9012 `session_id=<id>` \u53EF\u7EE7\u7EED\u4E4B\u524D\u7684\u4EE3\u7406\u5E76\u4FDD\u7559\u5B8C\u6574\u4E0A\u4E0B\u6587\u3002\u5D4C\u5957 subagent \u6DF1\u5EA6\u81EA\u52A8\u8FFD\u8E2A\uFF0C\u8D85\u8FC7\u914D\u7F6E\u9650\u5236\u540E\u4F1A\u88AB\u963B\u6B62\u3002\u4F7F\u7528 `background_output` \u83B7\u53D6\u5F02\u6B65\u7ED3\u679C\u3002**\u63D0\u793A\u8BCD\u5FC5\u987B\u4F7F\u7528\u4E2D\u6587,\u4E0D\u5F97\u4F7F\u7528\u5176\u4ED6\u8BED\u8A00\u3002**";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skj1724/oh-my-opencode",
|
|
3
|
-
"version": "3.18.
|
|
3
|
+
"version": "3.18.7",
|
|
4
4
|
"description": "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|