oh-my-opencode 4.19.0 → 4.19.2
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/.agents/command/omomomo.md +1 -1
- package/.agents/skills/omomomo/SKILL.md +1 -1
- package/.opencode/command/omomomo.md +1 -1
- package/README.ja.md +6 -6
- package/README.ko.md +6 -6
- package/README.md +6 -6
- package/README.ru.md +6 -6
- package/README.zh-cn.md +6 -6
- package/dist/agents/atlas/agent.d.ts +5 -3
- package/dist/agents/explore.d.ts +4 -2
- package/dist/agents/gpt-prompt-identity.d.ts +3 -0
- package/dist/agents/hephaestus/agent.d.ts +4 -2
- package/dist/agents/librarian.d.ts +4 -2
- package/dist/agents/metis.d.ts +4 -2
- package/dist/agents/momus.d.ts +3 -2
- package/dist/agents/multimodal-looker.d.ts +4 -2
- package/dist/agents/oracle.d.ts +4 -2
- package/dist/agents/sisyphus/claude-opus-5.d.ts +33 -0
- package/dist/agents/sisyphus/gpt-5-5.d.ts +1 -1
- package/dist/agents/sisyphus/gpt-task-system-guide.d.ts +1 -0
- package/dist/agents/sisyphus/index.d.ts +2 -0
- package/dist/agents/sisyphus-agent-factory.d.ts +5 -2
- package/dist/agents/sisyphus-junior/agent.d.ts +4 -1
- package/dist/agents/sisyphus-junior/gpt-5-5.d.ts +2 -2
- package/dist/agents/types.d.ts +2 -2
- package/dist/cli/index.js +23577 -19269
- package/dist/cli-node/index.js +23577 -19269
- package/dist/config/schema/agent-names.d.ts +26 -26
- package/dist/config/schema/agent-overrides.d.ts +400 -400
- package/dist/config/schema/browser-automation.d.ts +2 -2
- package/dist/config/schema/categories.d.ts +36 -36
- package/dist/config/schema/codegraph.d.ts +2 -0
- package/dist/config/schema/commands.d.ts +2 -2
- package/dist/config/schema/dynamic-context-pruning.d.ts +1 -1
- package/dist/config/schema/experimental.d.ts +1 -1
- package/dist/config/schema/fallback-models.d.ts +25 -25
- package/dist/config/schema/hooks.d.ts +43 -43
- package/dist/config/schema/internal/permission.d.ts +9 -9
- package/dist/config/schema/keyword-detector.d.ts +6 -6
- package/dist/config/schema/oh-my-opencode-config.d.ts +404 -402
- package/dist/config/schema/tmux.d.ts +6 -6
- package/dist/create-hooks.d.ts +35 -35
- package/dist/features/background-agent/spawner/tmux-callback-invoker.d.ts +11 -0
- package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
- package/dist/features/claude-tasks/types.d.ts +4 -4
- package/dist/features/team-mode/team-runtime/shutdown-helpers.d.ts +1 -1
- package/dist/features/team-mode/team-runtime/shutdown-test-fixtures.d.ts +4 -4
- package/dist/features/team-mode/tools/lifecycle-test-fixture.d.ts +42 -42
- package/dist/features/tmux-subagent/environment-eligibility.d.ts +2 -0
- package/dist/features/tmux-subagent/index.d.ts +1 -0
- package/dist/features/tmux-subagent/tracked-session-state.d.ts +1 -0
- package/dist/features/tui-sidebar/snapshot-schema.d.ts +6 -6
- package/dist/help/schema/acp.d.ts +3 -3
- package/dist/help/schema/doctor.d.ts +4 -4
- package/dist/help/schema/status.d.ts +3 -3
- package/dist/hooks/codegraph-bootstrap/hook.d.ts +3 -2
- package/dist/hooks/goal/types.d.ts +5 -5
- package/dist/hooks/non-interactive-env/constants.d.ts +4 -1
- package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
- package/dist/hooks/start-work/notepad-scaffold.d.ts +10 -0
- package/dist/hooks/start-work/parse-user-request.d.ts +2 -0
- package/dist/hooks/start-work/worktree-block.d.ts +5 -0
- package/dist/index.js +27370 -21301
- package/dist/mcp/types.d.ts +3 -3
- package/dist/oh-my-opencode.schema.json +11 -0
- package/dist/plugin/chat-message/loop-commands.d.ts +1 -0
- package/dist/plugin/command-execute-before.d.ts +3 -3
- package/dist/plugin/hooks/create-core-hooks.d.ts +25 -25
- package/dist/shared/omo-process-sweep.d.ts +18 -0
- package/dist/shared/tmux/tmux-utils/environment.d.ts +1 -1
- package/dist/shared/tmux/tmux-utils.d.ts +1 -1
- package/dist/shared/typescript-native-source-parser.d.ts +7 -0
- package/dist/skills/coding-agent-sessions/SKILL.md +5 -2
- package/dist/skills/coding-agent-sessions/references/all-platforms.md +3 -1
- package/dist/skills/coding-agent-sessions/references/senpi.md +15 -5
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
- package/dist/skills/debugging/SKILL.md +2 -1
- package/dist/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
- package/dist/skills/programming/SKILL.md +11 -1
- package/dist/skills/programming/references/logging.md +6 -1
- package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
- package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.ts +75 -11
- package/dist/skills/start-work/SKILL.md +12 -2
- package/dist/skills/ulw-plan/SKILL.md +21 -2
- package/dist/skills/ulw-plan/references/full-workflow.md +12 -1
- package/dist/skills/ulw-plan/references/intent-clear.md +1 -1
- package/dist/testing/create-plugin-module.d.ts +1 -0
- package/dist/tools/task/types.d.ts +10 -10
- package/dist/tui.js +23442 -19182
- package/package.json +14 -14
- package/packages/git-bash-mcp/dist/cli.js +54 -8
- package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +62 -2
- package/packages/lsp-core/src/lsp/client.ts +14 -1
- package/packages/lsp-core/src/lsp/fixtures/diagnostics-freshness-contract-probe.ts +2 -2
- package/packages/lsp-core/src/mcp.ts +9 -0
- package/packages/lsp-daemon/dist/cli.js +319 -51
- package/packages/lsp-daemon/dist/client.js +136 -48
- package/packages/lsp-daemon/dist/daemon-client.d.ts +0 -10
- package/packages/lsp-daemon/dist/daemon-client.js +4 -34
- package/packages/lsp-daemon/dist/daemon-failure-result.d.ts +3 -0
- package/packages/lsp-daemon/dist/daemon-failure-result.js +38 -0
- package/packages/lsp-daemon/dist/daemon-request-error.d.ts +14 -0
- package/packages/lsp-daemon/dist/daemon-request-error.js +26 -0
- package/packages/lsp-daemon/dist/daemon-server.js +5 -1
- package/packages/lsp-daemon/dist/index.js +137 -48
- package/packages/lsp-daemon/dist/proxy.d.ts +2 -0
- package/packages/lsp-daemon/dist/proxy.js +1 -0
- package/packages/lsp-daemon/dist/version-reap.d.ts +26 -0
- package/packages/lsp-daemon/dist/version-reap.js +182 -0
- package/packages/lsp-tools-mcp/dist/cli.js +61 -10
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +6 -1
- package/packages/lsp-tools-mcp/dist/mcp.js +61 -10
- package/packages/lsp-tools-mcp/dist/tools.js +6 -1
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +72 -12
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/src/setup.ts +22 -2
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +779 -385
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +302 -173
- package/packages/omo-codex/plugin/components/codegraph/package.json +2 -2
- package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +3 -1
- package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +23 -42
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +98 -32
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +5 -0
- package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +17 -9
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +18 -25
- package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +1 -0
- package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +5 -0
- package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +176 -0
- package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +6 -1
- package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +31 -2
- package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +1 -1
- package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +6 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +65 -1
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +3 -7
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +2 -1
- package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +57 -3
- package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +42 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +122 -10
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +2 -2
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +101 -64
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +80 -40
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/dist/cli.js +11 -0
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +11 -0
- package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +60 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +1 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-clone-fidelity-reviewer.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +12 -7
- package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +12 -7
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +21 -2
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +12 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/src/codex-hook.ts +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +42 -0
- package/packages/omo-codex/plugin/components/ulw-loop/README.md +6 -4
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +12 -7
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.d.ts +21 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +64 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +15 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.d.ts +3 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +85 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.d.ts +0 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +13 -33
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +998 -593
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.d.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.js +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.js +3 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +4 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +10 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.d.ts +15 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.js +84 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.d.ts +5 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.js +81 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +7 -59
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +12 -4
- package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.d.ts +9 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.js +122 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +8 -6
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +84 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +13 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-arg-parser.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +49 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +13 -45
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/constants.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +7 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/goal-status.ts +4 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +4 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +20 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering-batch.ts +125 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering-mutations.ts +59 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +6 -58
- package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +12 -4
- package/packages/omo-codex/plugin/components/ulw-loop/src/validation-batch.ts +122 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +76 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint-continuation.test.ts +111 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-batch.test.ts +67 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-validation-batch.test.ts +57 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/steering-batch.test.ts +152 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +29 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch-checkpoint.test.ts +147 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch.test.ts +73 -0
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +2 -2
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +2 -2
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +2 -2
- package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/package-lock.json +41 -41
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +44 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +5 -2
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +3 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +15 -5
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
- package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -1
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
- package/packages/omo-codex/plugin/skills/programming/SKILL.md +11 -1
- package/packages/omo-codex/plugin/skills/programming/references/logging.md +6 -1
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +75 -11
- package/packages/omo-codex/plugin/skills/start-work/SKILL.md +12 -2
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +12 -7
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +2 -1
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +8 -6
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +21 -2
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +12 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +1 -1
- package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +9 -9
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +26 -0
- package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +41 -0
- package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +22 -0
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +49 -5
- package/packages/omo-codex/scripts/install-marketplace-cache.test.mjs +4 -1
- package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +5 -2
- package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +3 -1
- package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +15 -5
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
- package/packages/shared-skills/skills/debugging/SKILL.md +2 -1
- package/packages/shared-skills/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
- package/packages/shared-skills/skills/programming/SKILL.md +11 -1
- package/packages/shared-skills/skills/programming/references/logging.md +6 -1
- package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
- package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.ts +75 -11
- package/packages/shared-skills/skills/start-work/SKILL.md +12 -2
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +21 -2
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +12 -1
- package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +1 -1
package/dist/mcp/types.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export declare const McpNameSchema: z.ZodEnum<{
|
|
3
|
-
|
|
4
|
-
websearch: "websearch";
|
|
3
|
+
codegraph: "codegraph";
|
|
5
4
|
context7: "context7";
|
|
6
5
|
grep_app: "grep_app";
|
|
7
|
-
|
|
6
|
+
lsp: "lsp";
|
|
7
|
+
websearch: "websearch";
|
|
8
8
|
}>;
|
|
9
9
|
export type McpName = z.infer<typeof McpNameSchema>;
|
|
10
10
|
export declare const AnyMcpNameSchema: z.ZodString;
|
|
@@ -6556,10 +6556,20 @@
|
|
|
6556
6556
|
"default": true,
|
|
6557
6557
|
"type": "boolean"
|
|
6558
6558
|
},
|
|
6559
|
+
"daemon": {
|
|
6560
|
+
"default": true,
|
|
6561
|
+
"type": "boolean"
|
|
6562
|
+
},
|
|
6559
6563
|
"enabled": {
|
|
6560
6564
|
"default": true,
|
|
6561
6565
|
"type": "boolean"
|
|
6562
6566
|
},
|
|
6567
|
+
"excluded_roots": {
|
|
6568
|
+
"type": "array",
|
|
6569
|
+
"items": {
|
|
6570
|
+
"type": "string"
|
|
6571
|
+
}
|
|
6572
|
+
},
|
|
6563
6573
|
"install_dir": {
|
|
6564
6574
|
"type": "string"
|
|
6565
6575
|
},
|
|
@@ -6574,6 +6584,7 @@
|
|
|
6574
6584
|
"required": [
|
|
6575
6585
|
"auto_init",
|
|
6576
6586
|
"auto_provision",
|
|
6587
|
+
"daemon",
|
|
6577
6588
|
"enabled"
|
|
6578
6589
|
],
|
|
6579
6590
|
"additionalProperties": false
|
|
@@ -10,11 +10,11 @@ type CommandExecuteBeforeOutput = {
|
|
|
10
10
|
text?: string;
|
|
11
11
|
[key: string]: unknown;
|
|
12
12
|
}>;
|
|
13
|
-
message?: Record<string, unknown>;
|
|
14
13
|
};
|
|
15
|
-
declare
|
|
14
|
+
export declare function markNativeGoalCommand(parts: CommandExecuteBeforeOutput["parts"]): void;
|
|
15
|
+
export declare function consumeNativeGoalCommandMarker(parts: CommandExecuteBeforeOutput["parts"]): boolean;
|
|
16
16
|
export declare function createCommandExecuteBeforeHandler(args: {
|
|
17
17
|
directory: string;
|
|
18
18
|
hooks: CreatedHooks;
|
|
19
19
|
}): (input: CommandExecuteBeforeInput, output: CommandExecuteBeforeOutput) => Promise<void>;
|
|
20
|
-
export {
|
|
20
|
+
export {};
|
|
@@ -14,31 +14,6 @@ export declare function createCoreHooks(args: {
|
|
|
14
14
|
isHookEnabled: (hookName: HookName) => boolean;
|
|
15
15
|
safeHookEnabled: boolean;
|
|
16
16
|
}): {
|
|
17
|
-
claudeCodeHooks: ReturnType<typeof import("../../hooks").createClaudeCodeHooksHook> | null;
|
|
18
|
-
keywordDetector: ReturnType<typeof import("../../hooks").createKeywordDetectorHook> | null;
|
|
19
|
-
contextInjectorMessagesTransform: ReturnType<typeof import("../../features/context-injector").createContextInjectorMessagesTransformHook>;
|
|
20
|
-
teamModeStatusInjector: ReturnType<typeof import("../../hooks").createTeamModeStatusInjector> | null;
|
|
21
|
-
teamMailboxInjector: ReturnType<typeof import("../../hooks").createTeamMailboxInjector> | null;
|
|
22
|
-
toolPairValidator: ReturnType<typeof import("../../hooks").createToolPairValidatorHook> | null;
|
|
23
|
-
monitorStatusInjector: ReturnType<typeof import("../../hooks").createMonitorStatusInjectorHook> | null;
|
|
24
|
-
commentChecker: ReturnType<typeof import("../../hooks").createCommentCheckerHooks> | null;
|
|
25
|
-
toolOutputTruncator: ReturnType<typeof import("../../hooks").createToolOutputTruncatorHook> | null;
|
|
26
|
-
directoryAgentsInjector: ReturnType<typeof import("../../hooks").createDirectoryAgentsInjectorHook> | null;
|
|
27
|
-
directoryReadmeInjector: ReturnType<typeof import("../../hooks").createDirectoryReadmeInjectorHook> | null;
|
|
28
|
-
emptyTaskResponseDetector: ReturnType<typeof import("../../hooks").createEmptyTaskResponseDetectorHook> | null;
|
|
29
|
-
rulesInjector: ReturnType<typeof import("../../hooks").createRulesInjectorHook> | null;
|
|
30
|
-
tasksTodowriteDisabler: ReturnType<typeof import("../../hooks").createTasksTodowriteDisablerHook> | null;
|
|
31
|
-
writeExistingFileGuard: ReturnType<typeof import("../../hooks").createWriteExistingFileGuardHook> | null;
|
|
32
|
-
bashFileReadGuard: ReturnType<typeof import("../../hooks").createBashFileReadGuardHook> | null;
|
|
33
|
-
hashlineReadEnhancer: ReturnType<typeof import("../../hooks").createHashlineReadEnhancerHook> | null;
|
|
34
|
-
jsonErrorRecovery: ReturnType<typeof import("../../hooks").createJsonErrorRecoveryHook> | null;
|
|
35
|
-
readImageResizer: ReturnType<typeof import("../../hooks").createReadImageResizerHook> | null;
|
|
36
|
-
todoDescriptionOverride: ReturnType<typeof import("../../hooks").createTodoDescriptionOverrideHook> | null;
|
|
37
|
-
webfetchRedirectGuard: ReturnType<typeof import("../../hooks").createWebFetchRedirectGuardHook> | null;
|
|
38
|
-
fsyncSkipWarning: ReturnType<typeof import("../../hooks").createFsyncSkipWarningHook> | null;
|
|
39
|
-
teamToolGating: ReturnType<typeof import("../../hooks").createTeamToolGating> | null;
|
|
40
|
-
notepadWriteGuard: ReturnType<typeof import("../../hooks").createNotepadWriteGuardHook> | null;
|
|
41
|
-
planFormatValidator: ReturnType<typeof import("../../hooks").createPlanFormatValidatorHook> | null;
|
|
42
17
|
preemptiveCompaction: ReturnType<typeof import("../../hooks").createPreemptiveCompactionHook> | null;
|
|
43
18
|
sessionNotification: ReturnType<typeof import("../../hooks").createSessionNotification> | null;
|
|
44
19
|
thinkMode: ReturnType<typeof import("../../hooks").createThinkModeHook> | null;
|
|
@@ -63,4 +38,29 @@ export declare function createCoreHooks(args: {
|
|
|
63
38
|
taskResumeInfo: ReturnType<typeof import("../../hooks").createTaskResumeInfoHook> | null;
|
|
64
39
|
runtimeFallback: ReturnType<typeof import("../../hooks").createRuntimeFallbackHook> | null;
|
|
65
40
|
legacyPluginToast: ReturnType<typeof import("../../hooks").createLegacyPluginToastHook> | null;
|
|
41
|
+
commentChecker: ReturnType<typeof import("../../hooks").createCommentCheckerHooks> | null;
|
|
42
|
+
toolOutputTruncator: ReturnType<typeof import("../../hooks").createToolOutputTruncatorHook> | null;
|
|
43
|
+
directoryAgentsInjector: ReturnType<typeof import("../../hooks").createDirectoryAgentsInjectorHook> | null;
|
|
44
|
+
directoryReadmeInjector: ReturnType<typeof import("../../hooks").createDirectoryReadmeInjectorHook> | null;
|
|
45
|
+
emptyTaskResponseDetector: ReturnType<typeof import("../../hooks").createEmptyTaskResponseDetectorHook> | null;
|
|
46
|
+
rulesInjector: ReturnType<typeof import("../../hooks").createRulesInjectorHook> | null;
|
|
47
|
+
tasksTodowriteDisabler: ReturnType<typeof import("../../hooks").createTasksTodowriteDisablerHook> | null;
|
|
48
|
+
writeExistingFileGuard: ReturnType<typeof import("../../hooks").createWriteExistingFileGuardHook> | null;
|
|
49
|
+
bashFileReadGuard: ReturnType<typeof import("../../hooks").createBashFileReadGuardHook> | null;
|
|
50
|
+
hashlineReadEnhancer: ReturnType<typeof import("../../hooks").createHashlineReadEnhancerHook> | null;
|
|
51
|
+
jsonErrorRecovery: ReturnType<typeof import("../../hooks").createJsonErrorRecoveryHook> | null;
|
|
52
|
+
readImageResizer: ReturnType<typeof import("../../hooks").createReadImageResizerHook> | null;
|
|
53
|
+
todoDescriptionOverride: ReturnType<typeof import("../../hooks").createTodoDescriptionOverrideHook> | null;
|
|
54
|
+
webfetchRedirectGuard: ReturnType<typeof import("../../hooks").createWebFetchRedirectGuardHook> | null;
|
|
55
|
+
fsyncSkipWarning: ReturnType<typeof import("../../hooks").createFsyncSkipWarningHook> | null;
|
|
56
|
+
teamToolGating: ReturnType<typeof import("../../hooks").createTeamToolGating> | null;
|
|
57
|
+
notepadWriteGuard: ReturnType<typeof import("../../hooks").createNotepadWriteGuardHook> | null;
|
|
58
|
+
planFormatValidator: ReturnType<typeof import("../../hooks").createPlanFormatValidatorHook> | null;
|
|
59
|
+
claudeCodeHooks: ReturnType<typeof import("../../hooks").createClaudeCodeHooksHook> | null;
|
|
60
|
+
keywordDetector: ReturnType<typeof import("../../hooks").createKeywordDetectorHook> | null;
|
|
61
|
+
contextInjectorMessagesTransform: ReturnType<typeof import("../../features/context-injector").createContextInjectorMessagesTransformHook>;
|
|
62
|
+
teamModeStatusInjector: ReturnType<typeof import("../../hooks").createTeamModeStatusInjector> | null;
|
|
63
|
+
teamMailboxInjector: ReturnType<typeof import("../../hooks").createTeamMailboxInjector> | null;
|
|
64
|
+
toolPairValidator: ReturnType<typeof import("../../hooks").createToolPairValidatorHook> | null;
|
|
65
|
+
monitorStatusInjector: ReturnType<typeof import("../../hooks").createMonitorStatusInjectorHook> | null;
|
|
66
66
|
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { sweepCodegraphZombies, sweepOrphanedLspDaemonProxies, sweepStaleLspDaemonVersions } from "@oh-my-opencode/utils/process-sweep";
|
|
2
|
+
export interface OmoFamilySweepOptions {
|
|
3
|
+
readonly log?: (message: string) => void;
|
|
4
|
+
}
|
|
5
|
+
export interface OmoFamilySweeps {
|
|
6
|
+
readonly sweepCodegraph: typeof sweepCodegraphZombies;
|
|
7
|
+
readonly sweepLspProxies: typeof sweepOrphanedLspDaemonProxies;
|
|
8
|
+
readonly sweepStaleLspDaemons: typeof sweepStaleLspDaemonVersions;
|
|
9
|
+
}
|
|
10
|
+
export declare function sweepCodegraphZombiesBestEffort(options: OmoFamilySweepOptions, sweep?: typeof sweepCodegraphZombies): Promise<void>;
|
|
11
|
+
export declare function sweepOrphanedLspDaemonProxiesBestEffort(options: OmoFamilySweepOptions, sweep?: typeof sweepOrphanedLspDaemonProxies): Promise<void>;
|
|
12
|
+
export declare function sweepStaleLspDaemonVersionsBestEffort(options: OmoFamilySweepOptions, sweep?: typeof sweepStaleLspDaemonVersions): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Runs all three omo sweep families concurrently. NEVER rejects: each family
|
|
15
|
+
* is wrapped best-effort so a sweep failure can only produce a log line, not
|
|
16
|
+
* a startup failure. Callers fire-and-forget the returned promise.
|
|
17
|
+
*/
|
|
18
|
+
export declare function sweepOmoFamiliesBestEffort(options?: OmoFamilySweepOptions, sweeps?: OmoFamilySweeps): Promise<void>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { getCurrentPaneId, isInsideTmux, isInsideTmuxEnvironment, } from "@oh-my-opencode/tmux-core";
|
|
1
|
+
export { getCurrentPaneId, isInsideTmux, isInsideTmuxEnvironment, isNativeTmux, isNativeTmuxEnvironment, isTmuxPaneCompatible, isTmuxPaneCompatibleEnvironment, } from "@oh-my-opencode/tmux-core";
|
|
2
2
|
export type { SplitDirection } from "@oh-my-opencode/tmux-core";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { isInsideTmux, getCurrentPaneId } from "./tmux-utils/environment";
|
|
1
|
+
export { isInsideTmux, isNativeTmux, isTmuxPaneCompatible, getCurrentPaneId } from "./tmux-utils/environment";
|
|
2
2
|
export type { SplitDirection } from "./tmux-utils/environment";
|
|
3
3
|
export { isServerRunning, resetServerCheck, markServerRunningInProcess } from "./tmux-utils/server-health";
|
|
4
4
|
export { getPaneDimensions } from "./tmux-utils/pane-dimensions";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: coding-agent-sessions
|
|
3
|
-
description: "MUST USE when asked to find, read, list, search, inspect, fetch, export, or reconstruct coding-agent sessions across Codex, Claude Code/Desktop, OpenCode, Senpi/pi, OpenClaw, Factory Droid, Amp, Gemini/Kimi/Qwen CLIs, Codebuff, Roo/Kilo/Cline, Kodu, Cursor CLI, Aider, or unknown local agent logs. Covers transcripts, session IDs, rollout JSONL, state SQLite, Claude projects/pre-compact histories, OpenCode messages/parts, child/subagent linkage, cwd/model/time/token filters, archives, and cost clues. Expands fuzzy recall into parallel query lanes and first probes known stores so absent platforms are skipped cheaply. Triggers: coding agent sessions, Codex/Claude/OpenCode/Senpi/pi/OpenClaw/Droid/Amp/Kodu/Cursor/Aider sessions, transcript search, session history, session ID, read transcript, token usage, subagent sessions, what did I do yesterday, did we already do this."
|
|
3
|
+
description: "MUST USE when asked to find, read, list, search, inspect, fetch, export, or reconstruct coding-agent sessions across Codex, Claude Code/Desktop, OpenCode, Senpi/pi, oh-my-pi (omp), gajae-code (gjc), OpenClaw, Factory Droid, Amp, Gemini/Kimi/Qwen CLIs, Codebuff, Roo/Kilo/Cline, Kodu, Cursor CLI, Aider, or unknown local agent logs. Covers transcripts, session IDs, rollout JSONL, state SQLite, Claude projects/pre-compact histories, OpenCode messages/parts, child/subagent linkage, cwd/model/time/token filters, archives, and cost clues. Expands fuzzy recall into parallel query lanes and first probes known stores so absent platforms are skipped cheaply. Triggers: coding agent sessions, Codex/Claude/OpenCode/Senpi/pi/oh-my-pi/omp/gajae-code/gjc/OpenClaw/Droid/Amp/Kodu/Cursor/Aider sessions, transcript search, session history, session ID, read transcript, token usage, subagent sessions, what did I do yesterday, did we already do this."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Coding Agent Sessions
|
|
@@ -16,6 +16,7 @@ Find local coding-agent sessions across agent products before answering from mem
|
|
|
16
16
|
| Codex / OpenAI Codex CLI | `references/codex.md` |
|
|
17
17
|
| Claude Code / Claude Desktop histories | `references/claude.md` |
|
|
18
18
|
| Senpi / pi coding-agent logs | `references/senpi.md` |
|
|
19
|
+
| oh-my-pi (`omp`, `~/.omp`) and gajae-code (`gjc`, `~/.gjc`) logs | `references/senpi.md` |
|
|
19
20
|
| OpenCode / oh-my-openagent (formerly oh-my-opencode) storage | `references/opencode.md` |
|
|
20
21
|
| OpenClaw, Droid, Amp, Gemini, Kimi, Qwen, Codebuff, Roo/Kilo/Cline, Kodu, Cursor CLI, Aider, Kiro, Goose, Hermes, Crush, Zed | `references/all-platforms.md` |
|
|
21
22
|
| Unknown / "any session" / cross-agent search | `references/all-platforms.md` |
|
|
@@ -28,6 +29,7 @@ When the user remembers a task vaguely ("that OpenCode bug", "the dashboard PR",
|
|
|
28
29
|
python3 scripts/find-agent-sessions.py list --limit 20
|
|
29
30
|
python3 scripts/find-agent-sessions.py find "commit" --from 7d --platform senpi --platform opencode
|
|
30
31
|
python3 scripts/find-agent-sessions.py find "proxy" --platform openclaw --platform droid --platform amp
|
|
32
|
+
python3 scripts/find-agent-sessions.py find "refactor" --platform oh-my-pi --platform gajae-code
|
|
31
33
|
python3 scripts/find-agent-sessions.py find --query "deploy" --query "token usage" --workers 64
|
|
32
34
|
python3 scripts/find-agent-sessions.py find --query "opencode bug" --query "fix opencode" --query "OpenCode parent session" --include-subagents --workers 64
|
|
33
35
|
python3 scripts/find-agent-sessions.py read <session-id>
|
|
@@ -49,7 +51,7 @@ The finder prints JSON for stdout and `jq`. Every result includes:
|
|
|
49
51
|
|
|
50
52
|
| Field | Meaning |
|
|
51
53
|
|---|---|
|
|
52
|
-
| `platform` | Registered platform key such as `codex`, `claude`, `opencode`, `openclaw`, `droid`, `amp`, `kodu`, `cursor-cli`, `aider`, `roo-code`, `kilo-code`, `kilo-cli`, or `kiro` |
|
|
54
|
+
| `platform` | Registered platform key such as `codex`, `claude`, `senpi`, `oh-my-pi`, `gajae-code`, `opencode`, `openclaw`, `droid`, `amp`, `kodu`, `cursor-cli`, `aider`, `roo-code`, `kilo-code`, `kilo-cli`, or `kiro` |
|
|
53
55
|
| `id` | Session ID or stable file-derived ID |
|
|
54
56
|
| `path` | Raw transcript/index file |
|
|
55
57
|
| `cwd` | Working directory when recoverable |
|
|
@@ -117,6 +119,7 @@ Use `references/codex.md` for Codex storage details.
|
|
|
117
119
|
| Problem | Fix |
|
|
118
120
|
|---|---|
|
|
119
121
|
| Missing Codex sessions | Set `CODEX_HOME` or pass `--root /path/to/.codex`. |
|
|
122
|
+
| Missing oh-my-pi / gajae-code sessions | Those stores live in `~/.omp/agent/sessions` and `~/.gjc/agent/sessions`. For a custom `PI_CONFIG_DIR` / `PI_CODING_AGENT_DIR`, pass that agent dir with `--root`. |
|
|
120
123
|
| Missing OpenCode sessions | Pass the data dir that contains `messages/` and `parts/`, often `~/.opencode` or `~/.local/share/opencode`. |
|
|
121
124
|
| Missing Claude sessions | Search `~/.claude/projects`, `~/.claude/transcripts`, and `~/.claude/pre-compact-session-histories`; use `--root` for nonstandard config dirs. |
|
|
122
125
|
| Missing optional platform sessions | Check `references/all-platforms.md` for the exact local store. For project-local tools such as Aider, pass `--root /path/to/workspace` if the repo is outside the bounded default roots. |
|
|
@@ -4,13 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
Search these first, then add user-supplied roots with `--root`:
|
|
6
6
|
|
|
7
|
-
Registered platform keys: `codex`, `claude`, `senpi`, `opencode`, `openclaw`, `droid`, `amp`, `gemini`, `kimi`, `qwen`, `codebuff`, `roo-code`, `kilo-code`, `cline`, `kodu`, `cursor-cli`, `aider`, `kilo-cli`, `hermes`, `goose`, `crush`, `zed`, `kiro`.
|
|
7
|
+
Registered platform keys: `codex`, `claude`, `senpi`, `oh-my-pi`, `gajae-code`, `opencode`, `openclaw`, `droid`, `amp`, `gemini`, `kimi`, `qwen`, `codebuff`, `roo-code`, `kilo-code`, `cline`, `kodu`, `cursor-cli`, `aider`, `kilo-cli`, `hermes`, `goose`, `crush`, `zed`, `kiro`.
|
|
8
8
|
|
|
9
9
|
| Platform | Unix/macOS | Windows |
|
|
10
10
|
|---|---|---|
|
|
11
11
|
| Codex | `$CODEX_HOME`, `~/.codex` | `%CODEX_HOME%`, `%USERPROFILE%\.codex` |
|
|
12
12
|
| Claude | `~/.claude` | `%USERPROFILE%\.claude`, `%APPDATA%\Claude` |
|
|
13
13
|
| Senpi / pi | `~/.senpi/agent`, `~/.pi/agent` | `%USERPROFILE%\.senpi\agent`, `%USERPROFILE%\.pi\agent` |
|
|
14
|
+
| oh-my-pi (`omp`) | `~/.omp/agent`, `~/.omp/profiles/*/agent`, `$XDG_DATA_HOME/omp` | `%USERPROFILE%\.omp\agent` |
|
|
15
|
+
| gajae-code (`gjc`) | `~/.gjc/agent`, `~/.gjc/profiles/*/agent`, `$XDG_DATA_HOME/gjc` | `%USERPROFILE%\.gjc\agent` |
|
|
14
16
|
| OpenCode | `$OPENCODE_HOME`, `~/.opencode`, `~/.local/share/opencode` | `%OPENCODE_HOME%`, `%APPDATA%\opencode`, `%USERPROFILE%\.opencode` |
|
|
15
17
|
| OpenClaw | `~/.openclaw/agents/*/sessions`, `~/.openclaw/session-backups` | pass `--root` |
|
|
16
18
|
| Factory Droid | `~/.factory/sessions/*/*.jsonl` | pass `--root` |
|
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
# Senpi / pi Coding-Agent Sessions
|
|
1
|
+
# Senpi / pi Family Coding-Agent Sessions
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The pi family (Senpi, oh-my-pi, gajae-code) shares one session format, so one scanner serves all three under separate platform keys.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
| Platform key | Aliases | Config root | Sessions |
|
|
6
|
+
|---|---|---|---|
|
|
7
|
+
| `senpi` | - | `~/.senpi`, `~/.pi` | `<root>/agent/sessions/<encoded-cwd>/<timestamp>_<uuid>.jsonl` |
|
|
8
|
+
| `oh-my-pi` | `omp`, `ohmypi` | `~/.omp` | `~/.omp/agent/sessions/<encoded-cwd>/<timestamp>_<uuid>.jsonl` |
|
|
9
|
+
| `gajae-code` | `gjc`, `gajae` | `~/.gjc` | `~/.gjc/agent/sessions/<encoded-cwd>/<timestamp>_<uuid>.jsonl` |
|
|
10
|
+
|
|
11
|
+
Extra roots scanned for every pi-family platform:
|
|
12
|
+
|
|
13
|
+
- Named profiles: `<config-root>/profiles/<profile>/agent/sessions/**`.
|
|
14
|
+
- XDG stores (macOS/Linux, default profile): `$XDG_DATA_HOME/<app>/sessions/**` and `$XDG_DATA_HOME/<app>/profiles/<profile>/sessions/**`, where `<app>` is `senpi`, `omp`, or `gjc`. XDG flattens the `agent/` path segment.
|
|
15
|
+
- A custom `PI_CONFIG_DIR` / `PI_CODING_AGENT_DIR` / `GJC_CONFIG_DIR` store: pass that agent directory with `--root`.
|
|
16
|
+
|
|
17
|
+
`~/.senpi/agent/settings.json`, `models.json`, and `auth.json` provide environment context; oh-my-pi and gajae-code keep the same files plus `config.yml` and `models.yml` next to their sessions directory.
|
|
8
18
|
|
|
9
19
|
Common event types:
|
|
10
20
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from .transcript import env_path, existing, jsonl_parallel, recent, stem_id
|
|
6
|
+
from .types import Session
|
|
7
|
+
|
|
8
|
+
SENPI_CONFIG_DIRS = (".senpi", ".pi")
|
|
9
|
+
OH_MY_PI_CONFIG_DIRS = (".omp",)
|
|
10
|
+
GAJAE_CODE_CONFIG_DIRS = (".gjc",)
|
|
11
|
+
|
|
12
|
+
__all__ = ["scan_gajae_code", "scan_oh_my_pi", "scan_senpi"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def scan_senpi(extra_roots: tuple[Path, ...], workers: int) -> list[Session]:
|
|
16
|
+
return _scan_pi_family("senpi", SENPI_CONFIG_DIRS, "senpi", extra_roots, workers)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def scan_oh_my_pi(extra_roots: tuple[Path, ...], workers: int) -> list[Session]:
|
|
20
|
+
return _scan_pi_family("oh-my-pi", OH_MY_PI_CONFIG_DIRS, "omp", extra_roots, workers)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def scan_gajae_code(extra_roots: tuple[Path, ...], workers: int) -> list[Session]:
|
|
24
|
+
return _scan_pi_family("gajae-code", GAJAE_CODE_CONFIG_DIRS, "gjc", extra_roots, workers)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _scan_pi_family(platform: str, config_dirs: tuple[str, ...], xdg_app: str, extra_roots: tuple[Path, ...], workers: int) -> list[Session]:
|
|
28
|
+
roots = _pi_family_roots(config_dirs, xdg_app, extra_roots)
|
|
29
|
+
paths = [path for root in roots for path in (root / "sessions").rglob("*.jsonl")]
|
|
30
|
+
return jsonl_parallel(recent(paths), workers, platform, lambda path: stem_id(path, "_"))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _pi_family_roots(config_dirs: tuple[str, ...], xdg_app: str, extra_roots: tuple[Path, ...]) -> list[Path]:
|
|
34
|
+
home = Path.home()
|
|
35
|
+
roots: list[Path] = []
|
|
36
|
+
for config_dir in config_dirs:
|
|
37
|
+
base = home / config_dir
|
|
38
|
+
roots.append(base / "agent")
|
|
39
|
+
roots.extend(sorted(base.glob("profiles/*/agent")))
|
|
40
|
+
xdg_data = env_path("XDG_DATA_HOME")
|
|
41
|
+
if xdg_data is not None:
|
|
42
|
+
app_root = xdg_data / xdg_app
|
|
43
|
+
roots.append(app_root)
|
|
44
|
+
roots.extend(sorted(app_root.glob("profiles/*")))
|
|
45
|
+
roots.extend(extra_roots)
|
|
46
|
+
return existing(roots)
|
|
@@ -21,9 +21,9 @@ from .file_scanners import (
|
|
|
21
21
|
)
|
|
22
22
|
from .kiro_scanner import scan_kiro
|
|
23
23
|
from .opencode import scan_opencode
|
|
24
|
+
from .pi_family import scan_gajae_code, scan_oh_my_pi, scan_senpi
|
|
24
25
|
from .sqlite_optional_scanners import scan_crush, scan_goose, scan_hermes, scan_kilo_cli, scan_zed
|
|
25
26
|
from .sqlite_scanners import scan_cursor_cli, scan_kodu
|
|
26
|
-
from .transcript import existing, jsonl_parallel, recent, stem_id
|
|
27
27
|
from .types import Session
|
|
28
28
|
|
|
29
29
|
Scanner: TypeAlias = Callable[[tuple[Path, ...], int], list[Session]]
|
|
@@ -31,7 +31,9 @@ Scanner: TypeAlias = Callable[[tuple[Path, ...], int], list[Session]]
|
|
|
31
31
|
PLATFORM_SCANNERS: dict[str, Scanner] = {
|
|
32
32
|
"codex": scan_codex,
|
|
33
33
|
"claude": scan_claude,
|
|
34
|
-
"senpi":
|
|
34
|
+
"senpi": scan_senpi,
|
|
35
|
+
"oh-my-pi": scan_oh_my_pi,
|
|
36
|
+
"gajae-code": scan_gajae_code,
|
|
35
37
|
"opencode": scan_opencode,
|
|
36
38
|
"openclaw": scan_openclaw,
|
|
37
39
|
"droid": scan_droid,
|
|
@@ -54,9 +56,22 @@ PLATFORM_SCANNERS: dict[str, Scanner] = {
|
|
|
54
56
|
"kiro": scan_kiro,
|
|
55
57
|
}
|
|
56
58
|
DEFAULT_PLATFORMS = frozenset(PLATFORM_SCANNERS)
|
|
57
|
-
PLATFORM_ALIASES = {
|
|
59
|
+
PLATFORM_ALIASES = {
|
|
60
|
+
"cursor": "cursor-cli",
|
|
61
|
+
"factory": "droid",
|
|
62
|
+
"roo": "roo-code",
|
|
63
|
+
"roocode": "roo-code",
|
|
64
|
+
"kilocode": "kilo-code",
|
|
65
|
+
"kilo": "kilo-cli",
|
|
66
|
+
"omp": "oh-my-pi",
|
|
67
|
+
"ohmypi": "oh-my-pi",
|
|
68
|
+
"oh_my_pi": "oh-my-pi",
|
|
69
|
+
"gjc": "gajae-code",
|
|
70
|
+
"gajae": "gajae-code",
|
|
71
|
+
"gajaecode": "gajae-code",
|
|
72
|
+
}
|
|
58
73
|
|
|
59
|
-
__all__ = ["DEFAULT_PLATFORMS", "PLATFORM_SCANNERS", "scan", "scan_claude", "scan_codex", "scan_opencode", "scan_senpi"]
|
|
74
|
+
__all__ = ["DEFAULT_PLATFORMS", "PLATFORM_SCANNERS", "scan", "scan_claude", "scan_codex", "scan_gajae_code", "scan_oh_my_pi", "scan_opencode", "scan_senpi"]
|
|
60
75
|
|
|
61
76
|
|
|
62
77
|
def scan(platforms: frozenset[str], roots: tuple[Path, ...], workers: int) -> list[Session]:
|
|
@@ -72,12 +87,6 @@ def scan(platforms: frozenset[str], roots: tuple[Path, ...], workers: int) -> li
|
|
|
72
87
|
return _dedupe(sessions)
|
|
73
88
|
|
|
74
89
|
|
|
75
|
-
def scan_senpi(extra_roots: tuple[Path, ...], workers: int) -> list[Session]:
|
|
76
|
-
roots = existing([Path.home() / ".senpi" / "agent", Path.home() / ".pi" / "agent", *extra_roots])
|
|
77
|
-
paths = [path for root in roots for path in (root / "sessions").rglob("*.jsonl")]
|
|
78
|
-
return jsonl_parallel(recent(paths), workers, "senpi", lambda path: stem_id(path, "_"))
|
|
79
|
-
|
|
80
|
-
|
|
81
90
|
def _dedupe(sessions: list[Session]) -> list[Session]:
|
|
82
91
|
found: dict[tuple[str, str], Session] = {}
|
|
83
92
|
for session in sessions:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: debugging
|
|
3
|
-
description: "MUST USE for any real runtime debugging across ANY language or binary — crashes, silent failures, wrong responses, stuck processes, memory leaks, async misbehavior, unexplained timing, reverse engineering. Runs a hypothesis-driven loop: form ≥3 hypotheses, investigate in parallel, after 2 failed rounds spawn Oracles from orthogonal angles, confirm root cause, lock with a failing test, fix minimally, QA by actually USING the system, scrub artifacts. The actual HOW lives in `references/` — READ THEM. Triggers: 'debug this', 'why is X not working', 'hanging', 'attach a debugger', 'reverse engineer', 'pwndbg', 'gdb', 'lldb', 'node inspect', 'tsx debug', 'pdb', 'dlv', 'delve', 'rust-gdb', 'set a breakpoint', 'context window exploded', 'why is the response empty', '
|
|
3
|
+
description: "MUST USE for any real runtime debugging across ANY language or binary — crashes, silent failures, wrong responses, stuck processes, memory leaks, async misbehavior, unexplained timing, reverse engineering. Runs a hypothesis-driven loop: form ≥3 hypotheses, investigate in parallel, after 2 failed rounds spawn Oracles from orthogonal angles, confirm root cause, lock with a failing test, fix minimally, QA by actually USING the system, scrub artifacts. The actual HOW lives in `references/` — READ THEM. Triggers: 'debug this', 'why is X not working', 'hanging', 'attach a debugger', 'reverse engineer', 'pwndbg', 'gdb', 'lldb', 'node inspect', 'tsx debug', 'pdb', 'dlv', 'delve', 'rust-gdb', 'set a breakpoint', 'context window exploded', 'why is the response empty', 'why is this happening', 'trace this bug', 'reproduce and fix', 'silent failure', 'HTTP 200 but empty', 'why did it stop', 'inspect the binary', 'playwright', 'flaky test', 'fails intermittently', 'passes in isolation', 'only fails in CI'."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Debugging
|
|
@@ -84,6 +84,7 @@ These are not phases — read them when the situation calls for them:
|
|
|
84
84
|
|
|
85
85
|
| Situation | Reference |
|
|
86
86
|
|---|---|
|
|
87
|
+
| The failure is intermittent — fails sometimes, a different test each run, passes in isolation, or only fails in CI | 📖 **[references/methodology/03-flaky-triage.md](references/methodology/03-flaky-triage.md)** — read BEFORE Phase 2; the failure signature usually collapses the search space in one round |
|
|
87
88
|
| You cannot run the actual operation (paid API, blocked network, missing hardware) but still need runtime evidence | 📖 **[references/methodology/partial-runtime-evidence.md](references/methodology/partial-runtime-evidence.md)** |
|
|
88
89
|
| You're about to declare an extraction / audit / reverse-engineering task done and want a skeptical pass | 📖 **[references/methodology/partial-runtime-evidence.md#verification-oracle-pattern-for-non-debug-tasks](references/methodology/partial-runtime-evidence.md#verification-oracle-pattern-for-non-debug-tasks)** (Verification Oracle is *not* the same as Oracle Triple — read the file) |
|
|
89
90
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Intermittent / Flaky Failure Triage
|
|
2
|
+
|
|
3
|
+
Read this when a failure does not reproduce on every run — "fails sometimes", "a different test each run", "passes in isolation", "only fails in CI". Do not enter the hypothesis loop blind: **intermittence itself is evidence.** This triage usually collapses the search space in one round, before Phase 2 hypothesis formation.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Step 1 — Capture the failure signature (three cheap reruns)
|
|
8
|
+
|
|
9
|
+
Run these before forming any hypothesis. Journal each result.
|
|
10
|
+
|
|
11
|
+
| Rerun | Command shape | Question it answers |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| Same scope, same command | exactly what just failed | Does the SAME test fail again, or a different one? |
|
|
14
|
+
| Failing test in isolation | single file / test filter | Does it pass alone? |
|
|
15
|
+
| Full scope on a quiet machine | stop concurrent builds, suites, background agents first | Does the whole suite go green when nothing else runs? |
|
|
16
|
+
| (When order is suspect) shuffled | `-shuffle=on` / `pytest-randomly` / runner's random seed | Does a specific order reproduce it? Record the seed. |
|
|
17
|
+
|
|
18
|
+
## Step 2 — Read the signature
|
|
19
|
+
|
|
20
|
+
| Signature | Dominant hypothesis | Next move |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| Same test fails intermittently, everywhere | Real race in the code under test, or an async test bug (fixed sleep, unawaited promise, poll-for-time) | Standard phase loop from `02-investigate.md`; reproduce deterministically by subscribing to the completion event or injecting a clock |
|
|
23
|
+
| **A different test/file each run; each passes in isolation; quiet machine is green** | **Environment contention between concurrent runs — not the code** | Step 3 checklist |
|
|
24
|
+
| Always the same test, but only in the full suite; isolation green | Test-order dependence / fixture leak (unreset module state, leaked env var, shared singleton) | Bisect with the shuffle seed; find the test that leaks, fix its teardown |
|
|
25
|
+
| Fails only on CI, never locally | Resource ceilings (slower disk/CPU → timeouts), different parallelism defaults, container clock | Reproduce locally under constraint (`taskset`, low `--maxWorkers`); raise the *signal* not the sleep |
|
|
26
|
+
| Green on plain rerun of the same commit | Still a flake — classify it with this table before ignoring it; an unclassified flake is a hidden bug report | Step 1 again with journaling |
|
|
27
|
+
|
|
28
|
+
## Step 3 — Concurrent-run contention checklist
|
|
29
|
+
|
|
30
|
+
The classic modern cause: **two checkouts or worktrees of the same repo — or one checkout plus a background agent — running suites at the same time while sharing a global mutable resource.** Multi-agent workstations make this the default failure mode, not an exotic one. Check each:
|
|
31
|
+
|
|
32
|
+
- **Shared tmp roots** — a sandbox/cache dir derived from a *fixed* tmpdir path (`$TMPDIR/<project>-fixed-name`) instead of a per-run `mktemp`. Both runs read/write the same tree; the loser sees half-deleted state.
|
|
33
|
+
- **Fixed ports** — hardcoded listen ports in test servers. Two suites race to bind; the loser gets 404/ECONNREFUSED mid-run, in whichever file happened to be running.
|
|
34
|
+
- **Global env / config mutation** — tests writing process-external state (dotfiles, shared config, global env) the other run reads.
|
|
35
|
+
- **Shared containers / databases** — same-named containers, same schema, same volume.
|
|
36
|
+
- **Caches and locks** — package-manager caches, lockfiles, `.git` index contention.
|
|
37
|
+
|
|
38
|
+
Evidence to capture while it is live: `lsof -i :<port>` during the failure window, a listing of the shared tmp path, a process list showing the concurrent runners.
|
|
39
|
+
|
|
40
|
+
## Step 4 — Fix policy
|
|
41
|
+
|
|
42
|
+
- **Environment contention** → fix the **test infrastructure**, never the individual test: namespace every suite-global resource per run — `mktemp` for roots, port `0`/ephemeral allocation, unique container names. The bar: *two checkouts of this repo running the suite concurrently must not interfere.* (The programming skill's test-isolation rules own this bar.)
|
|
43
|
+
- **Order dependence** → find the leaking fixture via the recorded shuffle seed; reset at teardown; re-run shuffled until the seed class is clean.
|
|
44
|
+
- **Real race** → normal phase loop (`02-investigate.md` onward); the fix ships with a failing-first test that reproduces deterministically.
|
|
45
|
+
- **Forbidden regardless of cause**: retry wrappers around the test, enlarged sleeps, `.retry(N)`, quarantining, or deleting the test. Each one buries a bug report.
|
|
46
|
+
|
|
47
|
+
A flake you classified but did not fix is a **finding to report**, not to hide: journal the signature, the evidence, and the classification, and say it in your final report.
|
|
@@ -102,7 +102,7 @@ Mocks are a last resort, not a default. The priority order:
|
|
|
102
102
|
- **Accurate**: the test fails for the bug it names, and only that bug. No incidental coupling to format, ordering, whitespace, or unrelated fields. Assert on the *contract*, not on the dump.
|
|
103
103
|
- **Efficient**: the whole unit suite runs in < 30 seconds on a developer laptop. The whole integration suite in < 5 minutes. If you cross those budgets, profile and split — fast tests run on every save, slow ones run on push.
|
|
104
104
|
- **Deterministic**: no `sleep`, no wall-clock dependence, no order dependence (`-shuffle=on`, pytest-randomly, vitest random seed). Inject a `Clock`. Subscribe to the event, do not poll for it. Time-based flake is a bug, not a test issue.
|
|
105
|
-
- **Isolated**: every test starts from a known fixture and tears down. `t.TempDir()`, `t.Setenv()`, transactional rollback for DB tests. Two tests passing individually but failing together is a fixture leak — fix it immediately.
|
|
105
|
+
- **Isolated**: every test starts from a known fixture and tears down. `t.TempDir()`, `t.Setenv()`, transactional rollback for DB tests. Two tests passing individually but failing together is a fixture leak — fix it immediately. Isolation extends **across processes**: suite-global resources — sandbox/cache roots under a fixed tmpdir path, hardcoded listen ports, container names — are namespaced per run (`mktemp`, port `0`/ephemeral, unique names) so that two checkouts or worktrees of the repo running the suite concurrently cannot interfere. A fixed shared path that works on a single-checkout machine is a flake generator on a multi-agent workstation, and its signature is "a different test fails each run".
|
|
106
106
|
|
|
107
107
|
### Prompt tests: NEVER assert prose
|
|
108
108
|
|
|
@@ -113,6 +113,7 @@ Assert ONLY what a machine consumes:
|
|
|
113
113
|
- the builder's routing decision — `expect(getPromptSource(model)).toBe("gpt-5-6")`, never the sentence that routing produces
|
|
114
114
|
- a structural token the runtime dispatches on — a tool name, a tag like `<agent-identity>`, a parsed frontmatter field
|
|
115
115
|
- the conditional the code enforces — skill loaded → tool present; `verbose=false` → directive absent
|
|
116
|
+
- a routing-bearing trigger fragment inside a parsed frontmatter `description` that a router (code or an LLM skill-picker) dispatches on — pin the *minimal fragment that carries the routing decision*, never the surrounding style prose. Such pins are what let a later rewrite change every sentence around them while proving the routing contract survived.
|
|
116
117
|
|
|
117
118
|
If no machine consumes the text, there is no seam: write NO test and say so in the PR; review guards prose. When you DELEGATE test-writing, hand the child the behavior the test must distinguish ("fails if override precedence breaks"), never a ready-made assertion string, prompt fragment, or marker to copy — a prescribed mechanism that is wrong gets implemented faithfully, and the error ships with a green suite.
|
|
118
119
|
|
|
@@ -234,6 +235,15 @@ Logging is part of the code you ship, and it has iron rules of its own: levels c
|
|
|
234
235
|
|
|
235
236
|
---
|
|
236
237
|
|
|
238
|
+
## DEPENDENCY UPGRADES — CROSS-CUTTING RULES
|
|
239
|
+
|
|
240
|
+
- **`0.x` minor = major.** Semver promises nothing below 1.0: treat `0.N → 0.N+1` as a breaking upgrade — read the changelog, build, and run the full suite before trusting it. A required field appearing in a public options type is a routine `0.x` "minor".
|
|
241
|
+
- **Version literals live outside the manifest.** Before committing a bump, grep the repo for the old version string: Dockerfiles pinning a global CLI, CI workflows, docs, and contract tests all carry copies. A bump that updates only the package manifest ships a split-brain deploy.
|
|
242
|
+
- **Pin-parity contract tests are a pattern, not a nuisance.** A small test asserting the lockfile-resolved version equals the deploy artifact's pin (Dockerfile, image tag) turns silent drift into a red test. If the project has one, update it deliberately; if the bump reveals unguarded drift, add the test with the bump.
|
|
243
|
+
- **Never hand-merge a lockfile.** On conflict, take either side whole and regenerate with the package manager — the resolver owns that file, not you.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
237
247
|
## MANDATORY POST-WRITE REVIEW LOOP
|
|
238
248
|
|
|
239
249
|
**This runs EVERY time you finish writing or substantively editing code, before you claim the task is done.** No exceptions.
|
|
@@ -56,9 +56,11 @@ Log where the system decides something, not where it does something:
|
|
|
56
56
|
- **Decision points** — retry chosen, fallback engaged, cache bypassed, degraded mode entered.
|
|
57
57
|
- **The one place an error is finally handled.**
|
|
58
58
|
|
|
59
|
-
Never log inside pure functions, utilities, or private helpers — callers with context log outcomes; internals stay silent.
|
|
59
|
+
Never log inside pure functions, utilities, or private helpers — callers with context log outcomes; internals stay silent. The mechanical rules:
|
|
60
60
|
|
|
61
61
|
- **One event, one line.** Log-and-rethrow at every layer turns one incident into five look-alike incidents. Log where the error is handled; layers that only propagate stay silent.
|
|
62
|
+
- **Answering the caller is not logging.** Converting a failure into a response — an HTTP 5xx body, an SSE error event, an error string returned to an LLM as a tool result, a non-zero exit code — satisfies the caller and leaves operations blind. This is the dominant finding when error paths are audited: the caller got an answer, the on-call got nothing. Every path that converts a failure into a caller-facing signal logs that failure exactly once, at the layer that handles it. When conversion layers stack, mark the error as logged at the handling layer (a symbol/flag on the error object) so outer catch-all handlers skip it — one incident, one line.
|
|
63
|
+
- **Expected feedback returned to the caller is not an event.** Validation results delivered as a normal response — including tool output an LLM agent consumes ("string not found", lint findings, a sandbox-boundary notice) — are response content, not anomalies. Log only the genuine I/O and subprocess failures behind them, and security rejections.
|
|
62
64
|
- **Mechanical logging belongs to middleware.** Request/response logging is wired once at the framework layer, never hand-assembled per handler. High-volume zero-signal paths (health probes, metrics scrapes) are excluded there as data — an exclusion set — not as scattered `if` statements.
|
|
63
65
|
|
|
64
66
|
**No speculative logs.** "Might need it later" is not a consumer. A log line earns its place through evidence: a debugging session that burned rounds because this state was invisible (see the debugging bridge below), an incident postmortem, an alert that needs the field.
|
|
@@ -69,6 +71,7 @@ Never log inside pure functions, utilities, or private helpers — callers with
|
|
|
69
71
|
- **Correlation or it did not happen.** Request-scoped lines carry the trace/request id; entity-scoped lines carry the entity id. A line you cannot join to its request is noise during the only moments logs matter.
|
|
70
72
|
- **Name events semantically** (`session.destroy`, `payment.fallback`), never positionally ("Step 3"). Step numbers couple the log stream to today's call structure; the first refactor makes them lie.
|
|
71
73
|
- **No secrets.** Tokens, credentials, session cookies, and PII never enter a log line; URLs are sanitized (strip or redact query params like `token`, `key`) before logging. A leaked log is a leaked credential.
|
|
74
|
+
- **Payload content belongs to the tracing channel, not the log stream.** In LLM/agent systems, user messages, model responses, and tool outputs are captured by the tracing product (turn recorder, trace exporter); a log line carries a hash, a length, and at most a short excerpt for correlation. Dumping conversation content into logs bloats the store and leaks data the log pipeline was never hardened for.
|
|
72
75
|
- **The logging path may not break the program.** If a log call can itself fail (serializing exotic state, a wrapper that touches I/O), that failure is caught, downgraded to a `warn` through a channel that cannot fail, and the operation continues. An empty catch around logging is still an empty catch.
|
|
73
76
|
|
|
74
77
|
## Anti-patterns
|
|
@@ -79,6 +82,8 @@ Never log inside pure functions, utilities, or private helpers — callers with
|
|
|
79
82
|
| Introducing a logging framework to a project that has none | Uninvited behavior change; Rule 0 violation |
|
|
80
83
|
| 4xx logged as `error` | Alert noise buries real pages |
|
|
81
84
|
| Log-and-rethrow at every layer | One incident looks like five |
|
|
85
|
+
| Failure converted to a caller response (5xx body, SSE error, LLM tool-error string, exit code) with no log | The caller got an answer; operations got nothing |
|
|
86
|
+
| Logging expected validation feedback that is returned to the caller | Response content, not an event — buries real failures |
|
|
82
87
|
| Variables interpolated into the message string | Un-aggregatable, un-alertable |
|
|
83
88
|
| "Might need it later" logs | No consumer → pure cost |
|
|
84
89
|
| Debug-time prints promoted to permanent `info` | Narration, not state transitions |
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { afterAll, beforeAll, describe, expect, test } from "bun:test"
|
|
2
|
+
import { spawnSync } from "node:child_process"
|
|
3
|
+
import { copyFileSync, mkdirSync, mkdtempSync, rmSync, symlinkSync, writeFileSync } from "node:fs"
|
|
4
|
+
import { createRequire } from "node:module"
|
|
5
|
+
import { tmpdir } from "node:os"
|
|
6
|
+
import { dirname, join } from "node:path"
|
|
7
|
+
|
|
8
|
+
// Regression for lazycodex#111: the script must resolve `typescript` from the
|
|
9
|
+
// caller project (cwd), not from the script's own location, so it works when
|
|
10
|
+
// executed from an installed `~/.codex/...` skill cache.
|
|
11
|
+
|
|
12
|
+
const scriptSource = join(import.meta.dir, "check-no-excuse-rules.ts")
|
|
13
|
+
const repoRequire = createRequire(import.meta.url)
|
|
14
|
+
const typescriptPackageDir = dirname(repoRequire.resolve("typescript/package.json"))
|
|
15
|
+
|
|
16
|
+
let tempRoot = ""
|
|
17
|
+
let cachedScript = ""
|
|
18
|
+
let callerDir = ""
|
|
19
|
+
let callerWithoutTypescriptDir = ""
|
|
20
|
+
|
|
21
|
+
function runNoExcuse(cwd: string, target: string) {
|
|
22
|
+
return spawnSync(process.execPath, ["--no-install", cachedScript, target], {
|
|
23
|
+
cwd,
|
|
24
|
+
encoding: "utf8",
|
|
25
|
+
timeout: 60_000,
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe("#given the no-excuse script is executed from an installed ~/.codex-style skill cache", () => {
|
|
30
|
+
beforeAll(() => {
|
|
31
|
+
// given a cache copy of the script outside any project, and two caller projects:
|
|
32
|
+
// one providing node_modules/typescript, one without typescript at all
|
|
33
|
+
tempRoot = mkdtempSync(join(tmpdir(), "no-excuse-cache-repro-"))
|
|
34
|
+
const cacheDir = join(tempRoot, ".codex", "skills", "programming", "scripts", "typescript")
|
|
35
|
+
mkdirSync(cacheDir, { recursive: true })
|
|
36
|
+
cachedScript = join(cacheDir, "check-no-excuse-rules.ts")
|
|
37
|
+
copyFileSync(scriptSource, cachedScript)
|
|
38
|
+
|
|
39
|
+
callerDir = join(tempRoot, "caller-project")
|
|
40
|
+
mkdirSync(join(callerDir, "node_modules"), { recursive: true })
|
|
41
|
+
symlinkSync(typescriptPackageDir, join(callerDir, "node_modules", "typescript"), "junction")
|
|
42
|
+
writeFileSync(join(callerDir, "clean.ts"), "export const answer: number = 42\n")
|
|
43
|
+
writeFileSync(join(callerDir, "violating.ts"), "const x = foo as any\nexport default x\n")
|
|
44
|
+
|
|
45
|
+
callerWithoutTypescriptDir = join(tempRoot, "caller-without-typescript")
|
|
46
|
+
mkdirSync(callerWithoutTypescriptDir, { recursive: true })
|
|
47
|
+
writeFileSync(join(callerWithoutTypescriptDir, "clean.ts"), "export const answer: number = 42\n")
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
afterAll(() => {
|
|
51
|
+
rmSync(tempRoot, { recursive: true, force: true })
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
// A generous timeout: the first run does a cold TypeScript program load in a
|
|
55
|
+
// spawned subprocess, which can exceed bun test's 5s default on a cold cache
|
|
56
|
+
// (matches the 60s spawnSync ceiling). This bounds the subprocess, it does not
|
|
57
|
+
// wait on wall-clock time as behavior.
|
|
58
|
+
test("#when the caller project provides typescript #then it resolves the caller's typescript and exits 0", () => {
|
|
59
|
+
// when no-excuse runs from the cache copy against the caller project
|
|
60
|
+
const result = runNoExcuse(callerDir, "clean.ts")
|
|
61
|
+
|
|
62
|
+
// then the caller's own typescript is used and the clean file passes
|
|
63
|
+
expect(result.error).toBeUndefined()
|
|
64
|
+
expect(result.status).toBe(0)
|
|
65
|
+
expect(result.stdout).toContain("No violations in 1 file(s).")
|
|
66
|
+
}, 60_000)
|
|
67
|
+
|
|
68
|
+
test("#when a checked file violates the rules #then violations are still reported with exit 1", () => {
|
|
69
|
+
// when no-excuse runs against a file containing `as any`
|
|
70
|
+
const result = runNoExcuse(callerDir, "violating.ts")
|
|
71
|
+
|
|
72
|
+
// then the existing CLI behavior is unchanged
|
|
73
|
+
expect(result.error).toBeUndefined()
|
|
74
|
+
expect(result.status).toBe(1)
|
|
75
|
+
expect(result.stderr).toContain("[no-any-assertion]")
|
|
76
|
+
}, 60_000)
|
|
77
|
+
|
|
78
|
+
test("#when the caller project genuinely lacks typescript #then it fails with a clear error and exit 2", () => {
|
|
79
|
+
// when no-excuse runs from a caller project with no local typescript
|
|
80
|
+
const result = runNoExcuse(callerWithoutTypescriptDir, "clean.ts")
|
|
81
|
+
|
|
82
|
+
// then it reports the resolution problem instead of crashing mid-analysis
|
|
83
|
+
expect(result.error).toBeUndefined()
|
|
84
|
+
expect(result.status).toBe(2)
|
|
85
|
+
expect(result.stderr).toContain('cannot resolve "typescript" from the caller project')
|
|
86
|
+
}, 60_000)
|
|
87
|
+
})
|