@toolu/opencode 6.8.0
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/generated/GENERATED-NOTES.md +16 -0
- package/generated/agents/toolu--architect.md +52 -0
- package/generated/agents/toolu--deep-explore.md +65 -0
- package/generated/agents/toolu--implementer.md +50 -0
- package/generated/agents/toolu--quick-task.md +54 -0
- package/generated/agents/toolu--research-agent.md +101 -0
- package/generated/commands/toolu--commit.md +8 -0
- package/generated/commands/toolu--review-and-commit.md +8 -0
- package/generated/opencode.toolu.json +116 -0
- package/generated/skills/toolu--brainstorm/SKILL.md +57 -0
- package/generated/skills/toolu--brainstorm/references/design-questions.md +36 -0
- package/generated/skills/toolu--commit--skill/SKILL.md +11 -0
- package/generated/skills/toolu--debug/SKILL.md +54 -0
- package/generated/skills/toolu--deep-research/SKILL.md +51 -0
- package/generated/skills/toolu--execution/SKILL.md +77 -0
- package/generated/skills/toolu--orchestrator/SKILL.md +145 -0
- package/generated/skills/toolu--orchestrator/references/delegation-cost.md +104 -0
- package/generated/skills/toolu--orchestrator/references/model-routing.md +112 -0
- package/generated/skills/toolu--plan/SKILL.md +56 -0
- package/generated/skills/toolu--plan/references/ledger.md +18 -0
- package/generated/skills/toolu--plan-review/SKILL.md +48 -0
- package/generated/skills/toolu--review-and-commit--skill/SKILL.md +10 -0
- package/generated/skills/toolu--setup/SKILL.md +24 -0
- package/generated/skills/toolu--setup/scripts/setup.sh +206 -0
- package/generated/skills/toolu--spec/SKILL.md +67 -0
- package/generated/skills/toolu--spec-review/SKILL.md +50 -0
- package/generated/skills/toolu--test/SKILL.md +49 -0
- package/package.json +51 -0
- package/plugins/agent-browser/.claude-plugin/plugin.json +18 -0
- package/plugins/agent-browser/.codex-plugin/plugin.json +7 -0
- package/plugins/agent-browser/README.md +18 -0
- package/plugins/agent-browser/hooks/hooks.json +15 -0
- package/plugins/agent-browser/hooks/session-start.sh +42 -0
- package/plugins/agent-browser/skills/agent-browser/SKILL.md +77 -0
- package/plugins/agent-browser/skills/agent-browser/scripts/agent-browser.sh +80 -0
- package/plugins/ast-grep/.claude-plugin/plugin.json +18 -0
- package/plugins/ast-grep/.codex-plugin/plugin.json +7 -0
- package/plugins/ast-grep/README.md +21 -0
- package/plugins/ast-grep/hooks/hooks.json +15 -0
- package/plugins/ast-grep/hooks/post-tools.d/byte-savings.sh +67 -0
- package/plugins/ast-grep/hooks/pre-tools.d/search-nudge.sh +170 -0
- package/plugins/ast-grep/hooks/register.sh +68 -0
- package/plugins/ast-grep/scripts/byte-savings-report.sh +28 -0
- package/plugins/ast-grep/skills/ast-grep/SKILL.md +127 -0
- package/plugins/ast-grep/skills/ast-grep/references/ast-grep-advanced.md +44 -0
- package/plugins/ast-grep/skills/ast-grep/scripts/ast-grep.sh +103 -0
- package/plugins/context7/.claude-plugin/plugin.json +18 -0
- package/plugins/context7/.codex-plugin/plugin.json +7 -0
- package/plugins/context7/README.md +19 -0
- package/plugins/context7/hooks/hooks.json +15 -0
- package/plugins/context7/hooks/session-start.sh +42 -0
- package/plugins/context7/skills/context7/SKILL.md +64 -0
- package/plugins/context7/skills/context7/scripts/search.sh +151 -0
- package/plugins/exa-search/.claude-plugin/plugin.json +18 -0
- package/plugins/exa-search/.codex-plugin/plugin.json +7 -0
- package/plugins/exa-search/README.md +19 -0
- package/plugins/exa-search/hooks/hooks.json +15 -0
- package/plugins/exa-search/hooks/session-start.sh +34 -0
- package/plugins/exa-search/skills/exa-search/SKILL.md +91 -0
- package/plugins/exa-search/skills/exa-search/scripts/search.sh +221 -0
- package/plugins/jev/.claude-plugin/plugin.json +19 -0
- package/plugins/jev/.codex-plugin/plugin.json +7 -0
- package/plugins/jev/README.md +61 -0
- package/plugins/jev/hooks/hooks.json +25 -0
- package/plugins/jev/hooks/lib/common.sh +49 -0
- package/plugins/jev/hooks/session-start.sh +45 -0
- package/plugins/jev/hooks/user-prompt-submit.sh +41 -0
- package/plugins/jev/skills/jev/SKILL.md +81 -0
- package/plugins/jev/skills/jev/evals/README.md +98 -0
- package/plugins/jev/skills/jev/references/problem-solving.md +198 -0
- package/plugins/jev/skills/jev/scripts/jev.sh +405 -0
- package/plugins/jira/.claude-plugin/plugin.json +18 -0
- package/plugins/jira/.codex-plugin/plugin.json +7 -0
- package/plugins/jira/README.md +42 -0
- package/plugins/jira/hooks/hooks.json +15 -0
- package/plugins/jira/hooks/session-start.sh +34 -0
- package/plugins/jira/skills/jira/SKILL.md +123 -0
- package/plugins/jira/skills/jira/scripts/jira.sh +70 -0
- package/plugins/jira/skills/jira/scripts/lib/adf.sh +17 -0
- package/plugins/jira/skills/jira/scripts/lib/attachment.sh +94 -0
- package/plugins/jira/skills/jira/scripts/lib/board.sh +58 -0
- package/plugins/jira/skills/jira/scripts/lib/http.sh +184 -0
- package/plugins/jira/skills/jira/scripts/lib/issue.sh +159 -0
- package/plugins/jira/skills/jira/scripts/lib/paginate.sh +45 -0
- package/plugins/jira/skills/jira/scripts/lib/plan-parse.sh +70 -0
- package/plugins/jira/skills/jira/scripts/lib/plan-run.sh +115 -0
- package/plugins/jira/skills/jira/scripts/lib/plan-store.sh +168 -0
- package/plugins/jira/skills/jira/scripts/lib/plan.sh +108 -0
- package/plugins/jira/skills/jira/scripts/lib/project.sh +42 -0
- package/plugins/jira/skills/jira/scripts/lib/raw.sh +15 -0
- package/plugins/jira/skills/jira/scripts/lib/search.sh +41 -0
- package/plugins/jira/skills/jira/scripts/lib/sprint.sh +88 -0
- package/plugins/jira/skills/jira/scripts/lib/user.sh +45 -0
- package/plugins/jira/skills/jira/scripts/lib/worklog.sh +56 -0
- package/plugins/pr-babysit/.claude-plugin/plugin.json +25 -0
- package/plugins/pr-babysit/.codex-plugin/plugin.json +7 -0
- package/plugins/pr-babysit/README.md +38 -0
- package/plugins/pr-babysit/commands/babysit.md +13 -0
- package/plugins/pr-babysit/hooks/check-toolu.sh +20 -0
- package/plugins/pr-babysit/hooks/hooks.json +15 -0
- package/plugins/pr-babysit/scripts/babysit-tick.sh +133 -0
- package/plugins/pr-babysit/scripts/collect-pr.sh +224 -0
- package/plugins/pr-babysit/scripts/lib/common.sh +146 -0
- package/plugins/pr-babysit/scripts/lib/gh.sh +150 -0
- package/plugins/pr-babysit/scripts/lib/lock.sh +84 -0
- package/plugins/pr-babysit/scripts/lib/normalize.sh +98 -0
- package/plugins/pr-babysit/scripts/lib/state.sh +37 -0
- package/plugins/pr-babysit/scripts/parse-verdict.sh +171 -0
- package/plugins/pr-babysit/scripts/record.sh +69 -0
- package/plugins/pr-babysit/scripts/reduce-state.sh +245 -0
- package/plugins/pr-babysit/scripts/reply-thread.sh +90 -0
- package/plugins/pr-babysit/scripts/resolve-thread.sh +71 -0
- package/plugins/pr-babysit/skills/babysit/SKILL.md +31 -0
- package/plugins/pr-babysit/skills/babysit/references/helper.md +209 -0
- package/plugins/pr-babysit/workflows/babysit.md +722 -0
- package/plugins/python-quality/.claude-plugin/plugin.json +24 -0
- package/plugins/python-quality/.codex-plugin/plugin.json +6 -0
- package/plugins/python-quality/README.md +23 -0
- package/plugins/python-quality/hooks/check-toolu.sh +20 -0
- package/plugins/python-quality/hooks/concerns/00-preamble.sh +85 -0
- package/plugins/python-quality/hooks/concerns/10-size-file.sh +6 -0
- package/plugins/python-quality/hooks/concerns/20-tests.sh +37 -0
- package/plugins/python-quality/hooks/concerns/30-suppression.sh +33 -0
- package/plugins/python-quality/hooks/concerns/50-size-fn.sh +49 -0
- package/plugins/python-quality/hooks/concerns/70-no-mocks.sh +76 -0
- package/plugins/python-quality/hooks/concerns/90-docs.sh +52 -0
- package/plugins/python-quality/hooks/concerns/99-finalize.sh +36 -0
- package/plugins/python-quality/hooks/hooks.json +19 -0
- package/plugins/python-quality/hooks/register.sh +65 -0
- package/plugins/rust-quality/.claude-plugin/plugin.json +24 -0
- package/plugins/rust-quality/.codex-plugin/plugin.json +6 -0
- package/plugins/rust-quality/README.md +24 -0
- package/plugins/rust-quality/hooks/check-toolu.sh +20 -0
- package/plugins/rust-quality/hooks/concerns/00-preamble.sh +93 -0
- package/plugins/rust-quality/hooks/concerns/10-size-file.sh +10 -0
- package/plugins/rust-quality/hooks/concerns/20-tests.sh +84 -0
- package/plugins/rust-quality/hooks/concerns/30-suppression.sh +26 -0
- package/plugins/rust-quality/hooks/concerns/40-unsafe.sh +39 -0
- package/plugins/rust-quality/hooks/concerns/50-size-fn.sh +38 -0
- package/plugins/rust-quality/hooks/concerns/55-size-impl.sh +28 -0
- package/plugins/rust-quality/hooks/concerns/60-error-handling.sh +149 -0
- package/plugins/rust-quality/hooks/concerns/70-no-mocks.sh +139 -0
- package/plugins/rust-quality/hooks/concerns/90-docs.sh +32 -0
- package/plugins/rust-quality/hooks/concerns/99-finalize.sh +36 -0
- package/plugins/rust-quality/hooks/hooks.json +19 -0
- package/plugins/rust-quality/hooks/register.sh +65 -0
- package/plugins/statusline/.claude-plugin/plugin.json +19 -0
- package/plugins/statusline/.codex-plugin/plugin.json +7 -0
- package/plugins/statusline/README.md +108 -0
- package/plugins/statusline/commands/setup.md +30 -0
- package/plugins/statusline/hooks/hooks.json +15 -0
- package/plugins/statusline/hooks/session-start.sh +45 -0
- package/plugins/statusline/scripts/collect-status.sh +147 -0
- package/plugins/statusline/scripts/setup.sh +93 -0
- package/plugins/statusline/scripts/status.sh +55 -0
- package/plugins/statusline/skills/status/SKILL.md +13 -0
- package/plugins/statusline/statusline.sh +177 -0
- package/plugins/toolu/.claude-plugin/plugin.json +19 -0
- package/plugins/toolu/.codex-plugin/plugin.json +7 -0
- package/plugins/toolu/README.md +35 -0
- package/plugins/toolu/agents/.gitkeep +0 -0
- package/plugins/toolu/agents/architect.md +52 -0
- package/plugins/toolu/agents/deep-explore.md +65 -0
- package/plugins/toolu/agents/implementer.md +50 -0
- package/plugins/toolu/agents/quick-task.md +54 -0
- package/plugins/toolu/agents/research-agent.md +107 -0
- package/plugins/toolu/assets/agents/architect.toml +9 -0
- package/plugins/toolu/assets/agents/deep-explore.toml +9 -0
- package/plugins/toolu/assets/agents/implementer.toml +9 -0
- package/plugins/toolu/assets/agents/quick-task.toml +9 -0
- package/plugins/toolu/assets/agents/research-agent.toml +9 -0
- package/plugins/toolu/commands/.gitkeep +0 -0
- package/plugins/toolu/commands/commit.md +5 -0
- package/plugins/toolu/commands/review-and-commit.md +5 -0
- package/plugins/toolu/hooks/docs/gates.md +157 -0
- package/plugins/toolu/hooks/docs/model-routing.md +14 -0
- package/plugins/toolu/hooks/docs/post-compaction.md +3 -0
- package/plugins/toolu/hooks/docs/push-review.md +123 -0
- package/plugins/toolu/hooks/docs/session-start-python.md +3 -0
- package/plugins/toolu/hooks/docs/session-start-rust.md +4 -0
- package/plugins/toolu/hooks/docs/session-start-ts.md +3 -0
- package/plugins/toolu/hooks/docs/session-start.md +16 -0
- package/plugins/toolu/hooks/hooks.json +76 -0
- package/plugins/toolu/hooks/lib/config.sh +355 -0
- package/plugins/toolu/hooks/lib/detect.sh +929 -0
- package/plugins/toolu/hooks/lib/diff-sha.sh +32 -0
- package/plugins/toolu/hooks/lib/dispatch.sh +365 -0
- package/plugins/toolu/hooks/lib/docs-sync-config.sh +81 -0
- package/plugins/toolu/hooks/lib/edit-records.sh +157 -0
- package/plugins/toolu/hooks/lib/gate-file.sh +201 -0
- package/plugins/toolu/hooks/lib/gate-mode.sh +244 -0
- package/plugins/toolu/hooks/lib/host.sh +205 -0
- package/plugins/toolu/hooks/lib/permissions.sh +125 -0
- package/plugins/toolu/hooks/lib/plan-ledger-parse.sh +219 -0
- package/plugins/toolu/hooks/lib/plan-ledger-preflight.sh +137 -0
- package/plugins/toolu/hooks/lib/plan-ledger.sh +749 -0
- package/plugins/toolu/hooks/lib/push-waiver.sh +116 -0
- package/plugins/toolu/hooks/lib/quality-config.sh +184 -0
- package/plugins/toolu/hooks/lib/registry.sh +72 -0
- package/plugins/toolu/hooks/lib/state-sweeper.sh +194 -0
- package/plugins/toolu/hooks/lib/telemetry.sh +94 -0
- package/plugins/toolu/hooks/lib/verdict.sh +477 -0
- package/plugins/toolu/hooks/post-tools/mod.sh +42 -0
- package/plugins/toolu/hooks/post-tools/modules/gate-status.sh +140 -0
- package/plugins/toolu/hooks/post-tools/modules/push-waiver.sh +97 -0
- package/plugins/toolu/hooks/pre-compact.sh +18 -0
- package/plugins/toolu/hooks/pre-tools/agent-tier.sh +111 -0
- package/plugins/toolu/hooks/pre-tools/mod.sh +37 -0
- package/plugins/toolu/hooks/pre-tools/modules/bash-commands.sh +187 -0
- package/plugins/toolu/hooks/pre-tools/modules/code-edit-rules.sh +78 -0
- package/plugins/toolu/hooks/pre-tools/modules/commit-gate.sh +70 -0
- package/plugins/toolu/hooks/pre-tools/modules/docs-sync.sh +137 -0
- package/plugins/toolu/hooks/pre-tools/modules/mcp-blocker.sh +151 -0
- package/plugins/toolu/hooks/pre-tools/modules/plan-ledger.sh +201 -0
- package/plugins/toolu/hooks/pre-tools/modules/protected-files.sh +177 -0
- package/plugins/toolu/hooks/pre-tools/modules/push-review.sh +273 -0
- package/plugins/toolu/hooks/pre-tools/modules/quality-gate.sh +87 -0
- package/plugins/toolu/hooks/session-start.sh +379 -0
- package/plugins/toolu/hooks/user-prompt-submit.sh +197 -0
- package/plugins/toolu/scripts/context-budget.sh +111 -0
- package/plugins/toolu/scripts/debug-log.sh +98 -0
- package/plugins/toolu/scripts/debug-stack.sh +108 -0
- package/plugins/toolu/scripts/debug-testfail.sh +97 -0
- package/plugins/toolu/settings/.gitkeep +0 -0
- package/plugins/toolu/settings/README.md +127 -0
- package/plugins/toolu/settings/bash-allowlist.txt +12 -0
- package/plugins/toolu/settings/bash-denylist.txt +25 -0
- package/plugins/toolu/settings/code-edit-rules.json +67 -0
- package/plugins/toolu/settings/commit-prefixes.txt +12 -0
- package/plugins/toolu/settings/mcp-blocklist.txt +8 -0
- package/plugins/toolu/settings/permissions.fragment.json +36 -0
- package/plugins/toolu/settings/protected-files.txt +30 -0
- package/plugins/toolu/settings/rust-unsafe-exemptions.txt +5 -0
- package/plugins/toolu/settings/toolu.config.example.json +130 -0
- package/plugins/toolu/skills/.gitkeep +0 -0
- package/plugins/toolu/skills/brainstorm/SKILL.md +57 -0
- package/plugins/toolu/skills/brainstorm/references/design-questions.md +36 -0
- package/plugins/toolu/skills/commit/SKILL.md +11 -0
- package/plugins/toolu/skills/debug/SKILL.md +54 -0
- package/plugins/toolu/skills/debug/evals/README.md +17 -0
- package/plugins/toolu/skills/debug/evals/cases.json +24 -0
- package/plugins/toolu/skills/debug/evals/results.json +34 -0
- package/plugins/toolu/skills/deep-research/SKILL.md +51 -0
- package/plugins/toolu/skills/execution/SKILL.md +77 -0
- package/plugins/toolu/skills/orchestrator/SKILL.md +145 -0
- package/plugins/toolu/skills/orchestrator/references/delegation-cost.md +104 -0
- package/plugins/toolu/skills/orchestrator/references/model-routing.md +112 -0
- package/plugins/toolu/skills/plan/SKILL.md +56 -0
- package/plugins/toolu/skills/plan/references/ledger.md +18 -0
- package/plugins/toolu/skills/plan-review/SKILL.md +48 -0
- package/plugins/toolu/skills/review-and-commit/SKILL.md +10 -0
- package/plugins/toolu/skills/setup/SKILL.md +24 -0
- package/plugins/toolu/skills/setup/scripts/setup.sh +206 -0
- package/plugins/toolu/skills/spec/SKILL.md +67 -0
- package/plugins/toolu/skills/spec-review/SKILL.md +50 -0
- package/plugins/toolu/skills/test/SKILL.md +49 -0
- package/plugins/toolu/workflows/commit.md +21 -0
- package/plugins/toolu/workflows/host-mapping.md +22 -0
- package/plugins/toolu/workflows/review-and-commit.md +54 -0
- package/plugins/toolu/workflows/semantic-judgments.md +35 -0
- package/plugins/toolu-review/.claude-plugin/plugin.json +18 -0
- package/plugins/toolu-review/.codex-plugin/plugin.json +7 -0
- package/plugins/toolu-review/README.md +17 -0
- package/plugins/toolu-review/hooks/hooks.json +15 -0
- package/plugins/toolu-review/hooks/session-start.sh +34 -0
- package/plugins/toolu-review/skills/review/SKILL.md +90 -0
- package/plugins/toolu-review/skills/review/scripts/write-state.sh +189 -0
- package/plugins/ts-quality/.claude-plugin/plugin.json +24 -0
- package/plugins/ts-quality/.codex-plugin/plugin.json +6 -0
- package/plugins/ts-quality/README.md +24 -0
- package/plugins/ts-quality/hooks/check-toolu.sh +20 -0
- package/plugins/ts-quality/hooks/concerns/00-preamble.sh +123 -0
- package/plugins/ts-quality/hooks/concerns/10-imports.sh +33 -0
- package/plugins/ts-quality/hooks/concerns/15-type-as.sh +9 -0
- package/plugins/ts-quality/hooks/concerns/20-tests.sh +26 -0
- package/plugins/ts-quality/hooks/concerns/25-size-file.sh +40 -0
- package/plugins/ts-quality/hooks/concerns/30-size-fn.sh +53 -0
- package/plugins/ts-quality/hooks/concerns/35-react-hooks.sh +7 -0
- package/plugins/ts-quality/hooks/concerns/40-factory.sh +5 -0
- package/plugins/ts-quality/hooks/concerns/45-typeguard.sh +6 -0
- package/plugins/ts-quality/hooks/concerns/50-type-dup.sh +16 -0
- package/plugins/ts-quality/hooks/concerns/55-naming.sh +11 -0
- package/plugins/ts-quality/hooks/concerns/60-console.sh +6 -0
- package/plugins/ts-quality/hooks/concerns/65-suppression.sh +12 -0
- package/plugins/ts-quality/hooks/concerns/70-ui-confirm.sh +8 -0
- package/plugins/ts-quality/hooks/concerns/72-ui-radix.sh +12 -0
- package/plugins/ts-quality/hooks/concerns/74-react-props.sh +6 -0
- package/plugins/ts-quality/hooks/concerns/76-toast.sh +10 -0
- package/plugins/ts-quality/hooks/concerns/78-error-ast.sh +242 -0
- package/plugins/ts-quality/hooks/concerns/80-throw-literal.sh +23 -0
- package/plugins/ts-quality/hooks/concerns/85-no-mocks.sh +109 -0
- package/plugins/ts-quality/hooks/concerns/90-duplication.sh +30 -0
- package/plugins/ts-quality/hooks/concerns/92-docs.sh +36 -0
- package/plugins/ts-quality/hooks/concerns/94-handler.sh +15 -0
- package/plugins/ts-quality/hooks/concerns/99-finalize.sh +46 -0
- package/plugins/ts-quality/hooks/hooks.json +19 -0
- package/plugins/ts-quality/hooks/register.sh +65 -0
- package/src/adapter/__tests__/evaluate.test.ts +82 -0
- package/src/adapter/__tests__/permission-map.test.ts +91 -0
- package/src/adapter/evaluate.ts +54 -0
- package/src/adapter/permission-map.ts +177 -0
- package/src/bootstrap/__tests__/bootstrap.test.ts +148 -0
- package/src/bootstrap/entrypoint.ts +18 -0
- package/src/bootstrap/index.ts +5 -0
- package/src/bootstrap/readiness.ts +59 -0
- package/src/bootstrap/result.ts +21 -0
- package/src/bootstrap/runtime.ts +99 -0
- package/src/bootstrap/test-helpers.ts +25 -0
- package/src/host/__tests__/host.test.ts +37 -0
- package/src/host/detect.ts +46 -0
- package/src/host/index.ts +10 -0
- package/src/host/roots.ts +59 -0
- package/src/host/types.ts +14 -0
- package/src/inventory/__tests__/inventory.test.ts +69 -0
- package/src/inventory/index.ts +9 -0
- package/src/inventory/manifest.ts +46 -0
- package/src/inventory/scan.ts +66 -0
- package/src/inventory/selection.ts +92 -0
- package/src/inventory/types.ts +22 -0
- package/src/lifecycle/__tests__/lifecycle.test.ts +7 -0
- package/src/lifecycle/index.ts +2 -0
- package/src/lifecycle/table.ts +42 -0
- package/src/plugin/__tests__/plugin-stub.test.ts +6 -0
- package/src/plugin/plugin-stub.ts +7 -0
- package/src/plugin/toolu.ts +142 -0
- package/src/preflight/__tests__/preflight.test.ts +20 -0
- package/src/preflight/check.ts +75 -0
- package/src/preflight/index.ts +2 -0
- package/src/select/__tests__/select.test.ts +52 -0
- package/src/select/index.ts +2 -0
- package/src/select/resolve.ts +87 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Jev problem-solving patterns
|
|
2
|
+
|
|
3
|
+
Load Setup + the matching example only. Evidence → focused judgment → next action.
|
|
4
|
+
Reassess changed inputs; reuse unchanged evidence/questions/criteria across stages.
|
|
5
|
+
Synthetic scenarios; replace observations with actual evidence in real work.
|
|
6
|
+
|
|
7
|
+
Sources: TypeSafe [semantic search](https://docs.typesafe.ai/cookbooks/semantic_find.md)
|
|
8
|
+
(separate ranking/existence), [citation checking](https://docs.typesafe.ai/cookbooks/citation_check.md)
|
|
9
|
+
(exact quote check before context judgment), [batching](https://docs.typesafe.ai/patterns/fan-out.md)
|
|
10
|
+
(independent questions, shared state). Evaluation only: [record](../evals/README.md).
|
|
11
|
+
|
|
12
|
+
## Setup and failure handling
|
|
13
|
+
|
|
14
|
+
Run setup + selected example in one Bash shell. Requires `curl`, `jq`, environment
|
|
15
|
+
`TYPESAFE_API_KEY`; never read `.env`.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Codex (for Claude Code use the second line instead):
|
|
19
|
+
JEV="${TOOLU_CONFIG_DIR:-${CODEX_HOME:-$HOME/.codex}}/jev/jev.sh"
|
|
20
|
+
# JEV="${TOOLU_CONFIG_DIR:-${CLAUDE_CONFIG_DIR:-$HOME/.claude}}/jev/jev.sh"
|
|
21
|
+
# Repository development, from the repository root, if not installed:
|
|
22
|
+
if [ ! -x "$JEV" ]; then JEV="$PWD/plugins/jev/skills/jev/scripts/jev.sh"; fi
|
|
23
|
+
JEV_EXAMPLES=$(mktemp -d)
|
|
24
|
+
|
|
25
|
+
judge() {
|
|
26
|
+
local name="$1"
|
|
27
|
+
if "$JEV" ask "$JEV_EXAMPLES/$name.questions.json" \
|
|
28
|
+
-s "@$JEV_EXAMPLES/$name.state.json" --raw >"$JEV_EXAMPLES/$name.result.json"; then
|
|
29
|
+
jq '.answers' "$JEV_EXAMPLES/$name.result.json"
|
|
30
|
+
else
|
|
31
|
+
rm -f "$JEV_EXAMPLES/$name.result.json"
|
|
32
|
+
printf '%s\n' "Jev unavailable for $name; inspect the named evidence and apply the rubric manually." >&2
|
|
33
|
+
return 1
|
|
34
|
+
fi
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Failure → apply the example's rubric manually. Missing output is not a negative
|
|
39
|
+
judgment. Uncertain/conflicting distributions → inspect source, gather evidence,
|
|
40
|
+
or narrow question. No universal thresholds. Confidence is concentration, not
|
|
41
|
+
correctness. Retain raw model/usage for evaluation; never credentials.
|
|
42
|
+
|
|
43
|
+
## Search: rank excerpts and detect no answer
|
|
44
|
+
|
|
45
|
+
Named retrieved excerpts: access/restoration and billing. Neither states retention.
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
cat > "$JEV_EXAMPLES/search.state.json" <<'JSON'
|
|
49
|
+
{
|
|
50
|
+
"query": "How long are deleted project backups retained?",
|
|
51
|
+
"excerpts": {
|
|
52
|
+
"access": {"source": "docs/access.md", "text": "Administrators may restore a deleted project from a backup."},
|
|
53
|
+
"billing": {"source": "docs/billing.md", "text": "Invoices are emailed to the billing contact every month."}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
JSON
|
|
57
|
+
cat > "$JEV_EXAMPLES/search.questions.json" <<'JSON'
|
|
58
|
+
{
|
|
59
|
+
"exists": {
|
|
60
|
+
"type": "noul",
|
|
61
|
+
"instructions": "Do the supplied `excerpts` contain an answer to `query`, including its requested retention duration?",
|
|
62
|
+
"criteria": {"true": "The duration is stated or unambiguously implied in the excerpts.", "false": "The excerpts omit the duration, even if they discuss backups or restoration."}
|
|
63
|
+
},
|
|
64
|
+
"access_relevance": {
|
|
65
|
+
"type": "score",
|
|
66
|
+
"instructions": "How well does `excerpts.access.text` answer `query`? Use only this excerpt.",
|
|
67
|
+
"criteria": ["Unrelated to deleted project backups.", "Discusses backups or restoration but omits the requested duration.", "Supplies the requested backup retention duration."]
|
|
68
|
+
},
|
|
69
|
+
"billing_relevance": {
|
|
70
|
+
"type": "score",
|
|
71
|
+
"instructions": "How well does `excerpts.billing.text` answer `query`? Use only this excerpt.",
|
|
72
|
+
"criteria": ["Unrelated to deleted project backups.", "Discusses backups or restoration but omits the requested duration.", "Supplies the requested backup retention duration."]
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
JSON
|
|
76
|
+
judge search
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Interpret: sort comparable Scores in code; inspect legend/distribution. A top
|
|
80
|
+
rank can still be incomplete. Choice probabilities are relative, not graded
|
|
81
|
+
relevance. Here, access ranks first but existence should be negative.
|
|
82
|
+
Next: retrieve retention policy; never infer retention from billing frequency.
|
|
83
|
+
Uncertain → inspect surrounding source/refine retrieval. API failure → manually
|
|
84
|
+
confirm missing duration, then retrieve policy.
|
|
85
|
+
|
|
86
|
+
## Debugging: prioritize an experiment, then reassess
|
|
87
|
+
|
|
88
|
+
Supplied observations + hypotheses + experiments. Judgments prioritize tests;
|
|
89
|
+
they do not prove causes.
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
cat > "$JEV_EXAMPLES/debug.state.json" <<'JSON'
|
|
93
|
+
{
|
|
94
|
+
"observations": {"cold": "A fresh profile renders the current label.", "warm": "An existing profile still renders the old label after refresh."},
|
|
95
|
+
"hypotheses": {"cache": "A browser cache is serving stale assets.", "server": "The server serves an old build to every profile."},
|
|
96
|
+
"experiments": {"cache": "Disable the browser cache in the affected profile and reload.", "server": "Compare the deployed asset hash against the build artifact."}
|
|
97
|
+
}
|
|
98
|
+
JSON
|
|
99
|
+
cat > "$JEV_EXAMPLES/debug.questions.json" <<'JSON'
|
|
100
|
+
{
|
|
101
|
+
"next": {
|
|
102
|
+
"type": "choice",
|
|
103
|
+
"instructions": "Which supplied hypothesis best fits all `observations` and should have its `experiments` entry tried next? This is experiment prioritization, not proof of a cause.",
|
|
104
|
+
"criteria": {"cache": "The profile-dependent behavior favors stale browser assets.", "server": "The observations favor the same old deployment affecting all profiles.", "insufficient": "Neither hypothesis explains the observations, or evidence cannot distinguish them."}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
JSON
|
|
108
|
+
judge debug
|
|
109
|
+
|
|
110
|
+
# Synthetic result of running the cache experiment; in real work supply actual output.
|
|
111
|
+
jq '.observations += {"cache_disabled": "Old label persists with browser cache disabled.", "network": "Both profiles receive identical current assets.", "storage": "Only the affected profile has a saved label override in local storage."}' \
|
|
112
|
+
"$JEV_EXAMPLES/debug.state.json" > "$JEV_EXAMPLES/debug-next.state.json"
|
|
113
|
+
cp "$JEV_EXAMPLES/debug.questions.json" "$JEV_EXAMPLES/debug-next.questions.json"
|
|
114
|
+
judge debug-next
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Interpret: first judgment prioritizes the cache experiment. New observations
|
|
118
|
+
invalidate reuse; second should select `insufficient`. Next: test a local-storage
|
|
119
|
+
hypothesis by removing/restoring only the saved override in a disposable profile.
|
|
120
|
+
Confirm through reproduction before fixing. Cache still selected → inspect
|
|
121
|
+
contradictory evidence, revise candidates. Uncertainty/API failure → choose the
|
|
122
|
+
discriminating experiment from explicit evidence, without claiming certainty.
|
|
123
|
+
|
|
124
|
+
## Planning: compare approaches against separate preferences
|
|
125
|
+
|
|
126
|
+
Named alternatives + separate preferences → independent questions, one batch.
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
cat > "$JEV_EXAMPLES/plan.state.json" <<'JSON'
|
|
130
|
+
{
|
|
131
|
+
"preferences": {"delivery": "Ship a working export this week.", "operations": "Avoid operating a new service."},
|
|
132
|
+
"approaches": {"worker": "Use the existing job worker and database; estimated two days of implementation.", "service": "Build and deploy a dedicated export service; estimated two weeks plus new monitoring."}
|
|
133
|
+
}
|
|
134
|
+
JSON
|
|
135
|
+
cat > "$JEV_EXAMPLES/plan.questions.json" <<'JSON'
|
|
136
|
+
{
|
|
137
|
+
"delivery": {
|
|
138
|
+
"type": "choice",
|
|
139
|
+
"instructions": "Which approach in `approaches` best fits `preferences.delivery`, taking the supplied estimates as assumptions rather than verified facts?",
|
|
140
|
+
"criteria": {"worker": "The existing worker approach better meets the delivery preference.", "service": "The dedicated service approach better meets the delivery preference.", "neither": "Neither approach meets it, or the supplied information cannot distinguish them."}
|
|
141
|
+
},
|
|
142
|
+
"operations": {
|
|
143
|
+
"type": "choice",
|
|
144
|
+
"instructions": "Which approach in `approaches` best fits `preferences.operations`?",
|
|
145
|
+
"criteria": {"worker": "The existing worker approach better meets the operations preference.", "service": "The dedicated service approach better meets the operations preference.", "neither": "Neither approach meets it, or the supplied information cannot distinguish them."}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
JSON
|
|
149
|
+
judge plan
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Interpret: worker fits both supplied preferences. Next: verify worker capacity,
|
|
153
|
+
retry semantics, and export requirements; Jev cannot validate estimates or
|
|
154
|
+
feasibility. Conflicting preferences/`neither`/uncertainty → inspect tradeoffs or
|
|
155
|
+
missing requirements. Reuse unchanged results at review; changed capacity →
|
|
156
|
+
reassess affected questions. API failure → manually compare each preference and
|
|
157
|
+
retain the technical checks.
|
|
158
|
+
|
|
159
|
+
## Review: support, contradiction, or unsupported claim
|
|
160
|
+
|
|
161
|
+
Named policy source + quote + claim. Check quote presence with code, then context.
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
cat > "$JEV_EXAMPLES/review.state.json" <<'JSON'
|
|
165
|
+
{
|
|
166
|
+
"source": {"path": "docs/export-policy.md", "text": "Admins may request exports. Members cannot request exports; ask an admin to submit the request."},
|
|
167
|
+
"quote": "Members cannot request exports",
|
|
168
|
+
"claim": "Members may request exports directly."
|
|
169
|
+
}
|
|
170
|
+
JSON
|
|
171
|
+
cat > "$JEV_EXAMPLES/review.questions.json" <<'JSON'
|
|
172
|
+
{
|
|
173
|
+
"relation": {
|
|
174
|
+
"type": "choice",
|
|
175
|
+
"instructions": "How does `source.text`, read in full context, relate to `claim`? Use only the supplied source, not outside knowledge.",
|
|
176
|
+
"criteria": {"supports": "The source establishes the claim as stated, including its scope and qualifications.", "contradicts": "The source states something incompatible with the claim.", "unsupported": "The source neither establishes nor contradicts the claim, or lacks the context needed to decide."}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
JSON
|
|
180
|
+
if jq -e '.quote as $quote | .source.text | contains($quote)' \
|
|
181
|
+
"$JEV_EXAMPLES/review.state.json" >/dev/null; then
|
|
182
|
+
judge review
|
|
183
|
+
else
|
|
184
|
+
printf '%s\n' 'Quote absent: fetch the source and repair the citation before semantic review.' >&2
|
|
185
|
+
fi
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Interpret: `contradicts` → correct claim and cite full passage. `unsupported` →
|
|
189
|
+
retrieve evidence, qualify, or drop claim; unsupported does not mean false.
|
|
190
|
+
`supports` concerns this excerpt, not source truth/currency. Next: verify provenance
|
|
191
|
+
and product behavior with tools. Uncertain/API failure → read full passage and
|
|
192
|
+
record explicit reasoning; never fabricate a Jev verdict.
|
|
193
|
+
|
|
194
|
+
Clean up after retaining evaluation notes:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
rm -rf "$JEV_EXAMPLES"
|
|
198
|
+
```
|
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# jev — typed judgments from TypeSafe's System One API.
|
|
5
|
+
# Usage: ./jev.sh <command> [options]
|
|
6
|
+
#
|
|
7
|
+
# Reads TYPESAFE_API_KEY from the environment (never from .env).
|
|
8
|
+
|
|
9
|
+
command -v jq >/dev/null 2>&1 || { echo "jev: jq required" >&2; exit 1; }
|
|
10
|
+
command -v curl >/dev/null 2>&1 || { echo "jev: curl required" >&2; exit 1; }
|
|
11
|
+
|
|
12
|
+
JEV_URL="https://api.typesafe.ai/v1/systemone"
|
|
13
|
+
DEFAULT_MODEL="jev-latest"
|
|
14
|
+
|
|
15
|
+
# One check covers both unset and empty; the inline default keeps `set -u`
|
|
16
|
+
# from aborting before the message can print.
|
|
17
|
+
if [[ -z "${TYPESAFE_API_KEY:-}" ]]; then
|
|
18
|
+
echo "jev: TYPESAFE_API_KEY unset" >&2
|
|
19
|
+
exit 1
|
|
20
|
+
fi
|
|
21
|
+
if [[ "$TYPESAFE_API_KEY" == *$'\r'* || "$TYPESAFE_API_KEY" == *$'\n'* ]]; then
|
|
22
|
+
echo "jev: TYPESAFE_API_KEY must not contain line breaks" >&2
|
|
23
|
+
exit 1
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
die() { echo "jev: $1" >&2; exit 1; }
|
|
27
|
+
|
|
28
|
+
usage() {
|
|
29
|
+
cat >&2 <<'EOF'
|
|
30
|
+
jev.sh <command> [options]
|
|
31
|
+
|
|
32
|
+
Commands:
|
|
33
|
+
noul <instructions> Yes/no judgment -> probability of yes
|
|
34
|
+
choice <instructions> Pick one option -> choice + probabilities + confidence
|
|
35
|
+
score <instructions> Rate on ordered levels -> score + legend + confidence
|
|
36
|
+
ask <questions-json> Many typed questions in ONE call (file path, or - for stdin)
|
|
37
|
+
|
|
38
|
+
Shared options:
|
|
39
|
+
-s, --state VALUE State to judge: literal text, @FILE, or - for stdin [required]
|
|
40
|
+
-m, --model NAME Model (default: jev-latest)
|
|
41
|
+
--id NAME Question id in the answer map (default: q)
|
|
42
|
+
--raw Print the whole response body instead of just .answers
|
|
43
|
+
|
|
44
|
+
noul: --true DESC / --false DESC what a yes / a no means
|
|
45
|
+
choice: -o, --option KEY=DESC repeatable, 2..255 (bare -o KEY sends no description)
|
|
46
|
+
score: -l, --level DESC repeatable, 2..10, lowest level first
|
|
47
|
+
EOF
|
|
48
|
+
exit 1
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# Shared option state.
|
|
52
|
+
STATE_RAW=""
|
|
53
|
+
STATE_SET=false
|
|
54
|
+
STATE_FROM_STDIN=false
|
|
55
|
+
MODEL="$DEFAULT_MODEL"
|
|
56
|
+
QID="q"
|
|
57
|
+
RAW=false
|
|
58
|
+
INSTRUCTIONS=""
|
|
59
|
+
|
|
60
|
+
# state_json -> the JSON value for the request's `state` field.
|
|
61
|
+
# A literal string stays a string. @FILE and - are sent as structured JSON only
|
|
62
|
+
# when they parse as an object or an array; anything else (including a bare
|
|
63
|
+
# JSON scalar such as 123) is sent as a string.
|
|
64
|
+
state_json() {
|
|
65
|
+
local text file
|
|
66
|
+
case "$STATE_RAW" in
|
|
67
|
+
-)
|
|
68
|
+
text="$(cat)"
|
|
69
|
+
;;
|
|
70
|
+
@*)
|
|
71
|
+
file="${STATE_RAW#@}"
|
|
72
|
+
[[ -r "$file" ]] || die "cannot read $file"
|
|
73
|
+
text="$(cat "$file")"
|
|
74
|
+
;;
|
|
75
|
+
*)
|
|
76
|
+
printf '%s' "$STATE_RAW" | jq -Rs '.'
|
|
77
|
+
return
|
|
78
|
+
;;
|
|
79
|
+
esac
|
|
80
|
+
if printf '%s' "$text" | jq -se 'length == 1 and (.[0] | type == "object" or type == "array")' >/dev/null 2>&1; then
|
|
81
|
+
printf '%s' "$text" | jq -c '.'
|
|
82
|
+
else
|
|
83
|
+
printf '%s' "$text" | jq -Rs '.'
|
|
84
|
+
fi
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
# claim_stdin — only one option may read stdin per invocation.
|
|
88
|
+
claim_stdin() {
|
|
89
|
+
[[ "$STATE_FROM_STDIN" == true ]] && die "only one option can read stdin"
|
|
90
|
+
STATE_FROM_STDIN=true
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# parse_shared OPTION ARG... -> RETURNS the consumed-arg count (0 = unrecognized).
|
|
94
|
+
# Callers must invoke it as `consumed=0; parse_shared "$@" || consumed=$?` so the
|
|
95
|
+
# non-zero count is read as data instead of tripping `set -e`.
|
|
96
|
+
parse_shared() {
|
|
97
|
+
case "$1" in
|
|
98
|
+
-s|--state)
|
|
99
|
+
[[ $# -ge 2 ]] || die "--state needs a value"
|
|
100
|
+
STATE_RAW="$2"; STATE_SET=true
|
|
101
|
+
[[ "$2" == "-" ]] && claim_stdin
|
|
102
|
+
return 2;;
|
|
103
|
+
-m|--model)
|
|
104
|
+
[[ $# -ge 2 ]] || die "--model needs a value"
|
|
105
|
+
MODEL="$2"; return 2;;
|
|
106
|
+
--id)
|
|
107
|
+
[[ $# -ge 2 ]] || die "--id needs a value"
|
|
108
|
+
QID="$2"; return 2;;
|
|
109
|
+
--raw)
|
|
110
|
+
RAW=true; return 1;;
|
|
111
|
+
esac
|
|
112
|
+
return 0
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
require_state() { [[ "$STATE_SET" == true ]] || die "--state is required"; }
|
|
116
|
+
require_instructions() { [[ -n "$INSTRUCTIONS" ]] || usage; }
|
|
117
|
+
|
|
118
|
+
jev_post() (
|
|
119
|
+
local request="$1" tmp code status attempt delay retry_after
|
|
120
|
+
umask 077
|
|
121
|
+
tmp=$(mktemp -d "${TMPDIR:-/tmp}/jev.XXXXXXXX") || return 1
|
|
122
|
+
trap 'rm -rf "$tmp"' EXIT
|
|
123
|
+
# Keep the key out of process arguments; the private directory is removed on exit.
|
|
124
|
+
printf 'Authorization: Bearer %s\n' "$TYPESAFE_API_KEY" > "$tmp/auth-header"
|
|
125
|
+
for attempt in 1 2 3; do
|
|
126
|
+
status=0
|
|
127
|
+
code=$(printf '%s' "$request" | curl -sS \
|
|
128
|
+
--max-time "${JEV_TIMEOUT:-60}" \
|
|
129
|
+
--output "$tmp/body" --dump-header "$tmp/headers" --write-out '%{http_code}' \
|
|
130
|
+
-X POST "$JEV_URL" \
|
|
131
|
+
-H "@$tmp/auth-header" \
|
|
132
|
+
-H "Content-Type: application/json" -H "Accept: application/json" \
|
|
133
|
+
--data-binary @- 2>"$tmp/error") || status=$?
|
|
134
|
+
if [[ "$status" -eq 0 && "$code" == 2* ]]; then
|
|
135
|
+
cat "$tmp/body"
|
|
136
|
+
return 0
|
|
137
|
+
fi
|
|
138
|
+
# Same retry set as TypeSafe's SDK default policy: HTTP 408, 429, every
|
|
139
|
+
# 5xx (which covers the documented 529 overload), timeouts, and connection
|
|
140
|
+
# errors. curl's own --retry omits 529, so the loop lives here. Separate
|
|
141
|
+
# attempt bodies so transient errors never become answer JSON.
|
|
142
|
+
delay=$((1 << (attempt - 1)))
|
|
143
|
+
# Retry-After (seconds) wins over retry-after-ms (milliseconds, rounded up);
|
|
144
|
+
# both are documented SDK-honored headers. Waits over 60s surface the error.
|
|
145
|
+
retry_after=$(awk 'tolower($1) == "retry-after:" {gsub("\r", "", $2); print $2}' "$tmp/headers")
|
|
146
|
+
if [[ ! "$retry_after" =~ ^[0-9]+$ ]]; then
|
|
147
|
+
retry_after=$(awk 'tolower($1) == "retry-after-ms:" {gsub("\r", "", $2); print $2}' "$tmp/headers")
|
|
148
|
+
if [[ "$retry_after" =~ ^[0-9]+$ ]]; then
|
|
149
|
+
# More than 8 digits is already past the 60s ceiling; skip the arithmetic
|
|
150
|
+
# so an absurd header cannot overflow into a negative delay.
|
|
151
|
+
if [[ ${#retry_after} -gt 8 ]]; then
|
|
152
|
+
retry_after=61
|
|
153
|
+
else
|
|
154
|
+
retry_after=$(( (10#$retry_after + 999) / 1000 ))
|
|
155
|
+
fi
|
|
156
|
+
else
|
|
157
|
+
retry_after=""
|
|
158
|
+
fi
|
|
159
|
+
fi
|
|
160
|
+
if [[ "$retry_after" =~ ^[0-9]+$ ]]; then
|
|
161
|
+
if [[ ${#retry_after} -gt 2 ]] || ((10#$retry_after > 60)); then
|
|
162
|
+
break
|
|
163
|
+
fi
|
|
164
|
+
((10#$retry_after <= delay)) || delay=$((10#$retry_after))
|
|
165
|
+
fi
|
|
166
|
+
[[ "$attempt" -lt 3 ]] || break
|
|
167
|
+
# $code is curl's %{http_code}: three digits, or 000 when no status line
|
|
168
|
+
# arrived (retried as a connection error whatever the exit status).
|
|
169
|
+
# Connection-level failures carry curl's own exit status instead:
|
|
170
|
+
# 7 (connect), 28 (timeout), 35 (TLS handshake), 52 (empty reply),
|
|
171
|
+
# 55 (send), 56 (receive) — the SDK retries these as connection errors.
|
|
172
|
+
case "$status:$code" in
|
|
173
|
+
0:408|0:429|0:5[0-9][0-9]|0:000|7:*|28:*|35:*|52:*|55:*|56:*) sleep "$delay";;
|
|
174
|
+
*) break;;
|
|
175
|
+
esac
|
|
176
|
+
done
|
|
177
|
+
[[ ! -s "$tmp/error" ]] || cat "$tmp/error" >&2
|
|
178
|
+
[[ ! -s "$tmp/body" ]] || cat "$tmp/body" >&2
|
|
179
|
+
[[ "$status" -ne 0 ]] || status=22
|
|
180
|
+
return "$status"
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
# evaluate QUESTIONS_JSON — send the request and print the answers.
|
|
184
|
+
# An HTTP failure propagates: the API's error body goes to stderr and the exit
|
|
185
|
+
# status is curl's own (22 for an error response, 28 for a timeout).
|
|
186
|
+
evaluate() {
|
|
187
|
+
local questions="$1" state body out status
|
|
188
|
+
# Resolved in its own statement: a failure inside state_json exits the command
|
|
189
|
+
# substitution's subshell, and only an explicit check propagates that here.
|
|
190
|
+
state="$(state_json)" || exit $?
|
|
191
|
+
body=$(printf '%s\n%s\n' "$state" "$questions" | jq -sc --arg model "$MODEL" \
|
|
192
|
+
'{state: .[0], model: $model, questions: .[1]}')
|
|
193
|
+
|
|
194
|
+
set +e
|
|
195
|
+
out="$(jev_post "$body")"
|
|
196
|
+
status=$?
|
|
197
|
+
set -e
|
|
198
|
+
if [[ "$status" -ne 0 ]]; then
|
|
199
|
+
[[ -n "$out" ]] && printf '%s\n' "$out" >&2
|
|
200
|
+
exit "$status"
|
|
201
|
+
fi
|
|
202
|
+
|
|
203
|
+
# Never let a malformed success response be consumed as a false/no judgment.
|
|
204
|
+
printf '%s\n%s\n' "$questions" "$out" | jq -se '
|
|
205
|
+
def probability: type == "number" and . >= 0 and . <= 1;
|
|
206
|
+
def tokens: type == "number" and . >= 0 and . == floor;
|
|
207
|
+
def distribution($keys):
|
|
208
|
+
type == "object" and keys == ($keys | sort) and
|
|
209
|
+
all(.[]; probability) and (([.[]] | add) - 1 | fabs) < 0.000001;
|
|
210
|
+
length == 2 and
|
|
211
|
+
(.[0] as $questions | .[1] as $response | $response.answers as $answers |
|
|
212
|
+
($response.model | type == "string" and length > 0) and
|
|
213
|
+
($response.usage.input_tokens | tokens) and ($response.usage.output_tokens | tokens) and
|
|
214
|
+
($answers | type == "object") and
|
|
215
|
+
(($questions | keys) == ($answers | keys)) and
|
|
216
|
+
all($questions | to_entries[];
|
|
217
|
+
. as $q | $answers[$q.key] as $a |
|
|
218
|
+
$a.type == $q.value.type and
|
|
219
|
+
if $a.type == "noul" then ($a.noul | probability)
|
|
220
|
+
elif $a.type == "choice" then
|
|
221
|
+
($a.confidence | probability) and
|
|
222
|
+
($a.probabilities | distribution($q.value.criteria | keys)) and
|
|
223
|
+
($q.value.criteria | has($a.choice))
|
|
224
|
+
elif $a.type == "score" then
|
|
225
|
+
[range($q.value.criteria | length) | tostring] as $levels |
|
|
226
|
+
($a.confidence | probability) and ($a.score | type == "number") and
|
|
227
|
+
$a.score >= 0 and $a.score <= ($q.value.criteria | length) - 1 and
|
|
228
|
+
($a.legend | type == "object" and keys == ($levels | sort)) and
|
|
229
|
+
($a.probabilities | distribution($levels))
|
|
230
|
+
else false end))
|
|
231
|
+
' >/dev/null 2>&1 || die "invalid response: expected a typed answer for every question"
|
|
232
|
+
|
|
233
|
+
if [[ "$RAW" == true ]]; then
|
|
234
|
+
printf '%s\n' "$out" | jq '.'
|
|
235
|
+
else
|
|
236
|
+
printf '%s\n' "$out" | jq -c '.answers'
|
|
237
|
+
fi
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
# ── noul ────────────────────────────────────────────────────
|
|
241
|
+
cmd_noul() {
|
|
242
|
+
local true_desc="" false_desc="" consumed
|
|
243
|
+
|
|
244
|
+
while [[ $# -gt 0 ]]; do
|
|
245
|
+
consumed=0
|
|
246
|
+
parse_shared "$@" || consumed=$?
|
|
247
|
+
if [[ "$consumed" -gt 0 ]]; then shift "$consumed"; continue; fi
|
|
248
|
+
case "$1" in
|
|
249
|
+
--true) [[ $# -ge 2 ]] || die "--true needs a value"
|
|
250
|
+
true_desc="$2"; shift 2;;
|
|
251
|
+
--false) [[ $# -ge 2 ]] || die "--false needs a value"
|
|
252
|
+
false_desc="$2"; shift 2;;
|
|
253
|
+
-*) die "unknown option: $1";;
|
|
254
|
+
*) [[ -z "$INSTRUCTIONS" ]] || die "unexpected argument: $1"
|
|
255
|
+
INSTRUCTIONS="$1"; shift;;
|
|
256
|
+
esac
|
|
257
|
+
done
|
|
258
|
+
|
|
259
|
+
require_instructions
|
|
260
|
+
require_state
|
|
261
|
+
|
|
262
|
+
# criteria carries only the side(s) actually described, and is omitted
|
|
263
|
+
# entirely when neither was.
|
|
264
|
+
local question
|
|
265
|
+
question=$(jq -nc \
|
|
266
|
+
--arg id "$QID" \
|
|
267
|
+
--arg instructions "$INSTRUCTIONS" \
|
|
268
|
+
--arg t "$true_desc" \
|
|
269
|
+
--arg f "$false_desc" \
|
|
270
|
+
'((if $t == "" then {} else {"true": $t} end)
|
|
271
|
+
+ (if $f == "" then {} else {"false": $f} end)) as $criteria
|
|
272
|
+
| {($id): ({type: "noul", instructions: $instructions}
|
|
273
|
+
+ (if ($criteria | length) > 0 then {criteria: $criteria} else {} end))}')
|
|
274
|
+
evaluate "$question"
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
# ── choice ──────────────────────────────────────────────────
|
|
278
|
+
cmd_choice() {
|
|
279
|
+
local criteria='{}' consumed key desc
|
|
280
|
+
|
|
281
|
+
while [[ $# -gt 0 ]]; do
|
|
282
|
+
consumed=0
|
|
283
|
+
parse_shared "$@" || consumed=$?
|
|
284
|
+
if [[ "$consumed" -gt 0 ]]; then shift "$consumed"; continue; fi
|
|
285
|
+
case "$1" in
|
|
286
|
+
-o|--option)
|
|
287
|
+
[[ $# -ge 2 ]] || die "--option needs a value"
|
|
288
|
+
key="${2%%=*}"
|
|
289
|
+
[[ -n "$key" ]] || die "--option needs a KEY (KEY=DESCRIPTION)"
|
|
290
|
+
# A bare KEY sends null — the API's documented "no extra detail" form.
|
|
291
|
+
# A repeated KEY keeps its original position and takes the last value.
|
|
292
|
+
if [[ "$2" == *=* ]]; then
|
|
293
|
+
desc="${2#*=}"
|
|
294
|
+
criteria=$(jq -c --arg k "$key" --arg d "$desc" '. + {($k): $d}' <<<"$criteria")
|
|
295
|
+
else
|
|
296
|
+
criteria=$(jq -c --arg k "$key" '. + {($k): null}' <<<"$criteria")
|
|
297
|
+
fi
|
|
298
|
+
shift 2;;
|
|
299
|
+
-*) die "unknown option: $1";;
|
|
300
|
+
*) [[ -z "$INSTRUCTIONS" ]] || die "unexpected argument: $1"
|
|
301
|
+
INSTRUCTIONS="$1"; shift;;
|
|
302
|
+
esac
|
|
303
|
+
done
|
|
304
|
+
|
|
305
|
+
require_instructions
|
|
306
|
+
require_state
|
|
307
|
+
[[ "$(jq 'length' <<<"$criteria")" -ge 2 ]] || die "choice needs at least 2 options"
|
|
308
|
+
# The API accepts up to 255 options per Choice.
|
|
309
|
+
[[ "$(jq 'length' <<<"$criteria")" -le 255 ]] || die "choice accepts at most 255 options"
|
|
310
|
+
|
|
311
|
+
local question
|
|
312
|
+
question=$(jq -nc \
|
|
313
|
+
--arg id "$QID" \
|
|
314
|
+
--arg instructions "$INSTRUCTIONS" \
|
|
315
|
+
--argjson criteria "$criteria" \
|
|
316
|
+
'{($id): {type: "choice", instructions: $instructions, criteria: $criteria}}')
|
|
317
|
+
evaluate "$question"
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
# ── score ───────────────────────────────────────────────────
|
|
321
|
+
cmd_score() {
|
|
322
|
+
local levels='[]' consumed
|
|
323
|
+
|
|
324
|
+
while [[ $# -gt 0 ]]; do
|
|
325
|
+
consumed=0
|
|
326
|
+
parse_shared "$@" || consumed=$?
|
|
327
|
+
if [[ "$consumed" -gt 0 ]]; then shift "$consumed"; continue; fi
|
|
328
|
+
case "$1" in
|
|
329
|
+
-l|--level)
|
|
330
|
+
[[ $# -ge 2 ]] || die "--level needs a value"
|
|
331
|
+
# Order is the rubric: levels stay in the order they were given.
|
|
332
|
+
levels=$(jq -c --arg l "$2" '. + [$l]' <<<"$levels")
|
|
333
|
+
shift 2;;
|
|
334
|
+
-*) die "unknown option: $1";;
|
|
335
|
+
*) [[ -z "$INSTRUCTIONS" ]] || die "unexpected argument: $1"
|
|
336
|
+
INSTRUCTIONS="$1"; shift;;
|
|
337
|
+
esac
|
|
338
|
+
done
|
|
339
|
+
|
|
340
|
+
require_instructions
|
|
341
|
+
require_state
|
|
342
|
+
[[ "$(jq 'length' <<<"$levels")" -ge 2 ]] || die "score needs at least 2 levels"
|
|
343
|
+
# The API accepts up to 10 levels per Score.
|
|
344
|
+
[[ "$(jq 'length' <<<"$levels")" -le 10 ]] || die "score accepts at most 10 levels"
|
|
345
|
+
|
|
346
|
+
local question
|
|
347
|
+
question=$(jq -nc \
|
|
348
|
+
--arg id "$QID" \
|
|
349
|
+
--arg instructions "$INSTRUCTIONS" \
|
|
350
|
+
--argjson levels "$levels" \
|
|
351
|
+
'{($id): {type: "score", instructions: $instructions, criteria: $levels}}')
|
|
352
|
+
evaluate "$question"
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
# ── ask ─────────────────────────────────────────────────────
|
|
356
|
+
# Many typed questions against one state, in a single request. Jev ingests the
|
|
357
|
+
# state once and answers every question in parallel, so this is the cheap way
|
|
358
|
+
# to ask several things — including speculative ones the caller may discard.
|
|
359
|
+
cmd_ask() {
|
|
360
|
+
local src="" consumed text questions
|
|
361
|
+
|
|
362
|
+
while [[ $# -gt 0 ]]; do
|
|
363
|
+
# ask answers under the ids in the payload, so --id would name nothing.
|
|
364
|
+
[[ "$1" == "--id" ]] && die "ask takes its question ids from the payload; --id does not apply"
|
|
365
|
+
consumed=0
|
|
366
|
+
parse_shared "$@" || consumed=$?
|
|
367
|
+
if [[ "$consumed" -gt 0 ]]; then shift "$consumed"; continue; fi
|
|
368
|
+
case "$1" in
|
|
369
|
+
# A lone dash is the stdin source, not an option.
|
|
370
|
+
-) [[ -z "$src" ]] || die "unexpected argument: -"
|
|
371
|
+
src="-"; claim_stdin; shift;;
|
|
372
|
+
-*) die "unknown option: $1";;
|
|
373
|
+
*) [[ -z "$src" ]] || die "unexpected argument: $1"
|
|
374
|
+
src="$1"; shift;;
|
|
375
|
+
esac
|
|
376
|
+
done
|
|
377
|
+
|
|
378
|
+
[[ -n "$src" ]] || usage
|
|
379
|
+
require_state
|
|
380
|
+
|
|
381
|
+
if [[ "$src" == "-" ]]; then
|
|
382
|
+
text="$(cat)"
|
|
383
|
+
else
|
|
384
|
+
[[ -r "$src" ]] || die "cannot read $src"
|
|
385
|
+
text="$(cat "$src")"
|
|
386
|
+
fi
|
|
387
|
+
|
|
388
|
+
questions="$(printf '%s' "$text" | jq -sc 'if length == 1 then .[0] else error("expected one questions object") end' 2>/dev/null)" || die "invalid JSON in $src"
|
|
389
|
+
[[ "$(jq -r 'type' <<<"$questions")" == "object" ]] || die "questions must be a JSON object"
|
|
390
|
+
[[ "$(jq 'length' <<<"$questions")" -ge 1 ]] || die "questions must not be empty"
|
|
391
|
+
|
|
392
|
+
evaluate "$questions"
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
# ── dispatch ────────────────────────────────────────────────
|
|
396
|
+
[[ $# -gt 0 ]] || usage
|
|
397
|
+
command="$1"; shift
|
|
398
|
+
case "$command" in
|
|
399
|
+
noul) cmd_noul "$@";;
|
|
400
|
+
choice) cmd_choice "$@";;
|
|
401
|
+
score) cmd_score "$@";;
|
|
402
|
+
ask) cmd_ask "$@";;
|
|
403
|
+
-h|--help|help) usage;;
|
|
404
|
+
*) echo "jev: unknown command: $command" >&2; usage;;
|
|
405
|
+
esac
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jira",
|
|
3
|
+
"version": "6.8.0",
|
|
4
|
+
"description": "Jira issue search and workflow from the session via a REST wrapper (skill + bash). Cloud + Server/DC, read and safe writes. Standalone, no dependencies.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Falconiere Barbosa",
|
|
7
|
+
"email": "hello@falconiere.io"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/falconiere/toolu",
|
|
10
|
+
"repository": "https://github.com/falconiere/toolu.git",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"claude-code",
|
|
14
|
+
"jira",
|
|
15
|
+
"atlassian",
|
|
16
|
+
"skills"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jira",
|
|
3
|
+
"version": "6.8.0",
|
|
4
|
+
"description": "Jira issue search and workflow from the session via a REST wrapper (skill + bash). Cloud + Server/DC, read and safe writes. Standalone, no dependencies.",
|
|
5
|
+
"skills": "./skills/",
|
|
6
|
+
"hooks": "./hooks/hooks.json"
|
|
7
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# jira
|
|
2
|
+
|
|
3
|
+
Jira issue search and workflow from the session via a REST wrapper — a skill plus bash. Cloud + Server/DC, read and safe writes.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/plugin install jira@toolu
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Standalone, no dependencies.
|
|
12
|
+
|
|
13
|
+
## What it provides
|
|
14
|
+
|
|
15
|
+
- **`jira` skill** — work a ticket without leaving the session: JQL search, read/create/comment/transition/assign issues, plus boards, sprints, worklogs, projects, users, and attachments, with a `raw` verb for any endpoint. Triggers on Jira mentions, JQL, issue keys like `ABC-123`, a pasted `*.atlassian.net/browse/...` link, "create a task at Jira", "my tickets", and create/comment/transition/assign requests. **Prefer this skill over the Atlassian MCP** — it reuses your existing Jira auth and stays in-session. If you also run the toolu plugin, its `UserPromptSubmit` hook nudges the same way when a prompt mentions Jira.
|
|
16
|
+
- **`plan` family** — decomposes non-trivial ticket work into small, individually verifiable steps and tracks them in a ledger.
|
|
17
|
+
|
|
18
|
+
## Plans
|
|
19
|
+
|
|
20
|
+
Read-only lookups run directly. Anything that **mutates** a ticket, or needs two or more calls, is planned first:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
jira.sh plan init ABC-123 # scaffold the host-native Jira plan path
|
|
24
|
+
jira.sh plan run <DOC> [--step <id>] # run each step's check, update the ledger
|
|
25
|
+
jira.sh plan status ABC-123 # summary
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Each step carries a `check` — a shell command that exits 0 **only when Jira itself reflects the change** (`"$JIRA" issue get ABC-123 --lean | jq -e '.status=="Done"'`). A step is green because Jira agrees, not because the agent said so. `plan run` probes Jira once before running anything, so an auth or network failure aborts instead of marking every step red.
|
|
29
|
+
|
|
30
|
+
The ledger is written to `<repo>/.claude/tmp/plan-ledger/jira-<KEY>.json` on
|
|
31
|
+
Claude or `<repo>/.codex/tmp/plan-ledger/jira-<KEY>.json` on Codex. It is
|
|
32
|
+
deliberately **not** the branch ledger: toolu's push gate only reads
|
|
33
|
+
`<branch-slug>.json`, so a pending Jira step can never block `git push`.
|
|
34
|
+
|
|
35
|
+
## The Jira API
|
|
36
|
+
|
|
37
|
+
The skill drives `scripts/jira.sh`, a bash wrapper over the Jira REST API (Cloud and Server/Data Center).
|
|
38
|
+
|
|
39
|
+
- **Easiest** — if the [`jira` CLI](https://github.com/ankitpokhrel/jira-cli) is configured (`jira init`), the plugin reuses its login automatically (server + login from `~/.config/.jira/.config.yml`, token from the OS keyring). No extra setup.
|
|
40
|
+
- **Or set environment variables** (these always take precedence; never a `.env` file): `JIRA_BASE_URL` (required), then either `JIRA_PAT` (Bearer) or `JIRA_EMAIL` + `JIRA_API_TOKEN` (basic). Set `JIRA_API_VERSION=2` for Server/Data Center.
|
|
41
|
+
|
|
42
|
+
When nothing is configured the plugin prints a short, friendly setup prompt and exits.
|