mossbear 0.1.0-alpha.28 → 0.1.0-alpha.30
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/README.md +30 -10
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +61 -72
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/guides/history.d.ts +72 -0
- package/dist/commands/guides/history.d.ts.map +1 -0
- package/dist/commands/guides/history.js +217 -0
- package/dist/commands/guides/history.js.map +1 -0
- package/dist/commands/guides/index.d.ts.map +1 -1
- package/dist/commands/guides/index.js +4 -0
- package/dist/commands/guides/index.js.map +1 -1
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +138 -68
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/link.d.ts +142 -0
- package/dist/commands/link.d.ts.map +1 -0
- package/dist/commands/link.js +272 -0
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +6 -4
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/pull.d.ts +22 -0
- package/dist/commands/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +190 -75
- package/dist/commands/pull.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +96 -23
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +148 -97
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/unlink.d.ts +118 -0
- package/dist/commands/unlink.d.ts.map +1 -0
- package/dist/commands/unlink.js +271 -0
- package/dist/commands/unlink.js.map +1 -0
- package/dist/commit-anchor.d.ts +25 -0
- package/dist/commit-anchor.d.ts.map +1 -0
- package/dist/commit-anchor.js +93 -0
- package/dist/commit-anchor.js.map +1 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +19 -36
- package/dist/config.js.map +1 -1
- package/dist/context/materialize.d.ts +200 -0
- package/dist/context/materialize.d.ts.map +1 -0
- package/dist/context/materialize.js +145 -0
- package/dist/context/materialize.js.map +1 -0
- package/dist/context/pull.d.ts +41 -48
- package/dist/context/pull.d.ts.map +1 -1
- package/dist/context/pull.js +36 -287
- package/dist/context/pull.js.map +1 -1
- package/dist/docs/bundle-by-name.d.ts +47 -0
- package/dist/docs/bundle-by-name.d.ts.map +1 -0
- package/dist/docs/bundle-by-name.js +56 -0
- package/dist/docs/bundle-by-name.js.map +1 -0
- package/dist/docs/classify.d.ts +1 -1
- package/dist/docs/classify.d.ts.map +1 -1
- package/dist/docs/classify.js +2 -2
- package/dist/docs/classify.js.map +1 -1
- package/dist/docs/delivery-check.d.ts +25 -7
- package/dist/docs/delivery-check.d.ts.map +1 -1
- package/dist/docs/delivery-check.js +32 -11
- package/dist/docs/delivery-check.js.map +1 -1
- package/dist/docs/delivery.d.ts +105 -0
- package/dist/docs/delivery.d.ts.map +1 -0
- package/dist/docs/delivery.js +128 -0
- package/dist/docs/delivery.js.map +1 -0
- package/dist/docs/guide-projection.d.ts +32 -0
- package/dist/docs/guide-projection.d.ts.map +1 -1
- package/dist/docs/guide-projection.js +55 -27
- package/dist/docs/guide-projection.js.map +1 -1
- package/dist/docs/relink-mapping.d.ts.map +1 -1
- package/dist/docs/relink-mapping.js +2 -3
- package/dist/docs/relink-mapping.js.map +1 -1
- package/dist/docs/repo-config.d.ts +0 -6
- package/dist/docs/repo-config.d.ts.map +1 -1
- package/dist/docs/repo-config.js +7 -37
- package/dist/docs/repo-config.js.map +1 -1
- package/dist/docs/sidecar.d.ts.map +1 -1
- package/dist/docs/sidecar.js +11 -3
- package/dist/docs/sidecar.js.map +1 -1
- package/dist/docs/status.d.ts +130 -14
- package/dist/docs/status.d.ts.map +1 -1
- package/dist/docs/status.js +160 -18
- package/dist/docs/status.js.map +1 -1
- package/dist/docs/subscribe.d.ts +44 -47
- package/dist/docs/subscribe.d.ts.map +1 -1
- package/dist/docs/subscribe.js +52 -87
- package/dist/docs/subscribe.js.map +1 -1
- package/dist/docs/sync-docs.d.ts +90 -4
- package/dist/docs/sync-docs.d.ts.map +1 -1
- package/dist/docs/sync-docs.js +508 -924
- package/dist/docs/sync-docs.js.map +1 -1
- package/dist/docs/sync-plan.d.ts +517 -0
- package/dist/docs/sync-plan.d.ts.map +1 -0
- package/dist/docs/sync-plan.js +872 -0
- package/dist/docs/sync-plan.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/client.d.ts +52 -5
- package/dist/mcp/client.d.ts.map +1 -1
- package/dist/mcp/client.js +69 -18
- package/dist/mcp/client.js.map +1 -1
- package/dist/mcp/import-tool.d.ts +19 -7
- package/dist/mcp/import-tool.d.ts.map +1 -1
- package/dist/mcp/import-tool.js +5 -5
- package/dist/mcp/import-tool.js.map +1 -1
- package/dist/mcp/scope.d.ts +35 -2
- package/dist/mcp/scope.d.ts.map +1 -1
- package/dist/mcp/scope.js +34 -2
- package/dist/mcp/scope.js.map +1 -1
- package/dist/mcp/server.d.ts +29 -12
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +376 -65
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/write-items.d.ts +73 -14
- package/dist/mcp/write-items.d.ts.map +1 -1
- package/dist/mcp/write-items.js +90 -22
- package/dist/mcp/write-items.js.map +1 -1
- package/dist/project-hooks.d.ts +60 -0
- package/dist/project-hooks.d.ts.map +1 -0
- package/dist/project-hooks.js +93 -0
- package/dist/project-hooks.js.map +1 -0
- package/dist/rules/guide-history-client.d.ts +70 -0
- package/dist/rules/guide-history-client.d.ts.map +1 -0
- package/dist/rules/guide-history-client.js +121 -0
- package/dist/rules/guide-history-client.js.map +1 -0
- package/dist/rules/import-client.d.ts +1 -1
- package/dist/rules/import-paths.js +2 -2
- package/dist/rules/import-paths.js.map +1 -1
- package/dist/rules/repo-identity.d.ts +45 -0
- package/dist/rules/repo-identity.d.ts.map +1 -0
- package/dist/rules/repo-identity.js +59 -0
- package/dist/rules/repo-identity.js.map +1 -0
- package/dist/rules/unlink-client.d.ts +39 -0
- package/dist/rules/unlink-client.d.ts.map +1 -0
- package/dist/rules/unlink-client.js +86 -0
- package/dist/rules/unlink-client.js.map +1 -0
- package/dist/run-self-report.d.ts +68 -0
- package/dist/run-self-report.d.ts.map +1 -0
- package/dist/run-self-report.js +49 -0
- package/dist/run-self-report.js.map +1 -0
- package/dist/skill-template.d.ts +3 -3
- package/dist/skill-template.d.ts.map +1 -1
- package/dist/skill-template.js +59 -28
- package/dist/skill-template.js.map +1 -1
- package/dist/soft-json.d.ts +34 -0
- package/dist/soft-json.d.ts.map +1 -0
- package/dist/soft-json.js +44 -0
- package/dist/soft-json.js.map +1 -0
- package/dist/state/machine-cache.d.ts +34 -0
- package/dist/state/machine-cache.d.ts.map +1 -1
- package/dist/state/machine-cache.js +37 -0
- package/dist/state/machine-cache.js.map +1 -1
- package/dist/sync-batches.d.ts +22 -1
- package/dist/sync-batches.d.ts.map +1 -1
- package/dist/sync-batches.js +17 -0
- package/dist/sync-batches.js.map +1 -1
- package/dist/sync-client.d.ts.map +1 -1
- package/dist/sync-client.js +25 -1
- package/dist/sync-client.js.map +1 -1
- package/dist/transcript/narration.d.ts +46 -0
- package/dist/transcript/narration.d.ts.map +1 -1
- package/dist/transcript/narration.js +69 -4
- package/dist/transcript/narration.js.map +1 -1
- package/dist/update/assets.d.ts.map +1 -1
- package/dist/update/assets.js +7 -57
- package/dist/update/assets.js.map +1 -1
- package/package.json +12 -14
- package/dist/commands/import.d.ts +0 -57
- package/dist/commands/import.d.ts.map +0 -1
- package/dist/commands/import.js +0 -217
- package/dist/commands/import.js.map +0 -1
- package/dist/docs/enroll-default-bundle.d.ts +0 -71
- package/dist/docs/enroll-default-bundle.d.ts.map +0 -1
- package/dist/docs/enroll-default-bundle.js +0 -111
- package/dist/docs/enroll-default-bundle.js.map +0 -1
- package/dist/docs/own-bundle.d.ts +0 -76
- package/dist/docs/own-bundle.d.ts.map +0 -1
- package/dist/docs/own-bundle.js +0 -96
- package/dist/docs/own-bundle.js.map +0 -1
- package/dist/docs/resolve-subscriptions.d.ts +0 -67
- package/dist/docs/resolve-subscriptions.d.ts.map +0 -1
- package/dist/docs/resolve-subscriptions.js +0 -67
- package/dist/docs/resolve-subscriptions.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# mossbear
|
|
2
2
|
|
|
3
|
-
Local-first CLI for [Mossbear](https://app.mossbear.io) — a feedback layer for AI coding agents. Mossbear grades what your agents actually did against
|
|
3
|
+
Local-first CLI for [Mossbear](https://app.mossbear.io) — a feedback layer for AI coding agents. Mossbear grades what your agents actually did against your guides — the rules, skills and documents you wrote (`AGENTS.md`, `CLAUDE.md`, `.cursorrules`, …) — and shows you which ones work.
|
|
4
4
|
|
|
5
|
-
The CLI is the on-device half of the product: it hooks into your agent's lifecycle, records what each tool call did, and syncs
|
|
5
|
+
The CLI is the on-device half of the product: it hooks into your agent's lifecycle, records what each tool call did, and syncs that record to your dashboard, which grades the run against your rules and skills. Your file contents, your diffs and your raw conversation transcripts never leave your machine — [Privacy](#privacy) lists exactly what does.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -68,7 +68,8 @@ mossbear sync --token <token> # remembered after the first successful sync
|
|
|
68
68
|
| `mossbear sync` | Upload logged actions + extracted feedback for grading, pull the guide bundle (run by the Stop and SessionEnd hooks) |
|
|
69
69
|
| `mossbear pull <bundle>` | Pull a context bundle's canonical items into a local directory as Markdown (default `.mossbear/context/<bundle>/`) |
|
|
70
70
|
| `mossbear mcp` | Run the Mossbear MCP server, exposing your context layer (bundles + inbox) to any agent |
|
|
71
|
-
| `mossbear
|
|
71
|
+
| `mossbear link` | Adopt this repo's existing guide files (`AGENTS.md`, `.agents/`, `CLAUDE.md`, `.claude/rules/`, `.cursorrules`, `.cursor/rules/*.mdc`) into your dashboard — pick from a list, never type a path |
|
|
72
|
+
| `mossbear unlink <file>` | Stop delivering a file you linked — it stays on disk, and `mossbear link` puts it back |
|
|
72
73
|
| `mossbear guides active` / `search` | List or search your synced guides |
|
|
73
74
|
| `mossbear suggest` | Review pending guide suggestions |
|
|
74
75
|
| `mossbear status` | Show pending actions + config status |
|
|
@@ -79,16 +80,16 @@ mossbear sync --token <token> # remembered after the first successful sync
|
|
|
79
80
|
If the repo already has an `AGENTS.md`, `CLAUDE.md`, `.cursorrules`, or skills, `mossbear init` finds them and offers to import them once a token is configured (`--import-guides` / `--no-import-guides` to answer without the prompt). To do it later, or after adding a new guide file:
|
|
80
81
|
|
|
81
82
|
```bash
|
|
82
|
-
mossbear
|
|
83
|
-
mossbear
|
|
84
|
-
mossbear
|
|
83
|
+
mossbear link # pick from a list; Enter takes all of them
|
|
84
|
+
mossbear link --yes # no prompt (required when stdin is not a TTY)
|
|
85
|
+
mossbear link --global # also scan ~/.claude/CLAUDE.md
|
|
85
86
|
```
|
|
86
87
|
|
|
87
88
|
Files a context bundle already manages are **listed as managed** rather than hidden,
|
|
88
89
|
and cannot be selected — they are canonical in the dashboard, so edit them there or
|
|
89
90
|
on disk and run `mossbear sync`.
|
|
90
91
|
|
|
91
|
-
Re-run `mossbear
|
|
92
|
+
Re-run `mossbear link` after editing a guide file. There is no file watcher: a
|
|
92
93
|
watcher pushed one import per save, and because import has no update path, each save
|
|
93
94
|
filed a *new* guide row rather than updating the existing one. Continuous guide sync
|
|
94
95
|
returns via `mossbear sync` once guides have stable identity — see
|
|
@@ -98,9 +99,28 @@ It reads the dashboard URL from `~/.mossbear/config.json`, so a `--dashboard-url
|
|
|
98
99
|
|
|
99
100
|
## Privacy
|
|
100
101
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
The CLI runs no LLM calls and holds no provider credentials, and produces no verdict of its own — grading happens on the dashboard, over what you synced. There is no telemetry.
|
|
103
|
+
|
|
104
|
+
**Stays on your machine, always:** your file contents, your diffs, raw hook payloads, and full conversation transcripts.
|
|
105
|
+
|
|
106
|
+
**Sent to your dashboard.** Five classes, and nothing else:
|
|
107
|
+
|
|
108
|
+
1. **Action metadata** — tool-call types, one-line summaries, and file *paths* (never contents). Shell command text is secret-redacted and length-capped before it is recorded at all.
|
|
109
|
+
2. **Guide-file manifests** — the paths, formats and SHA-256 hashes of the instruction files that were in your agent's context, so a verdict can name which version of a guide it graded against.
|
|
110
|
+
3. **Token usage**, read out of the transcript locally.
|
|
111
|
+
4. **Content you explicitly push** — guide files you `mossbear link`, and context you capture or push through the MCP server.
|
|
112
|
+
5. **Two kinds of derived prose**: drafted guide suggestions (their text and the reasoning behind them), and a short narration of what you and the agent said, which the dashboard shows as evidence beside a verdict. Both are extracted from the transcript **on your machine**, have code blocks stripped structurally before upload, and are length-capped on the wire.
|
|
113
|
+
|
|
114
|
+
That fifth class is the one worth deciding about, because it is prose rather than metadata. Narration is per-repo and you can turn it off:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
mossbear narration # show the current setting for this repo
|
|
118
|
+
mossbear narration off # stop sending transcript excerpts from here
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Guide suggestions have no equivalent switch yet — if you do not want drafted suggestions leaving the machine, do not run `mossbear sync` in that repo.
|
|
122
|
+
|
|
123
|
+
We enumerate these rather than summarising them as "metadata" on purpose: this is a promise you can check by watching your own network traffic, and one you can check is worth more than one you cannot.
|
|
104
124
|
|
|
105
125
|
## Links
|
|
106
126
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AA8CA,eAAO,MAAM,aAAa;;;;;;;;;;;EAwPxB,CAAA"}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
1
|
import { defineCommand } from 'citty';
|
|
4
2
|
import { MOSSBEAR_TOKEN_ENV, readEnvToken, resolveDashboardUrl, resolveToken, } from '../config.js';
|
|
5
3
|
import { describeDashboardHealth } from '../dashboard-health.js';
|
|
6
4
|
import { describeGuideDelivery } from '../docs/delivery-check.js';
|
|
5
|
+
import { repoBundleIds } from '../docs/delivery.js';
|
|
7
6
|
import { collidesWithHomeConfig, readRepoDocsConfig } from '../docs/repo-config.js';
|
|
8
|
-
import { MOSSBEAR_HOOK_COMMAND, MOSSBEAR_SYNC_COMMAND,
|
|
7
|
+
import { MOSSBEAR_HOOK_COMMAND, MOSSBEAR_SYNC_COMMAND, stopHookUploadsActions, } from '../hooks-settings.js';
|
|
8
|
+
import { createContextClient } from '../mcp/client.js';
|
|
9
9
|
import { resolveOnPath } from '../path-resolve.js';
|
|
10
|
+
import { detectLoggerHook, readProjectHooks } from '../project-hooks.js';
|
|
10
11
|
import { resolveRepoRoot } from '../repo-root.js';
|
|
11
12
|
import { discoverGuideFiles } from '../rules/discover.js';
|
|
12
13
|
import { verifyDashboardToken } from '../token-verify.js';
|
|
@@ -14,55 +15,6 @@ import { detectBundledSkillDrift } from '../update/assets.js';
|
|
|
14
15
|
import { checkForUpdate, formatUpdateNotice } from '../update/notice.js';
|
|
15
16
|
import { formatUpdateSuccess, performUpdate, syncGeneratedAssets, } from '../update/perform.js';
|
|
16
17
|
import { CLI_VERSION } from '../version.js';
|
|
17
|
-
/** The project's parsed `.claude/settings.json`, or null when absent/malformed. */
|
|
18
|
-
async function readProjectSettings() {
|
|
19
|
-
const settingsPath = join(process.cwd(), '.claude', 'settings.json');
|
|
20
|
-
try {
|
|
21
|
-
const raw = await readFile(settingsPath, 'utf8');
|
|
22
|
-
return JSON.parse(raw);
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Which form of the logger hook this project's settings configure for one
|
|
30
|
-
* event, if any. Shared by `PostToolUse` (the success logger) and
|
|
31
|
-
* `PostToolUseFailure` (`hook-failure-event-registration`) — same command,
|
|
32
|
-
* same recognizer, only the settings.json key differs.
|
|
33
|
-
*/
|
|
34
|
-
function detectConfiguredHookFor(settings, event) {
|
|
35
|
-
try {
|
|
36
|
-
if (!settings)
|
|
37
|
-
return { form: 'none' };
|
|
38
|
-
const hooks = settings['hooks'];
|
|
39
|
-
const groups = hooks?.[event];
|
|
40
|
-
if (!Array.isArray(groups))
|
|
41
|
-
return { form: 'none' };
|
|
42
|
-
// Shares the recognizer with the merge so the two cannot disagree about
|
|
43
|
-
// what counts as configured — the substring match this replaced would miss
|
|
44
|
-
// the portable command and call a correctly wired repo unconfigured.
|
|
45
|
-
for (const group of groups) {
|
|
46
|
-
const groupHooks = group['hooks'];
|
|
47
|
-
if (!Array.isArray(groupHooks))
|
|
48
|
-
continue;
|
|
49
|
-
for (const hook of groupHooks) {
|
|
50
|
-
if (typeof hook === 'object' && hook !== null) {
|
|
51
|
-
if (isMossbearLoggerCommand(hook['command'])) {
|
|
52
|
-
return { form: 'portable' };
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return { form: 'none' };
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
return { form: 'none' };
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
function detectConfiguredHook(settings) {
|
|
64
|
-
return detectConfiguredHookFor(settings, 'PostToolUse');
|
|
65
|
-
}
|
|
66
18
|
/**
|
|
67
19
|
* True when this project's Stop hooks upload the session (`mossbear sync`).
|
|
68
20
|
*
|
|
@@ -73,10 +25,7 @@ function detectConfiguredHook(settings) {
|
|
|
73
25
|
* is destroyed at session end the entire record is lost with it. Doctor
|
|
74
26
|
* reporting all-clear in that state is what let it go unnoticed here.
|
|
75
27
|
*/
|
|
76
|
-
function detectUploadHook(
|
|
77
|
-
if (!settings)
|
|
78
|
-
return false;
|
|
79
|
-
const hooks = settings['hooks'];
|
|
28
|
+
function detectUploadHook(hooks) {
|
|
80
29
|
return stopHookUploadsActions(hooks?.['Stop']);
|
|
81
30
|
}
|
|
82
31
|
export const doctorCommand = defineCommand({
|
|
@@ -97,12 +46,10 @@ export const doctorCommand = defineCommand({
|
|
|
97
46
|
},
|
|
98
47
|
},
|
|
99
48
|
async run({ args }) {
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
const
|
|
103
|
-
const
|
|
104
|
-
const failureHookConfigured = failureHook.form !== 'none';
|
|
105
|
-
const uploadConfigured = detectUploadHook(settings);
|
|
49
|
+
const projectHooks = await readProjectHooks(process.cwd());
|
|
50
|
+
const hooksConfigured = detectLoggerHook(projectHooks, 'PostToolUse') !== null;
|
|
51
|
+
const failureHookConfigured = detectLoggerHook(projectHooks, 'PostToolUseFailure') !== null;
|
|
52
|
+
const uploadConfigured = detectUploadHook(projectHooks);
|
|
106
53
|
const hookBinPath = resolveOnPath(MOSSBEAR_HOOK_COMMAND);
|
|
107
54
|
// The Stop hooks invoke `mossbear`, which ships as a separate bin from
|
|
108
55
|
// `mossbear-hook` and can be missing while the other resolves.
|
|
@@ -127,8 +74,30 @@ export const doctorCommand = defineCommand({
|
|
|
127
74
|
})
|
|
128
75
|
.then((files) => ({ files, failed: false }))
|
|
129
76
|
.catch(() => ({ files: [], failed: true }));
|
|
77
|
+
// The account scope, which only the server can answer. `null` when this run
|
|
78
|
+
// has no token or the dashboard is unreachable — deliberately not zero, see
|
|
79
|
+
// `GuideDeliveryInput.userSubscriptionCount`.
|
|
80
|
+
const deliveryToken = await resolveToken().catch(() => '');
|
|
81
|
+
let userSubscriptionCount = null;
|
|
82
|
+
if (deliveryToken) {
|
|
83
|
+
try {
|
|
84
|
+
const client = createContextClient({
|
|
85
|
+
dashboardUrl: await resolveDashboardUrl(args['dashboard-url']),
|
|
86
|
+
token: deliveryToken,
|
|
87
|
+
});
|
|
88
|
+
const resolved = await client.resolveSubscriptions(repoBundleIds(repoDocs.subscriptions));
|
|
89
|
+
userSubscriptionCount = resolved.bundles.filter(({ scopes }) => scopes.includes('user')).length;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// Left null. The dashboard probe further down reports an unreachable or
|
|
93
|
+
// rejected token as its own check, so a second message here would say
|
|
94
|
+
// the same thing twice — and this check's own detail line already tells
|
|
95
|
+
// the user it could not look.
|
|
96
|
+
}
|
|
97
|
+
}
|
|
130
98
|
const delivery = describeGuideDelivery({
|
|
131
|
-
|
|
99
|
+
repoSubscriptionCount: repoDocs.subscriptions.length,
|
|
100
|
+
userSubscriptionCount,
|
|
132
101
|
guideFileCount: discovered.files.length,
|
|
133
102
|
malformedConfig: repoDocs.malformed,
|
|
134
103
|
discoveryFailed: discovered.failed,
|
|
@@ -161,10 +130,16 @@ export const doctorCommand = defineCommand({
|
|
|
161
130
|
},
|
|
162
131
|
{
|
|
163
132
|
label: 'Claude Code hooks configured',
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
133
|
+
// Configured is not the same as able to run — the same distinction the
|
|
134
|
+
// two checks below already make. Without `runnerOk` a stripped PATH
|
|
135
|
+
// rendered `✗ mossbear-hook on PATH` directly above a `✓` here, so the
|
|
136
|
+
// inert case reported as healthy.
|
|
137
|
+
ok: hooksConfigured && runnerOk,
|
|
138
|
+
detail: !hooksConfigured
|
|
139
|
+
? 'not configured — run `mossbear init` in your project'
|
|
140
|
+
: runnerOk
|
|
141
|
+
? `.claude/settings.json has PostToolUse hook (${MOSSBEAR_HOOK_COMMAND})`
|
|
142
|
+
: `${MOSSBEAR_HOOK_COMMAND} not on PATH — reinstall globally (npm install -g mossbear)`,
|
|
168
143
|
},
|
|
169
144
|
// Only meaningful once the logger is wired: with no PostToolUse hook
|
|
170
145
|
// there is nothing to upload, and the check above already says so. Two
|
|
@@ -196,7 +171,7 @@ export const doctorCommand = defineCommand({
|
|
|
196
171
|
// case `missingHookPathWarning` already covers for init.
|
|
197
172
|
ok: uploadConfigured && mossbearBinPath !== null,
|
|
198
173
|
detail: !uploadConfigured
|
|
199
|
-
? `actions are being logged to ~/.mossbear/runs/ and never uploaded — add
|
|
174
|
+
? `actions are being logged to ~/.mossbear/runs/ and never uploaded — run \`mossbear init\` to add the \`${MOSSBEAR_SYNC_COMMAND}\` Stop hook. If you upload some other way, this check will keep reporting.`
|
|
200
175
|
: mossbearBinPath === null
|
|
201
176
|
? '`mossbear` is not on PATH, so the configured Stop hook fails with command-not-found and nothing uploads — reinstall globally (npm install -g mossbear)'
|
|
202
177
|
: `.claude/settings.json has Stop hook (${MOSSBEAR_SYNC_COMMAND})`,
|
|
@@ -209,7 +184,11 @@ export const doctorCommand = defineCommand({
|
|
|
209
184
|
for (const check of checks) {
|
|
210
185
|
const icon = check.ok ? '✓' : '✗';
|
|
211
186
|
const line = ` ${icon} ${check.label}`;
|
|
212
|
-
|
|
187
|
+
// A failing check always shows its detail: the detail *is* the remedy,
|
|
188
|
+
// and hiding it behind --verbose left the default run printing bare `✗`
|
|
189
|
+
// labels under a summary that says "See above for details".
|
|
190
|
+
const detail = check.detail ?? '';
|
|
191
|
+
console.log(!check.ok || args.verbose ? `${line}${detail ? ` (${detail})` : ''}` : line);
|
|
213
192
|
if (!check.ok)
|
|
214
193
|
allOk = false;
|
|
215
194
|
}
|
|
@@ -219,6 +198,7 @@ export const doctorCommand = defineCommand({
|
|
|
219
198
|
// broken connection instead of a misleading "configured" — that gap is the
|
|
220
199
|
// activation-failure signal this check exists to close.
|
|
221
200
|
const token = await resolveToken().catch(() => '');
|
|
201
|
+
let verification = null;
|
|
222
202
|
if (!token) {
|
|
223
203
|
console.log(` i ${describeDashboardHealth('unconfigured', '')}`);
|
|
224
204
|
}
|
|
@@ -230,7 +210,7 @@ export const doctorCommand = defineCommand({
|
|
|
230
210
|
console.log(` i token from $${MOSSBEAR_TOKEN_ENV}`);
|
|
231
211
|
}
|
|
232
212
|
const dashboardUrl = await resolveDashboardUrl(args['dashboard-url']);
|
|
233
|
-
|
|
213
|
+
verification = await verifyDashboardToken(dashboardUrl, token);
|
|
234
214
|
console.log(` i ${describeDashboardHealth(verification, dashboardUrl)}`);
|
|
235
215
|
}
|
|
236
216
|
// Repo-local skills are user-editable, so they are only reported (see
|
|
@@ -242,10 +222,19 @@ export const doctorCommand = defineCommand({
|
|
|
242
222
|
' run `mossbear init --skills-only` to rewrite them (this overwrites local edits)');
|
|
243
223
|
}
|
|
244
224
|
if (!allOk) {
|
|
245
|
-
|
|
225
|
+
// The verdict goes to stdout with the checks it summarizes; only the
|
|
226
|
+
// pointer to the next command goes to stderr. Splitting them left a
|
|
227
|
+
// piped run with no verdict at all on the failing path.
|
|
228
|
+
console.log('\nSome checks failed.');
|
|
229
|
+
console.error('Run `mossbear doctor --verbose` for the full detail on each.');
|
|
246
230
|
process.exit(1);
|
|
247
231
|
}
|
|
248
|
-
|
|
232
|
+
// The connection is informational and never fails the run (see above), but
|
|
233
|
+
// it must not be summarized away either: a rejected token means nothing
|
|
234
|
+
// will sync, and "All checks passed." on its own reads as a clean bill.
|
|
235
|
+
console.log(verification === 'rejected'
|
|
236
|
+
? '\nEnvironment checks passed. The dashboard is not accepting this token, so nothing will sync until you replace it.'
|
|
237
|
+
: '\nAll checks passed.');
|
|
249
238
|
// Doctor is the "check and fix my setup" surface, so it is the one place
|
|
250
239
|
// that offers to run the update rather than just naming it. Suppressed
|
|
251
240
|
// exactly like the ambient notice (TTY, env, config) via checkForUpdate.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { GuideHistoryChange } from '@mossbear/protocol';
|
|
2
|
+
/**
|
|
3
|
+
* `mossbear guides history <guide>` — what grading found about one guide.
|
|
4
|
+
*
|
|
5
|
+
* The shell twin of the `guide_history` MCP tool, over the same endpoint and
|
|
6
|
+
* the same client (`rules/guide-history-client.ts`). Both exist because an
|
|
7
|
+
* improvement session's wiring is not knowable in advance: an MCP-wired agent
|
|
8
|
+
* calls the tool, and any other agent — or the user, at a prompt — runs this
|
|
9
|
+
* (spec → Resolved, 2026-08-22).
|
|
10
|
+
*
|
|
11
|
+
* **This one reaches the network**, unlike `guides active` and `guides search`,
|
|
12
|
+
* which read the local cache. Verdicts are the server's and the CLI holds none
|
|
13
|
+
* of them by design, so there is nothing local to read here.
|
|
14
|
+
*
|
|
15
|
+
* `--json` is not a convenience flag: an agent invoking this through a shell
|
|
16
|
+
* wants the payload the MCP tool returns, delimiters included, rather than
|
|
17
|
+
* prose it has to parse back.
|
|
18
|
+
*/
|
|
19
|
+
export declare const guidesHistoryCommand: import("citty").CommandDef<{
|
|
20
|
+
guide: {
|
|
21
|
+
type: "positional";
|
|
22
|
+
description: string;
|
|
23
|
+
required: true;
|
|
24
|
+
};
|
|
25
|
+
root: {
|
|
26
|
+
type: "string";
|
|
27
|
+
description: string;
|
|
28
|
+
default: string;
|
|
29
|
+
};
|
|
30
|
+
'guide-id': {
|
|
31
|
+
type: "string";
|
|
32
|
+
description: string;
|
|
33
|
+
default: string;
|
|
34
|
+
};
|
|
35
|
+
json: {
|
|
36
|
+
type: "boolean";
|
|
37
|
+
description: string;
|
|
38
|
+
default: false;
|
|
39
|
+
};
|
|
40
|
+
token: {
|
|
41
|
+
type: "string";
|
|
42
|
+
description: string;
|
|
43
|
+
default: string;
|
|
44
|
+
};
|
|
45
|
+
'dashboard-url': {
|
|
46
|
+
type: "string";
|
|
47
|
+
description: string;
|
|
48
|
+
default: string;
|
|
49
|
+
};
|
|
50
|
+
}>;
|
|
51
|
+
/**
|
|
52
|
+
* The last edit's two windows, as sentences.
|
|
53
|
+
*
|
|
54
|
+
* **A window and its denominators, and then it stops.** "Since" is the
|
|
55
|
+
* strongest word the evidence supports — the model changed, the task mix
|
|
56
|
+
* changed and the codebase changed too — so nothing here says the edit caused
|
|
57
|
+
* what followed it, and the date is a boundary rather than an attribution.
|
|
58
|
+
*
|
|
59
|
+
* **A suppressed pair is a sentence, not a silence**, and so is a guide with no
|
|
60
|
+
* earlier wording. Printing nothing in either case would leave a reader unable
|
|
61
|
+
* to tell "too few runs to say" from "this edit changed nothing", which are
|
|
62
|
+
* opposite statements — the same reason the payload carries `change: null`
|
|
63
|
+
* rather than omitting the key.
|
|
64
|
+
*
|
|
65
|
+
* **A regression reads exactly like an improvement**: same place, same words,
|
|
66
|
+
* different verb. It is the more useful of the two, because it says the
|
|
67
|
+
* guidance is not the lever.
|
|
68
|
+
*
|
|
69
|
+
* Exported for its unit test, and pure so that test needs no network.
|
|
70
|
+
*/
|
|
71
|
+
export declare function guideChangeLines(change: GuideHistoryChange | null): string[];
|
|
72
|
+
//# sourceMappingURL=history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../../src/commands/guides/history.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAEV,kBAAkB,EAEnB,MAAM,oBAAoB,CAAA;AAE3B;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoF/B,CAAA;AA2EF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,GAAG,MAAM,EAAE,CAuC5E"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { defineCommand } from 'citty';
|
|
2
|
+
import { resolveDashboardUrl, resolveToken } from '../../config.js';
|
|
3
|
+
import { errText } from '../../err-text.js';
|
|
4
|
+
import { fetchGuideHistory } from '../../rules/guide-history-client.js';
|
|
5
|
+
import { resolveRepoIdentity } from '../../rules/repo-identity.js';
|
|
6
|
+
/**
|
|
7
|
+
* `mossbear guides history <guide>` — what grading found about one guide.
|
|
8
|
+
*
|
|
9
|
+
* The shell twin of the `guide_history` MCP tool, over the same endpoint and
|
|
10
|
+
* the same client (`rules/guide-history-client.ts`). Both exist because an
|
|
11
|
+
* improvement session's wiring is not knowable in advance: an MCP-wired agent
|
|
12
|
+
* calls the tool, and any other agent — or the user, at a prompt — runs this
|
|
13
|
+
* (spec → Resolved, 2026-08-22).
|
|
14
|
+
*
|
|
15
|
+
* **This one reaches the network**, unlike `guides active` and `guides search`,
|
|
16
|
+
* which read the local cache. Verdicts are the server's and the CLI holds none
|
|
17
|
+
* of them by design, so there is nothing local to read here.
|
|
18
|
+
*
|
|
19
|
+
* `--json` is not a convenience flag: an agent invoking this through a shell
|
|
20
|
+
* wants the payload the MCP tool returns, delimiters included, rather than
|
|
21
|
+
* prose it has to parse back.
|
|
22
|
+
*/
|
|
23
|
+
export const guidesHistoryCommand = defineCommand({
|
|
24
|
+
meta: {
|
|
25
|
+
name: 'history',
|
|
26
|
+
description: 'Show what grading found about one guide or skill (reads the dashboard)',
|
|
27
|
+
},
|
|
28
|
+
args: {
|
|
29
|
+
guide: {
|
|
30
|
+
type: 'positional',
|
|
31
|
+
description: "The guide file's path (.claude/skills/reviewer/SKILL.md, AGENTS.md) or a bare skill name (reviewer)",
|
|
32
|
+
required: true,
|
|
33
|
+
},
|
|
34
|
+
root: {
|
|
35
|
+
type: 'string',
|
|
36
|
+
description: 'project or global — which discovery root, when a name reaches both',
|
|
37
|
+
default: '',
|
|
38
|
+
},
|
|
39
|
+
'guide-id': {
|
|
40
|
+
type: 'string',
|
|
41
|
+
description: 'The exact guide, when a name reached several and the refusal listed them',
|
|
42
|
+
default: '',
|
|
43
|
+
},
|
|
44
|
+
json: {
|
|
45
|
+
type: 'boolean',
|
|
46
|
+
description: 'Print the raw payload instead of a summary',
|
|
47
|
+
default: false,
|
|
48
|
+
},
|
|
49
|
+
token: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
description: 'Mossbear API token — overrides the stored one for this call',
|
|
52
|
+
default: '',
|
|
53
|
+
},
|
|
54
|
+
'dashboard-url': {
|
|
55
|
+
type: 'string',
|
|
56
|
+
description: 'Override the dashboard base URL',
|
|
57
|
+
default: '',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
async run({ args }) {
|
|
61
|
+
const root = args.root.trim();
|
|
62
|
+
if (root !== '' && root !== 'project' && root !== 'global') {
|
|
63
|
+
console.error(` root must be "project" or "global" — got "${root}".`);
|
|
64
|
+
process.exitCode = 1;
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const token = await resolveToken(args.token);
|
|
68
|
+
if (!token) {
|
|
69
|
+
console.error('No Mossbear token configured. Get one from the dashboard (Settings → Developer → CLI Token), then run `mossbear init --token <token>` or pass `mossbear guides history <guide> --token <token>`.');
|
|
70
|
+
process.exitCode = 1;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const dashboardUrl = await resolveDashboardUrl(args['dashboard-url']);
|
|
74
|
+
let history;
|
|
75
|
+
try {
|
|
76
|
+
history = await fetchGuideHistory({
|
|
77
|
+
dashboardUrl,
|
|
78
|
+
token,
|
|
79
|
+
guide: args.guide,
|
|
80
|
+
root: root === '' ? undefined : root,
|
|
81
|
+
guideId: args['guide-id'] === '' ? undefined : args['guide-id'],
|
|
82
|
+
// A thunk: nothing about this repo is read unless the server says the
|
|
83
|
+
// identifier is ambiguous. Narrowing every query to this repo would
|
|
84
|
+
// stop answering about a guide adopted from another one.
|
|
85
|
+
disambiguateWith: () => resolveRepoIdentity(process.cwd()),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
console.error(` ${errText(err)}`);
|
|
90
|
+
process.exitCode = 1;
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (args.json) {
|
|
94
|
+
console.log(JSON.stringify(history, null, 2));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
printHistory(history);
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
/**
|
|
101
|
+
* The summary a person reads.
|
|
102
|
+
*
|
|
103
|
+
* Every branch below is a *different* sentence for a different state, which is
|
|
104
|
+
* the whole point: "no runs have engaged this guide", "no run has used this
|
|
105
|
+
* wording yet" and "never graded" are three facts, and one sentence covering
|
|
106
|
+
* all three would state something the record does not say.
|
|
107
|
+
*/
|
|
108
|
+
function printHistory(history) {
|
|
109
|
+
const { guide, window: figures } = history;
|
|
110
|
+
const where = guide.path === null ? '(no declared path)' : guide.path;
|
|
111
|
+
const rootLabel = guide.root === null ? '' : ` [${guide.root}]`;
|
|
112
|
+
console.log(`${guide.title} — ${where}${rootLabel}`);
|
|
113
|
+
if (history.state === 'unevaluated') {
|
|
114
|
+
console.log('\n Not yet graded. No run has produced a verdict for this guide.');
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (history.state === 'awaiting_current_revision') {
|
|
118
|
+
// The normal state right after an edit: a real record, none of it about the
|
|
119
|
+
// wording on disk now. Reporting it as "not graded" would be a claim the
|
|
120
|
+
// user can contradict from their own dashboard.
|
|
121
|
+
const count = figures.olderRevisionRows;
|
|
122
|
+
const hedge = figures.isWindowed ? 'at least ' : '';
|
|
123
|
+
console.log(`\n No runs on this wording yet. ${hedge}${count} earlier verdict(s) judged wording it no longer has.`);
|
|
124
|
+
}
|
|
125
|
+
else if (figures.alignmentRate === null) {
|
|
126
|
+
console.log(`\n Graded in ${figures.total} run(s), none of which engaged this guide.`);
|
|
127
|
+
}
|
|
128
|
+
else if (figures.isLowConfidence) {
|
|
129
|
+
// Below the threshold the counts are the honest report and a percentage is
|
|
130
|
+
// not — one applicable run does not make a rate.
|
|
131
|
+
console.log(`\n Aligned in ${figures.aligned} of ${figures.applicable} run(s) that engaged this guide — too few runs to read as a rate.`);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
console.log(`\n ${Math.round(figures.alignmentRate * 100)}% aligned — ${figures.aligned} of ${figures.applicable} run(s) that engaged this guide.`);
|
|
135
|
+
}
|
|
136
|
+
if (history.state === 'evaluated') {
|
|
137
|
+
const scope = figures.isWindowed
|
|
138
|
+
? `a sample of the last ${figures.windowSize} graded runs`
|
|
139
|
+
: `every graded run so far`;
|
|
140
|
+
console.log(` Counted over ${scope}; ${figures.notApplicable} never engaged it.`);
|
|
141
|
+
}
|
|
142
|
+
// Already indented to match the block above; the leading blank line separates
|
|
143
|
+
// the pair from the rate it qualifies.
|
|
144
|
+
for (const line of guideChangeLines(history.change))
|
|
145
|
+
console.log(line);
|
|
146
|
+
if (history.findings.length === 0) {
|
|
147
|
+
console.log('\n No recorded findings.');
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const more = history.findingsOmitted > 0 ? ` (${history.findingsOmitted} more not shown)` : '';
|
|
151
|
+
console.log(`\n Recent findings${more}:`);
|
|
152
|
+
for (const finding of history.findings) {
|
|
153
|
+
const age = finding.isCurrentRevision ? '' : ' — about earlier wording';
|
|
154
|
+
console.log(`\n · ${finding.occurredAt}${age}`);
|
|
155
|
+
// Printed with its markers intact. They are what says "this is transcript-
|
|
156
|
+
// derived text, not instructions", and an agent reading this through a
|
|
157
|
+
// shell needs that as much as one reading the MCP tool's JSON.
|
|
158
|
+
console.log(indent(finding.reasoning));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The last edit's two windows, as sentences.
|
|
163
|
+
*
|
|
164
|
+
* **A window and its denominators, and then it stops.** "Since" is the
|
|
165
|
+
* strongest word the evidence supports — the model changed, the task mix
|
|
166
|
+
* changed and the codebase changed too — so nothing here says the edit caused
|
|
167
|
+
* what followed it, and the date is a boundary rather than an attribution.
|
|
168
|
+
*
|
|
169
|
+
* **A suppressed pair is a sentence, not a silence**, and so is a guide with no
|
|
170
|
+
* earlier wording. Printing nothing in either case would leave a reader unable
|
|
171
|
+
* to tell "too few runs to say" from "this edit changed nothing", which are
|
|
172
|
+
* opposite statements — the same reason the payload carries `change: null`
|
|
173
|
+
* rather than omitting the key.
|
|
174
|
+
*
|
|
175
|
+
* **A regression reads exactly like an improvement**: same place, same words,
|
|
176
|
+
* different verb. It is the more useful of the two, because it says the
|
|
177
|
+
* guidance is not the lever.
|
|
178
|
+
*
|
|
179
|
+
* Exported for its unit test, and pure so that test needs no network.
|
|
180
|
+
*/
|
|
181
|
+
export function guideChangeLines(change) {
|
|
182
|
+
if (change === null) {
|
|
183
|
+
return ['', ' No before/after: this guide has no earlier wording with graded runs.'];
|
|
184
|
+
}
|
|
185
|
+
const when = change.changedAt === null ? '' : ` (recorded ${change.changedAt})`;
|
|
186
|
+
const { since, before } = change;
|
|
187
|
+
const lines = ['', ` Since the last edit${when}:`];
|
|
188
|
+
if (change.suppressedBy !== null) {
|
|
189
|
+
// Below the sample floor a percentage is a lie with a decimal point in it,
|
|
190
|
+
// so the counts are the whole report and the sentence names which side is
|
|
191
|
+
// thin: too few runs *since* is the ordinary state right after an edit,
|
|
192
|
+
// while too few *before* means there was never a baseline to compare with.
|
|
193
|
+
lines.push(change.suppressedBy === 'since'
|
|
194
|
+
? ` Not enough runs since this change to compare — ${since.applicable} run(s) have engaged this wording, against ${before.applicable} on the wording before it.`
|
|
195
|
+
: change.suppressedBy === 'before'
|
|
196
|
+
? ` Not enough runs before this change to compare — ${before.applicable} run(s) engaged the previous wording.`
|
|
197
|
+
: ` Not enough runs either side of this change to compare — ${since.applicable} since, ${before.applicable} before.`);
|
|
198
|
+
return lines;
|
|
199
|
+
}
|
|
200
|
+
const verb = change.direction === 'improved'
|
|
201
|
+
? 'more often'
|
|
202
|
+
: change.direction === 'regressed'
|
|
203
|
+
? 'less often'
|
|
204
|
+
: 'about as often';
|
|
205
|
+
lines.push(` Aligned ${verb} since this change: ${since.aligned} of ${since.applicable} run(s) that engaged this wording, against ${before.aligned} of ${before.applicable} before it.`);
|
|
206
|
+
if (change.isWindowed) {
|
|
207
|
+
lines.push(` Each side is a bounded sample of its own wording — up to ${change.windowSize} runs — not a lifetime total.`);
|
|
208
|
+
}
|
|
209
|
+
return lines;
|
|
210
|
+
}
|
|
211
|
+
function indent(block) {
|
|
212
|
+
return block
|
|
213
|
+
.split('\n')
|
|
214
|
+
.map((line) => ` ${line}`)
|
|
215
|
+
.join('\n');
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.js","sourceRoot":"","sources":["../../../src/commands/guides/history.ts"],"names":[],"mappings":"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"}
|