Skip to content

feat(mcp): cache last-good decision packs#266

Merged
JSONbored merged 2 commits into
JSONbored:mainfrom
MkDev11:codex/mcp-decision-pack-cache
Jun 2, 2026
Merged

feat(mcp): cache last-good decision packs#266
JSONbored merged 2 commits into
JSONbored:mainfrom
MkDev11:codex/mcp-decision-pack-cache

Conversation

@MkDev11
Copy link
Copy Markdown
Contributor

@MkDev11 MkDev11 commented Jun 2, 2026

Summary

  • Cache successful MCP decision-pack responses as bounded local last-good snapshots.
  • Return explicitly stale local fallback guidance for temporary API/network failures.
  • Add cache status/clear CLI commands, diagnostics, docs, and MCP CLI regression coverage.

Closes #100.

Scope

  • This PR is focused and does not mix unrelated backend, UI, MCP, docs, dependency, and deploy changes.
  • This follows CONTRIBUTING.md and does not reintroduce GitHub Pages, VitePress, site/, or CNAME.
  • I linked an issue, or this is small enough that the summary explains why an issue is not needed.

Validation

  • git diff --check
  • npm run actionlint
  • npm run typecheck
  • npm run test:coverage locally; global coverage stays at or above 97% for lines, statements, functions, and branches (aim for 98%+ branch coverage locally so CI variance does not fail near the threshold)
  • npm run test:workers
  • npm run build:mcp
  • npm run test:mcp-pack
  • npm run ui:openapi:check
  • npm run ui:lint
  • npm run ui:typecheck
  • npm run ui:build
  • npm audit --audit-level=moderate
  • New or changed behavior has unit/integration tests for new branches, fallback paths, and sanitizer boundaries

If any required check was skipped, explain why:

  • None. npm run test:ci passed locally.

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • Public GitHub text stays sanitized, low-noise, and does not imply compensation guarantees or optimization tactics.
  • Auth, cookie, CORS, GitHub App, Cloudflare, or session changes include negative-path tests.
  • API/OpenAPI/MCP behavior is updated and tested where needed.
  • UI changes use live API data or real empty/error/loading states, not production mock/demo fallbacks.
  • Visible UI changes include screenshots or a short recording.
  • Public docs/changelogs are updated where needed; changelogs are only edited for release-prep PRs.

Notes

  • MCP stale fallback is only used for transient API/network failures, HTTP 429, or 5xx responses. Missing local credentials and HTTP auth/permission failures do not return stale private cache data.
  • Cache entries are keyed by API version/login/API origin, bounded, schema-checked, and sanitized to exclude source contents, local paths, and sensitive key/token-like fields.
  • npm run test:ci passed with coverage summary: statements 98.99%, branches 97.02%, functions 98.18%, lines 99.59%.
  • No visible UI changes; screenshot/recording is not applicable.

@MkDev11 MkDev11 requested a review from JSONbored as a code owner June 2, 2026 08:09
@dosubot dosubot Bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Jun 2, 2026
@dosubot
Copy link
Copy Markdown

dosubot Bot commented Jun 2, 2026

Documentation Updates

1 document(s) were updated by changes in this PR:

MCP & Agent Integration
View Changes
@@ -17,7 +17,7 @@
 The package exposes two surfaces for different audiences:
 
 - **21 MCP tools** — structured tool definitions callable by AI agents via the MCP protocol, covering repo intelligence, PR preflight, scoring, contributor decisions, current-branch analysis, and agent planning [[5]](https://app.dosu.dev/7d8810aa-91c6-4074-849b-92fab65de734/documents/09d20768-c6a2-4ac0-9000-4395a9728dc9#L92-L98)
-- **13 CLI commands** — human-friendly equivalents of the same capabilities, usable directly from a terminal or CI script
+- **17 CLI commands** — human-friendly equivalents of the same capabilities, usable directly from a terminal or CI script
 
 It is designed for three audiences:
 
@@ -85,6 +85,7 @@
 # API: https://gittensory-api.aethereal.dev
 # API health: ok
 # Auth: authenticated (jsonbored)
+# Decision-pack cache: 3 entries
 # Source upload: disabled
 ```
 
@@ -98,6 +99,7 @@
 # - pass: api_compatibility - Local 0.4.0 meets the API minimum 0.4.0.
 # - pass: auth - Authenticated as jsonbored; session expires 2026-08-01T00:00:00.000Z.
 # - pass: source_upload - Source upload is disabled and unsupported in v1.
+# - pass: decision_pack_cache - Local stale fallback cache has 3 entries and is bounded at 25.
 # - pass: git_metadata - owner/repo on feature-branch; 4 changed file(s).
 # - pass: client_path - gittensory-mcp is visible on PATH.
 # - warn: local_scorer - GITTENSOR_SCORE_PREVIEW_CMD is not configured; ...
@@ -239,8 +241,8 @@
 
 | Tool | Description |
 |------|-------------|
-| `gittensory_get_decision_pack` | Returns the canonical private contributor decision pack for a GitHub login — contributor history, patterns, queue pressure, lane fit, credibility estimates, and maintainer friction signals [[25]](https://github.com/JSONbored/gittensory/blob/1e7506f4c5226d0b9b5da8fcd219309d84bacfcd/packages/gittensory-mcp/bin/gittensory-mcp.js#L221-L228) |
-| `gittensory_explain_repo_decision` | Returns the contributor/repo decision entry from the decision pack, scoped to a specific `owner/repo`. Explains whether the contributor should focus effort on this repo and why [[26]](https://github.com/JSONbored/gittensory/blob/1e7506f4c5226d0b9b5da8fcd219309d84bacfcd/packages/gittensory-mcp/bin/gittensory-mcp.js#L230-L241) |
+| `gittensory_get_decision_pack` | Returns the canonical private contributor decision pack for a GitHub login — contributor history, patterns, queue pressure, lane fit, credibility estimates, and maintainer friction signals. If API is temporarily unavailable, returns cached guidance with `source: "local_cache"` and `stale: true` [[25]](https://github.com/JSONbored/gittensory/blob/1e7506f4c5226d0b9b5da8fcd219309d84bacfcd/packages/gittensory-mcp/bin/gittensory-mcp.js#L221-L228) |
+| `gittensory_explain_repo_decision` | Returns the contributor/repo decision entry from the decision pack, scoped to a specific `owner/repo`. Explains whether the contributor should focus effort on this repo and why. Supports offline stale fallback when API is unreachable [[26]](https://github.com/JSONbored/gittensory/blob/1e7506f4c5226d0b9b5da8fcd219309d84bacfcd/packages/gittensory-mcp/bin/gittensory-mcp.js#L230-L241) |
 
 Decision packs are rebuilt every 6 hours and returned immediately (with a `freshness: "rebuilding"` flag if stale), ensuring agents always receive actionable context [[27]](https://app.dosu.dev/7d8810aa-91c6-4074-849b-92fab65de734/documents/09d20768-c6a2-4ac0-9000-4395a9728dc9#L258-L283).
 
@@ -584,7 +586,7 @@
 
 ### CLI Commands
 
-The package provides 13 CLI commands for human-friendly access to all capabilities. All commands support `--json` for structured output [[52]](https://github.com/JSONbored/gittensory/blob/1e7506f4c5226d0b9b5da8fcd219309d84bacfcd/packages/gittensory-mcp/bin/gittensory-mcp.js#L637-L676).
+The package provides 17 CLI commands for human-friendly access to all capabilities. All commands support `--json` for structured output [[52]](https://github.com/JSONbored/gittensory/blob/1e7506f4c5226d0b9b5da8fcd219309d84bacfcd/packages/gittensory-mcp/bin/gittensory-mcp.js#L637-L676).
 
 #### Authentication & Diagnostics
 
@@ -593,11 +595,20 @@
 | `gittensory-mcp login [--profile <name>] [--github-token <token>]` | Authenticate via GitHub Device Flow (or a static token). Stores a Gittensory session in `~/.config/gittensory/config.json` |
 | `gittensory-mcp logout [--profile <name>] [--all]` | Revoke the remote session and delete the local config. `--all` clears all profiles |
 | `gittensory-mcp whoami [--profile <name>]` | Print the authenticated GitHub login |
-| `gittensory-mcp status [--profile <name>]` | Report package version, npm latest, API health, auth state, and source-upload posture |
-| `gittensory-mcp doctor [--profile <name>] [--cwd path]` | Run the full diagnostic suite (API health, compatibility, auth, PATH, local scorer) |
+| `gittensory-mcp status [--profile <name>]` | Report package version, npm latest, API health, auth state, decision-pack cache status, and source-upload posture |
+| `gittensory-mcp doctor [--profile <name>] [--cwd path]` | Run the full diagnostic suite (API health, compatibility, auth, decision-pack cache, PATH, local scorer) |
 | `gittensory-mcp profile <list\|create\|switch\|remove>` | Manage named profiles for multi-account session isolation. Use `list` to show all profiles, `create <name>` to initialize a new profile, `switch <name>` to set the active profile, or `remove <name>` to delete a profile |
 | `gittensory-mcp changelog` | Print the local `CHANGELOG.md` |
 | `gittensory-mcp init-client --print codex\|claude\|cursor\|mcp` | Print a ready-to-paste MCP client config snippet |
+| `gittensory-mcp cache status [--json]` | Display decision-pack cache status |
+| `gittensory-mcp cache clear [--json]` | Clear cached decision-pack data |
+
+#### Decision-Pack Commands
+
+| Command | Purpose |
+|---------|---------|
+| `gittensory-mcp decision-pack --login <login> [--json]` | Fetch decision pack for a login (standalone command) |
+| `gittensory-mcp repo-decision --login <login> --repo owner/repo [--json]` | Get repo-specific decision (standalone command) |
 
 #### Branch Analysis
 
@@ -680,14 +691,14 @@
 
 - **Purpose:** Return the canonical private contributor decision pack for a GitHub login
 - **Input:** `{ login: string }`
-- **Output:** Full decision pack with contributor history, queue health, lane recommendations, credibility, per-repo decisions, and freshness metadata
+- **Output:** Full decision pack with contributor history, queue health, lane recommendations, credibility, per-repo decisions, and freshness metadata. If API is temporarily unavailable, returns cached guidance with `source: "local_cache"`, `stale: true`, `cachedAt` timestamp, and rerun guidance
 - **Use case:** Understand a contributor's full context before planning next work [[25]](https://github.com/JSONbored/gittensory/blob/1e7506f4c5226d0b9b5da8fcd219309d84bacfcd/packages/gittensory-mcp/bin/gittensory-mcp.js#L221-L228)
 
 **`gittensory_explain_repo_decision`**
 
 - **Purpose:** Return the contributor/repo decision from the decision pack, scoped to one repo
 - **Input:** `{ login: string, owner: string, repo: string }`
-- **Output:** Repo-scoped decision — whether to contribute, lane fit, friction signals
+- **Output:** Repo-scoped decision — whether to contribute, lane fit, friction signals. Supports offline stale fallback when API is unreachable
 - **Use case:** Get a focused recommendation for one specific repo [[26]](https://github.com/JSONbored/gittensory/blob/1e7506f4c5226d0b9b5da8fcd219309d84bacfcd/packages/gittensory-mcp/bin/gittensory-mcp.js#L230-L241)
 
 #### Category 4: Current Branch Analysis
@@ -823,3 +834,15 @@
 5. Leaves the actual PR creation to the human or to an explicitly authorized automation step
 
 The intelligence layer informs the decision. The decision itself belongs to the agent or the human.
+
+## Offline Decision-Pack Fallback
+
+Successful `decision-pack` and MCP `gittensory_get_decision_pack` calls store a bounded last-good local cache entry keyed by API version and login. When the API or network is temporarily unavailable, the system returns cached guidance with `source: "local_cache"`, `stale: true`, `cachedAt` timestamp, and rerun guidance.
+
+Auth and permission failures do not use stale fallback data. The cache excludes source contents and local paths, is bounded at 25 entries, and can be cleared with:
+
+```sh
+gittensory-mcp cache clear
+```
+
+Run `gittensory-mcp cache status` to inspect cache entries, or check the `decisionPackCache` field in `gittensory-mcp status` output. The `gittensory-mcp doctor` command includes decision-pack cache diagnostics in its report.

How did I do? Any feedback?  Join Discord

@JSONbored JSONbored added the feature New feature or request label Jun 2, 2026
Copy link
Copy Markdown
Owner

@JSONbored JSONbored left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MkDev11 this is ready from my pass.

A few notes:

  • The last-good decision-pack cache is useful, and the fallback semantics are appropriately conservative.
  • I like that stale output is clearly marked with source: "local_cache", stale: true, cachedAt, and rerun guidance.
  • The important safety boundary is covered: auth and permission failures do not return cached private data.
  • cache status, cache clear, status, and doctor integration make the behavior discoverable without adding hidden state.
  • I do not have code changes to request.

Validation expected:

  • Keep npm run test:ci/validate green on the final head.

@dosubot dosubot Bot added the lgtm This PR has been approved by a maintainer label Jun 2, 2026
@JSONbored JSONbored merged commit bf45d0c into JSONbored:main Jun 2, 2026
4 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in gittensory - v1 roadmap Jun 2, 2026
@github-actions github-actions Bot mentioned this pull request Jun 2, 2026
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request lgtm This PR has been approved by a maintainer size:S This PR changes 10-29 lines, ignoring generated files.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

feat(mcp): cache last-good decision packs for offline fallback

2 participants