@nanonets/graft 0.24.0 → 0.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ask/ask.d.ts +8 -0
- package/dist/ask/ask.d.ts.map +1 -1
- package/dist/ask/ask.js +33 -12
- package/dist/ask/ask.js.map +1 -1
- package/dist/claude/hook-io.d.ts +44 -0
- package/dist/claude/hook-io.d.ts.map +1 -0
- package/dist/claude/hook-io.js +144 -0
- package/dist/claude/hook-io.js.map +1 -0
- package/dist/claude/skills-hook-util.d.ts +25 -0
- package/dist/claude/skills-hook-util.d.ts.map +1 -0
- package/dist/claude/skills-hook-util.js +71 -0
- package/dist/claude/skills-hook-util.js.map +1 -0
- package/dist/cli-picker.d.ts +24 -0
- package/dist/cli-picker.d.ts.map +1 -1
- package/dist/cli-picker.js +36 -5
- package/dist/cli-picker.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +278 -29
- package/dist/cli.js.map +1 -1
- package/dist/cloud/lookup-activity.d.ts +16 -0
- package/dist/cloud/lookup-activity.d.ts.map +1 -0
- package/dist/cloud/lookup-activity.js +56 -0
- package/dist/cloud/lookup-activity.js.map +1 -0
- package/dist/cloud/nudge.d.ts.map +1 -1
- package/dist/cloud/nudge.js +3 -0
- package/dist/cloud/nudge.js.map +1 -1
- package/dist/cloud/onboarding.d.ts +237 -0
- package/dist/cloud/onboarding.d.ts.map +1 -0
- package/dist/cloud/onboarding.js +536 -0
- package/dist/cloud/onboarding.js.map +1 -0
- package/dist/cloud/pair.d.ts +76 -0
- package/dist/cloud/pair.d.ts.map +1 -0
- package/dist/cloud/pair.js +249 -0
- package/dist/cloud/pair.js.map +1 -0
- package/dist/cloud/workspace-sync.d.ts +10 -2
- package/dist/cloud/workspace-sync.d.ts.map +1 -1
- package/dist/cloud/workspace-sync.js +119 -7
- package/dist/cloud/workspace-sync.js.map +1 -1
- package/dist/cloud/workspace.d.ts +22 -1
- package/dist/cloud/workspace.d.ts.map +1 -1
- package/dist/cloud/workspace.js +16 -1
- package/dist/cloud/workspace.js.map +1 -1
- package/dist/graph/native.d.ts +2 -0
- package/dist/graph/native.d.ts.map +1 -1
- package/dist/graph/native.js +29 -4
- package/dist/graph/native.js.map +1 -1
- package/dist/hosts/claude-global.d.ts +14 -0
- package/dist/hosts/claude-global.d.ts.map +1 -1
- package/dist/hosts/claude-global.js +38 -3
- package/dist/hosts/claude-global.js.map +1 -1
- package/dist/init/install-record.d.ts +21 -0
- package/dist/init/install-record.d.ts.map +1 -0
- package/dist/init/install-record.js +144 -0
- package/dist/init/install-record.js.map +1 -0
- package/dist/init/plain-file.d.ts +11 -0
- package/dist/init/plain-file.d.ts.map +1 -0
- package/dist/init/plain-file.js +80 -0
- package/dist/init/plain-file.js.map +1 -0
- package/dist/mcp/brains.d.ts +72 -0
- package/dist/mcp/brains.d.ts.map +1 -0
- package/dist/mcp/brains.js +220 -0
- package/dist/mcp/brains.js.map +1 -0
- package/dist/mcp/server.d.ts +3 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +40 -5
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +7 -2
- package/dist/mcp/tools.js.map +1 -1
- package/dist/notes/cold-start.d.ts +30 -1
- package/dist/notes/cold-start.d.ts.map +1 -1
- package/dist/notes/cold-start.js +98 -19
- package/dist/notes/cold-start.js.map +1 -1
- package/dist/notes/every-repo.d.ts +18 -0
- package/dist/notes/every-repo.d.ts.map +1 -0
- package/dist/notes/every-repo.js +86 -0
- package/dist/notes/every-repo.js.map +1 -0
- package/dist/notes/guardrails.d.ts +8 -0
- package/dist/notes/guardrails.d.ts.map +1 -0
- package/dist/notes/guardrails.js +38 -0
- package/dist/notes/guardrails.js.map +1 -0
- package/dist/notes/lesson-index.d.ts +13 -0
- package/dist/notes/lesson-index.d.ts.map +1 -0
- package/dist/notes/lesson-index.js +135 -0
- package/dist/notes/lesson-index.js.map +1 -0
- package/dist/notes/linked-learnings.d.ts +8 -0
- package/dist/notes/linked-learnings.d.ts.map +1 -0
- package/dist/notes/linked-learnings.js +113 -0
- package/dist/notes/linked-learnings.js.map +1 -0
- package/dist/notes/replace.d.ts +14 -0
- package/dist/notes/replace.d.ts.map +1 -0
- package/dist/notes/replace.js +38 -0
- package/dist/notes/replace.js.map +1 -0
- package/dist/notes/repo-notes-dir.d.ts +2 -0
- package/dist/notes/repo-notes-dir.d.ts.map +1 -0
- package/dist/notes/repo-notes-dir.js +16 -0
- package/dist/notes/repo-notes-dir.js.map +1 -0
- package/dist/skills/anchors-cli.d.ts +33 -0
- package/dist/skills/anchors-cli.d.ts.map +1 -0
- package/dist/skills/anchors-cli.js +274 -0
- package/dist/skills/anchors-cli.js.map +1 -0
- package/dist/skills/anchors-git.d.ts +29 -0
- package/dist/skills/anchors-git.d.ts.map +1 -0
- package/dist/skills/anchors-git.js +241 -0
- package/dist/skills/anchors-git.js.map +1 -0
- package/dist/skills/anchors-wide.d.ts +25 -0
- package/dist/skills/anchors-wide.d.ts.map +1 -0
- package/dist/skills/anchors-wide.js +481 -0
- package/dist/skills/anchors-wide.js.map +1 -0
- package/dist/skills/anchors.d.ts +32 -0
- package/dist/skills/anchors.d.ts.map +1 -0
- package/dist/skills/anchors.js +485 -0
- package/dist/skills/anchors.js.map +1 -0
- package/dist/skills/check-result.d.ts +26 -0
- package/dist/skills/check-result.d.ts.map +1 -0
- package/dist/skills/check-result.js +46 -0
- package/dist/skills/check-result.js.map +1 -0
- package/dist/skills/codex-sandbox.d.ts +6 -0
- package/dist/skills/codex-sandbox.d.ts.map +1 -0
- package/dist/skills/codex-sandbox.js +55 -0
- package/dist/skills/codex-sandbox.js.map +1 -0
- package/dist/skills/compile-split.d.ts +57 -0
- package/dist/skills/compile-split.d.ts.map +1 -0
- package/dist/skills/compile-split.js +532 -0
- package/dist/skills/compile-split.js.map +1 -0
- package/dist/skills/compile-version.d.ts +37 -0
- package/dist/skills/compile-version.d.ts.map +1 -0
- package/dist/skills/compile-version.js +56 -0
- package/dist/skills/compile-version.js.map +1 -0
- package/dist/skills/compile-waits.d.ts +12 -0
- package/dist/skills/compile-waits.d.ts.map +1 -0
- package/dist/skills/compile-waits.js +52 -0
- package/dist/skills/compile-waits.js.map +1 -0
- package/dist/skills/compile-words.d.ts +82 -0
- package/dist/skills/compile-words.d.ts.map +1 -0
- package/dist/skills/compile-words.js +385 -0
- package/dist/skills/compile-words.js.map +1 -0
- package/dist/skills/compile.d.ts +35 -0
- package/dist/skills/compile.d.ts.map +1 -0
- package/dist/skills/compile.js +488 -0
- package/dist/skills/compile.js.map +1 -0
- package/dist/skills/credit-facts.d.ts +8 -0
- package/dist/skills/credit-facts.d.ts.map +1 -0
- package/dist/skills/credit-facts.js +32 -0
- package/dist/skills/credit-facts.js.map +1 -0
- package/dist/skills/directive-words.d.ts +11 -0
- package/dist/skills/directive-words.d.ts.map +1 -0
- package/dist/skills/directive-words.js +33 -0
- package/dist/skills/directive-words.js.map +1 -0
- package/dist/skills/fidelity.d.ts +42 -0
- package/dist/skills/fidelity.d.ts.map +1 -0
- package/dist/skills/fidelity.js +138 -0
- package/dist/skills/fidelity.js.map +1 -0
- package/dist/skills/forget-notice.d.ts +44 -0
- package/dist/skills/forget-notice.d.ts.map +1 -0
- package/dist/skills/forget-notice.js +131 -0
- package/dist/skills/forget-notice.js.map +1 -0
- package/dist/skills/found-skill.d.ts +35 -0
- package/dist/skills/found-skill.d.ts.map +1 -0
- package/dist/skills/found-skill.js +66 -0
- package/dist/skills/found-skill.js.map +1 -0
- package/dist/skills/front-version.d.ts +12 -0
- package/dist/skills/front-version.d.ts.map +1 -0
- package/dist/skills/front-version.js +87 -0
- package/dist/skills/front-version.js.map +1 -0
- package/dist/skills/host-facts.d.ts +51 -0
- package/dist/skills/host-facts.d.ts.map +1 -0
- package/dist/skills/host-facts.js +134 -0
- package/dist/skills/host-facts.js.map +1 -0
- package/dist/skills/ledger.d.ts +43 -0
- package/dist/skills/ledger.d.ts.map +1 -0
- package/dist/skills/ledger.js +336 -0
- package/dist/skills/ledger.js.map +1 -0
- package/dist/skills/lessons.d.ts +60 -0
- package/dist/skills/lessons.d.ts.map +1 -0
- package/dist/skills/lessons.js +396 -0
- package/dist/skills/lessons.js.map +1 -0
- package/dist/skills/offer-answers.d.ts +20 -0
- package/dist/skills/offer-answers.d.ts.map +1 -0
- package/dist/skills/offer-answers.js +51 -0
- package/dist/skills/offer-answers.js.map +1 -0
- package/dist/skills/own-folder.d.ts +9 -0
- package/dist/skills/own-folder.d.ts.map +1 -0
- package/dist/skills/own-folder.js +36 -0
- package/dist/skills/own-folder.js.map +1 -0
- package/dist/skills/person.d.ts +34 -0
- package/dist/skills/person.d.ts.map +1 -0
- package/dist/skills/person.js +102 -0
- package/dist/skills/person.js.map +1 -0
- package/dist/skills/probe-clean.d.ts +9 -0
- package/dist/skills/probe-clean.d.ts.map +1 -0
- package/dist/skills/probe-clean.js +48 -0
- package/dist/skills/probe-clean.js.map +1 -0
- package/dist/skills/probes.d.ts +26 -0
- package/dist/skills/probes.d.ts.map +1 -0
- package/dist/skills/probes.js +225 -0
- package/dist/skills/probes.js.map +1 -0
- package/dist/skills/recall.d.ts +119 -0
- package/dist/skills/recall.d.ts.map +1 -0
- package/dist/skills/recall.js +370 -0
- package/dist/skills/recall.js.map +1 -0
- package/dist/skills/receipts.d.ts +44 -0
- package/dist/skills/receipts.d.ts.map +1 -0
- package/dist/skills/receipts.js +223 -0
- package/dist/skills/receipts.js.map +1 -0
- package/dist/skills/run-checkout.d.ts +4 -0
- package/dist/skills/run-checkout.d.ts.map +1 -0
- package/dist/skills/run-checkout.js +37 -0
- package/dist/skills/run-checkout.js.map +1 -0
- package/dist/skills/runblock.d.ts +45 -0
- package/dist/skills/runblock.d.ts.map +1 -0
- package/dist/skills/runblock.js +222 -0
- package/dist/skills/runblock.js.map +1 -0
- package/dist/skills/save-parse.d.ts +42 -0
- package/dist/skills/save-parse.d.ts.map +1 -0
- package/dist/skills/save-parse.js +172 -0
- package/dist/skills/save-parse.js.map +1 -0
- package/dist/skills/save-store.d.ts +12 -0
- package/dist/skills/save-store.d.ts.map +1 -0
- package/dist/skills/save-store.js +22 -0
- package/dist/skills/save-store.js.map +1 -0
- package/dist/skills/settings.d.ts +38 -0
- package/dist/skills/settings.d.ts.map +1 -0
- package/dist/skills/settings.js +133 -0
- package/dist/skills/settings.js.map +1 -0
- package/dist/skills/skill-diff.d.ts +40 -0
- package/dist/skills/skill-diff.d.ts.map +1 -0
- package/dist/skills/skill-diff.js +191 -0
- package/dist/skills/skill-diff.js.map +1 -0
- package/dist/skills/skill-file.d.ts +24 -0
- package/dist/skills/skill-file.d.ts.map +1 -0
- package/dist/skills/skill-file.js +97 -0
- package/dist/skills/skill-file.js.map +1 -0
- package/dist/skills/skill-rebuild.d.ts +27 -0
- package/dist/skills/skill-rebuild.d.ts.map +1 -0
- package/dist/skills/skill-rebuild.js +85 -0
- package/dist/skills/skill-rebuild.js.map +1 -0
- package/dist/skills/skillmd.d.ts +17 -0
- package/dist/skills/skillmd.d.ts.map +1 -0
- package/dist/skills/skillmd.js +219 -0
- package/dist/skills/skillmd.js.map +1 -0
- package/dist/skills/skills.d.ts +2 -0
- package/dist/skills/skills.d.ts.map +1 -1
- package/dist/skills/skills.js +1 -1
- package/dist/skills/skills.js.map +1 -1
- package/dist/skills/staleness.d.ts +27 -0
- package/dist/skills/staleness.d.ts.map +1 -0
- package/dist/skills/staleness.js +178 -0
- package/dist/skills/staleness.js.map +1 -0
- package/dist/skills/state.d.ts +36 -0
- package/dist/skills/state.d.ts.map +1 -0
- package/dist/skills/state.js +259 -0
- package/dist/skills/state.js.map +1 -0
- package/dist/skills/store-fs.d.ts +77 -0
- package/dist/skills/store-fs.d.ts.map +1 -0
- package/dist/skills/store-fs.js +194 -0
- package/dist/skills/store-fs.js.map +1 -0
- package/dist/skills/store-held.d.ts +44 -0
- package/dist/skills/store-held.d.ts.map +1 -0
- package/dist/skills/store-held.js +147 -0
- package/dist/skills/store-held.js.map +1 -0
- package/dist/skills/store.d.ts +73 -0
- package/dist/skills/store.d.ts.map +1 -0
- package/dist/skills/store.js +279 -0
- package/dist/skills/store.js.map +1 -0
- package/dist/skills/validate.d.ts +11 -0
- package/dist/skills/validate.d.ts.map +1 -0
- package/dist/skills/validate.js +112 -0
- package/dist/skills/validate.js.map +1 -0
- package/dist/skills/versions-fs.d.ts +45 -0
- package/dist/skills/versions-fs.d.ts.map +1 -0
- package/dist/skills/versions-fs.js +234 -0
- package/dist/skills/versions-fs.js.map +1 -0
- package/dist/skills/versions.d.ts +56 -0
- package/dist/skills/versions.d.ts.map +1 -0
- package/dist/skills/versions.js +351 -0
- package/dist/skills/versions.js.map +1 -0
- package/dist/trace/checks.d.ts +63 -0
- package/dist/trace/checks.d.ts.map +1 -0
- package/dist/trace/checks.js +487 -0
- package/dist/trace/checks.js.map +1 -0
- package/dist/trace/claude.d.ts +124 -0
- package/dist/trace/claude.d.ts.map +1 -0
- package/dist/trace/claude.js +303 -0
- package/dist/trace/claude.js.map +1 -0
- package/dist/trace/codex-exec.d.ts +22 -0
- package/dist/trace/codex-exec.d.ts.map +1 -0
- package/dist/trace/codex-exec.js +129 -0
- package/dist/trace/codex-exec.js.map +1 -0
- package/dist/trace/codex-meta.d.ts +23 -0
- package/dist/trace/codex-meta.d.ts.map +1 -0
- package/dist/trace/codex-meta.js +112 -0
- package/dist/trace/codex-meta.js.map +1 -0
- package/dist/trace/codex.d.ts +33 -0
- package/dist/trace/codex.d.ts.map +1 -0
- package/dist/trace/codex.js +485 -0
- package/dist/trace/codex.js.map +1 -0
- package/dist/trace/cursor.d.ts +16 -0
- package/dist/trace/cursor.d.ts.map +1 -0
- package/dist/trace/cursor.js +133 -0
- package/dist/trace/cursor.js.map +1 -0
- package/dist/trace/dialect.d.ts +43 -0
- package/dist/trace/dialect.d.ts.map +1 -0
- package/dist/trace/dialect.js +95 -0
- package/dist/trace/dialect.js.map +1 -0
- package/dist/trace/epochs.d.ts +10 -0
- package/dist/trace/epochs.d.ts.map +1 -0
- package/dist/trace/epochs.js +16 -0
- package/dist/trace/epochs.js.map +1 -0
- package/dist/trace/failure.d.ts +15 -0
- package/dist/trace/failure.d.ts.map +1 -0
- package/dist/trace/failure.js +69 -0
- package/dist/trace/failure.js.map +1 -0
- package/dist/trace/gate-file.d.ts +71 -0
- package/dist/trace/gate-file.d.ts.map +1 -0
- package/dist/trace/gate-file.js +329 -0
- package/dist/trace/gate-file.js.map +1 -0
- package/dist/trace/guard-fast.d.ts +22 -0
- package/dist/trace/guard-fast.d.ts.map +1 -0
- package/dist/trace/guard-fast.js +213 -0
- package/dist/trace/guard-fast.js.map +1 -0
- package/dist/trace/housekeeping.d.ts +5 -0
- package/dist/trace/housekeeping.d.ts.map +1 -0
- package/dist/trace/housekeeping.js +93 -0
- package/dist/trace/housekeeping.js.map +1 -0
- package/dist/trace/jobs.d.ts +52 -0
- package/dist/trace/jobs.d.ts.map +1 -0
- package/dist/trace/jobs.js +182 -0
- package/dist/trace/jobs.js.map +1 -0
- package/dist/trace/known-repo.d.ts +3 -0
- package/dist/trace/known-repo.d.ts.map +1 -0
- package/dist/trace/known-repo.js +55 -0
- package/dist/trace/known-repo.js.map +1 -0
- package/dist/trace/pool.d.ts +40 -0
- package/dist/trace/pool.d.ts.map +1 -0
- package/dist/trace/pool.js +154 -0
- package/dist/trace/pool.js.map +1 -0
- package/dist/trace/repairs.d.ts +27 -0
- package/dist/trace/repairs.d.ts.map +1 -0
- package/dist/trace/repairs.js +303 -0
- package/dist/trace/repairs.js.map +1 -0
- package/dist/trace/run-calls.d.ts +82 -0
- package/dist/trace/run-calls.d.ts.map +1 -0
- package/dist/trace/run-calls.js +331 -0
- package/dist/trace/run-calls.js.map +1 -0
- package/dist/trace/run-join.d.ts +20 -0
- package/dist/trace/run-join.d.ts.map +1 -0
- package/dist/trace/run-join.js +99 -0
- package/dist/trace/run-join.js.map +1 -0
- package/dist/trace/run-sheets.d.ts +26 -0
- package/dist/trace/run-sheets.d.ts.map +1 -0
- package/dist/trace/run-sheets.js +145 -0
- package/dist/trace/run-sheets.js.map +1 -0
- package/dist/trace/run-turns.d.ts +24 -0
- package/dist/trace/run-turns.d.ts.map +1 -0
- package/dist/trace/run-turns.js +67 -0
- package/dist/trace/run-turns.js.map +1 -0
- package/dist/trace/run-verdict.d.ts +24 -0
- package/dist/trace/run-verdict.d.ts.map +1 -0
- package/dist/trace/run-verdict.js +176 -0
- package/dist/trace/run-verdict.js.map +1 -0
- package/dist/trace/runs.d.ts +54 -0
- package/dist/trace/runs.d.ts.map +1 -0
- package/dist/trace/runs.js +501 -0
- package/dist/trace/runs.js.map +1 -0
- package/dist/trace/skill-session.d.ts +64 -0
- package/dist/trace/skill-session.d.ts.map +1 -0
- package/dist/trace/skill-session.js +232 -0
- package/dist/trace/skill-session.js.map +1 -0
- package/dist/trace/tamper.d.ts +12 -0
- package/dist/trace/tamper.d.ts.map +1 -0
- package/dist/trace/tamper.js +405 -0
- package/dist/trace/tamper.js.map +1 -0
- package/dist/trace/typed.d.ts +30 -0
- package/dist/trace/typed.d.ts.map +1 -0
- package/dist/trace/typed.js +132 -0
- package/dist/trace/typed.js.map +1 -0
- package/dist/trace/wall-state.d.ts +86 -0
- package/dist/trace/wall-state.d.ts.map +1 -0
- package/dist/trace/wall-state.js +279 -0
- package/dist/trace/wall-state.js.map +1 -0
- package/dist/trace/walls.d.ts +40 -0
- package/dist/trace/walls.d.ts.map +1 -0
- package/dist/trace/walls.js +318 -0
- package/dist/trace/walls.js.map +1 -0
- package/dist/vendor/tree-sitter-swift/LICENSE +21 -0
- package/dist/vendor/tree-sitter-swift/node-types.json +30694 -0
- package/dist/vendor/tree-sitter-swift/prebuilds/darwin-arm64/tree-sitter-swift.node +0 -0
- package/dist/vendor/tree-sitter-swift/prebuilds/darwin-x64/tree-sitter-swift.node +0 -0
- package/dist/vendor/tree-sitter-swift/prebuilds/linux-arm64/tree-sitter-swift.node +0 -0
- package/dist/vendor/tree-sitter-swift/prebuilds/linux-x64/tree-sitter-swift.node +0 -0
- package/dist/vendor/tree-sitter-swift/prebuilds/win32-arm64/tree-sitter-swift.node +0 -0
- package/dist/vendor/tree-sitter-swift/prebuilds/win32-x64/tree-sitter-swift.node +0 -0
- package/package.json +6 -3
- package/scripts/stamp-telemetry-key.mjs +8 -5
- package/scripts/vendor-grammars.mjs +35 -0
package/dist/cli.js
CHANGED
|
@@ -41,6 +41,7 @@ import { planInit, selectedWrites } from "./hosts/plan.js";
|
|
|
41
41
|
import { planRetract, runRetract, changed } from "./hosts/retract.js";
|
|
42
42
|
import { compactWrites, formatNonInteractiveHelp, formatPlan, pickLearnings, runPicker } from "./cli-picker.js";
|
|
43
43
|
import { buildGraphWithProgress } from "./claude/build-progress.js";
|
|
44
|
+
import { installBrainsServer, removeBrainsServer } from "./hosts/claude-global.js";
|
|
44
45
|
import { homedir } from "node:os";
|
|
45
46
|
import { formatUpgradeReport, formatVersionReport, getNpmViewVersion, readCurrentVersion, readPackageName, runUpgrade } from "./cli-meta.js";
|
|
46
47
|
import { nativeFallbackNotice } from "./graph/native.js";
|
|
@@ -52,13 +53,17 @@ import { costLabel, listNotes, noteName, notePlace, noteTargets, readingTokens,
|
|
|
52
53
|
import { findLearning, liveLearnings } from "./notes/learning-fields.js";
|
|
53
54
|
import { aboutTerms, currentSessionCost } from "./notes/session-cost.js";
|
|
54
55
|
import { beginPastRead, finishPastRead } from "./notes/cold-start.js";
|
|
56
|
+
import { skippedSkillLines } from "./skills/found-skill.js";
|
|
55
57
|
import { anchoredReviews, beginReviewRead, finishReviewRead } from "./notes/pr-reviews.js";
|
|
56
58
|
import { finishMemoryRead, memoryCandidates, offeredBefore } from "./notes/memory-notes.js";
|
|
59
|
+
import { finishPair, PairRun, validPairCode } from "./cloud/pair.js";
|
|
57
60
|
import { currentBranch, noteAuthor, teammatesOn } from "./notes/git-facts.js";
|
|
58
61
|
import { gateNote, namesRepoSymbol, symbolCandidates, trackedFiles } from "./notes/note-gate.js";
|
|
59
62
|
import { confirm, fold, getSkill, learn, listSkills, publish, skillForAgent, skillName, skillStatus } from "./skills/skills.js";
|
|
63
|
+
import { recordLookup } from "./cloud/lookup-activity.js";
|
|
60
64
|
import { clearPending, cloudLines, loginLink, sessionKey, waitForConnect } from "./cloud/nudge.js";
|
|
61
|
-
import { addRepo, clearCloud, cloudEnabled, fetchMe, fetchTeam, isError, readCloud, writeCloud } from "./cloud/workspace.js";
|
|
65
|
+
import { addRepo, clearCloud, cloudEnabled, fetchMe, fetchTeam, isError, readCloud, trailUrl, writeCloud } from "./cloud/workspace.js";
|
|
66
|
+
import { claimConnectCode, connectAgain, offlineLine, learningsSummary, machineName, normalizeCode, OnboardingReporter, repoRef, teammatesChecked, teammatesFromGit, tokensOnOneLookup, } from "./cloud/onboarding.js";
|
|
62
67
|
import { inWorkspace, maybeSyncInBackground, recordActivity, runSyncChild, syncRepo } from "./cloud/workspace-sync.js";
|
|
63
68
|
import { checkLocally } from "./check/local-check.js";
|
|
64
69
|
import { formatOverlap, maybeRefreshBranches, overlapsWith, pushedWhen, readBranchCache, refreshBranches } from "./notes/branches.js";
|
|
@@ -307,6 +312,14 @@ program
|
|
|
307
312
|
.action(async () => {
|
|
308
313
|
await waitForConnect();
|
|
309
314
|
});
|
|
315
|
+
program
|
|
316
|
+
.command("_trail-pair", { hidden: true })
|
|
317
|
+
.description("internal: after `init --pair`, wait for the connect and the review in the browser, then upload the repo's learnings")
|
|
318
|
+
.argument("<state>")
|
|
319
|
+
.argument("<dir>")
|
|
320
|
+
.action(async (state, dir) => {
|
|
321
|
+
await finishPair(state, resolve(dir));
|
|
322
|
+
});
|
|
310
323
|
program
|
|
311
324
|
.command("_update-check", { hidden: true })
|
|
312
325
|
.description("internal: refresh the cached latest-version answer")
|
|
@@ -622,39 +635,27 @@ grouped(program.command("build"), GROUP.setup)
|
|
|
622
635
|
}
|
|
623
636
|
}
|
|
624
637
|
});
|
|
625
|
-
/** The file part of a hit's `file:Lx-Ly` pointer. */
|
|
626
|
-
function pointerFile(pointer) {
|
|
627
|
-
return pointer.replace(/:L\d+(-L?\d+)?$/, "");
|
|
628
|
-
}
|
|
629
638
|
/**
|
|
630
639
|
* After `ask`, under trail: which shown learnings are a teammate's, and the
|
|
631
|
-
*
|
|
632
|
-
* reuse
|
|
633
|
-
* current. Spawns no git itself. Teammates' branches come up after an edit
|
|
640
|
+
* lookup recorded (the learnings shown are a use, which is what the team page
|
|
641
|
+
* counts as reuse; the tokens saved ride along). Then the background upkeep
|
|
642
|
+
* that keeps branches and the workspace current. Spawns no git itself. Teammates' branches come up after an edit
|
|
634
643
|
* instead, once there's a function to compare (notes/edit-overlap.ts).
|
|
635
644
|
*/
|
|
636
645
|
function afterAsk(r, repo) {
|
|
646
|
+
// Every lookup is reported, not only ones that showed a learning: the tokens
|
|
647
|
+
// the map saved are what the team page's running total counts. A no-op unless
|
|
648
|
+
// this machine is connected and the repo is the workspace's.
|
|
649
|
+
recordLookup(r, repo);
|
|
637
650
|
if (!r.notesChecked)
|
|
638
651
|
return;
|
|
639
652
|
rememberRepo(repo);
|
|
640
653
|
maybeRefreshBranches(repo);
|
|
641
654
|
const me = noteAuthor(repo);
|
|
642
|
-
const files = [...new Set(r.hits.map((h) => pointerFile(h.pointer)))];
|
|
643
655
|
const shown = r.notes ?? [];
|
|
644
656
|
if (shown.length) {
|
|
645
657
|
for (const h of shown)
|
|
646
658
|
h.note.teammate = !!h.note.author && !!me && h.note.author !== me;
|
|
647
|
-
recordActivity({
|
|
648
|
-
repo: repoPlace(repo).key,
|
|
649
|
-
kind: "search",
|
|
650
|
-
asker: me,
|
|
651
|
-
session: sessionKey(repo) ?? `${me}-${new Date().toISOString().slice(0, 10)}`,
|
|
652
|
-
query: r.query,
|
|
653
|
-
files,
|
|
654
|
-
shown_paths: shown.map((h) => noteName(h.note)),
|
|
655
|
-
shown_authors: shown.map((h) => h.note.author),
|
|
656
|
-
at: new Date().toISOString(),
|
|
657
|
-
});
|
|
658
659
|
const saved = shown.reduce((sum, h) => sum + savedByNote(h.note), 0);
|
|
659
660
|
track("learning_reused", { teammate: String(shown.some((h) => h.note.teammate)), saved_tokens_bucket: savedTokensBucket(saved) }, { repo });
|
|
660
661
|
}
|
|
@@ -853,9 +854,14 @@ program
|
|
|
853
854
|
.command("mcp", { hidden: TRAIL })
|
|
854
855
|
.description("Serve the graph over MCP (stdio) — exposes graft_find_code, graft_trace_calls, graft_find_all, graft_file_api, graft_repo_map and graft_check_freshness as tools")
|
|
855
856
|
.argument(...DIR_ARG)
|
|
856
|
-
.
|
|
857
|
-
|
|
857
|
+
.option("--brains", "serve only the connected Trail workspace's brain tools (what Claude Code gets after init --connect)")
|
|
858
|
+
.action(async (dirArg, opts) => {
|
|
858
859
|
const { startMcpServer } = await import("./mcp/server.js");
|
|
860
|
+
if (opts.brains) {
|
|
861
|
+
startMcpServer(process.cwd(), undefined, currentVersion, { brainsOnly: true });
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
const dir = noteQuery(queryRoot(dirArg));
|
|
859
865
|
const globalOpts = program.opts();
|
|
860
866
|
startMcpServer(dir, globalOpts.dir, currentVersion);
|
|
861
867
|
});
|
|
@@ -1172,8 +1178,19 @@ grouped(program.command("init"), GROUP.setup)
|
|
|
1172
1178
|
.option("-y, --yes", "skip the picker and wire every detected agent (the pre-0.8 default)")
|
|
1173
1179
|
.option("--no-global", "skip writes outside this repo (the ~/.codex/ config + hooks)")
|
|
1174
1180
|
.option("--verbose", "print every file written, the graph build's own output and the closing banner")
|
|
1181
|
+
.option("--connect <code>", "connect this machine to your Trail workspace with the one-time code from team.trailhq.com, and send it a summary of this repo (titles, counts and names; never code)")
|
|
1182
|
+
.option("--pair <code>", "the pair code from Trail's onboarding page: that page shows this run live, then you review what it found")
|
|
1183
|
+
.option("--server <url>", "the Trail that gave the code (default: Trail cloud, https://team.trailhq.com)")
|
|
1175
1184
|
.action(async (dir, opts) => {
|
|
1176
|
-
|
|
1185
|
+
if (opts.connect !== undefined && opts.pair !== undefined) {
|
|
1186
|
+
console.error("✗ --connect and --pair are two ways in: use the one your Trail page gave you");
|
|
1187
|
+
process.exitCode = 1;
|
|
1188
|
+
return;
|
|
1189
|
+
}
|
|
1190
|
+
if (opts.connect !== undefined)
|
|
1191
|
+
await runConnectInit(dir, opts);
|
|
1192
|
+
else
|
|
1193
|
+
await runInitCommand(dir, opts);
|
|
1177
1194
|
});
|
|
1178
1195
|
/** Everything on stdin, or "" when nothing is piped in. */
|
|
1179
1196
|
async function readStdin() {
|
|
@@ -1334,19 +1351,58 @@ function printLines(lines) {
|
|
|
1334
1351
|
if (lines.length)
|
|
1335
1352
|
console.log(`\n${lines.join("\n")}`);
|
|
1336
1353
|
}
|
|
1354
|
+
/**
|
|
1355
|
+
* `--server <url>` on `init --connect` and `--pair`: the Trail that gave the
|
|
1356
|
+
* code, kept for the rest of this run as TRAIL_URL. False, after saying why,
|
|
1357
|
+
* when it isn't a URL.
|
|
1358
|
+
*/
|
|
1359
|
+
function useServerOption(raw) {
|
|
1360
|
+
const server = raw?.trim().replace(/\/+$/, "");
|
|
1361
|
+
if (!server)
|
|
1362
|
+
return true;
|
|
1363
|
+
if (!/^https?:\/\//.test(server)) {
|
|
1364
|
+
console.error("✗ --server takes a URL, like https://dev.trailhq.com");
|
|
1365
|
+
process.exitCode = 1;
|
|
1366
|
+
return false;
|
|
1367
|
+
}
|
|
1368
|
+
process.env.TRAIL_URL = server;
|
|
1369
|
+
return true;
|
|
1370
|
+
}
|
|
1371
|
+
/**
|
|
1372
|
+
* What `init --pair` hears from init, as the onboarding page's steps: the map
|
|
1373
|
+
* is done when `mapped` fires, the past sessions when `learned` does. Nothing
|
|
1374
|
+
* to say for a run that read no sessions (that step is already marked).
|
|
1375
|
+
*/
|
|
1376
|
+
function pairProgress(pair) {
|
|
1377
|
+
return {
|
|
1378
|
+
mapped: (m) => pair.phase("files", "done", m.files ? `${m.files.toLocaleString("en-US")} files` : "", m.files ? `Mapped ${m.files.toLocaleString("en-US")} files` : "Mapped the code"),
|
|
1379
|
+
learned: (l) => {
|
|
1380
|
+
if (l.sessions <= 0)
|
|
1381
|
+
return;
|
|
1382
|
+
// The PR reviews' learnings come with `sessions: 0`; the rest were said in past sessions.
|
|
1383
|
+
const fromSessions = l.notes.filter((n) => n.sessions !== 0).length;
|
|
1384
|
+
pair.phase("decisions", "done", `${l.sessions} sessions`, `Read ${l.sessions} past sessions: ${fromSessions} thing${fromSessions === 1 ? "" : "s"} you told Claude more than once`);
|
|
1385
|
+
},
|
|
1386
|
+
};
|
|
1387
|
+
}
|
|
1337
1388
|
/** Repo-relative with forward slashes, for printing. */
|
|
1338
1389
|
function shown(repo, path) {
|
|
1339
1390
|
return relative(repo, path).split("\\").join("/");
|
|
1340
1391
|
}
|
|
1392
|
+
/** Agents init knows by another id: both read AGENTS.md. */
|
|
1393
|
+
const AGENT_ALIASES = { codex: "agents", opencode: "agents" };
|
|
1341
1394
|
/** `graft init`. */
|
|
1342
|
-
async function runInitCommand(dir, opts) {
|
|
1395
|
+
async function runInitCommand(dir, opts, progress) {
|
|
1343
1396
|
if (opts.listAgents) {
|
|
1344
1397
|
for (const id of [...hostIds(), "claude"])
|
|
1345
1398
|
console.log(id);
|
|
1346
1399
|
return null;
|
|
1347
1400
|
}
|
|
1348
1401
|
const repo = resolve(dir);
|
|
1349
|
-
|
|
1402
|
+
// Codex and OpenCode read AGENTS.md: `--agents codex` means that wiring.
|
|
1403
|
+
// The name as given is kept for Trail's onboarding page.
|
|
1404
|
+
const asked = Array.isArray(opts.agents) ? opts.agents : undefined;
|
|
1405
|
+
const explicit = asked ? [...new Set(asked.map((id) => AGENT_ALIASES[id] ?? id))] : undefined;
|
|
1350
1406
|
// Checked before anything is written: run from the home folder, init wired
|
|
1351
1407
|
// it, mapped every code file under it, then said to commit.
|
|
1352
1408
|
const refusal = homeFolderRefusal(repo);
|
|
@@ -1426,6 +1482,26 @@ async function runInitCommand(dir, opts) {
|
|
|
1426
1482
|
console.error("· no agents selected — nothing written");
|
|
1427
1483
|
return null;
|
|
1428
1484
|
}
|
|
1485
|
+
// With --pair, Trail's onboarding page is waiting on this run: tell it
|
|
1486
|
+
// first, so the person can sign up while the rest of init runs.
|
|
1487
|
+
let pair = null;
|
|
1488
|
+
if (opts.pair !== undefined) {
|
|
1489
|
+
if (!useServerOption(opts.server))
|
|
1490
|
+
return null;
|
|
1491
|
+
if (!validPairCode(opts.pair)) {
|
|
1492
|
+
console.error(`✗ --pair takes the code from Trail's onboarding page, got "${opts.pair}"`);
|
|
1493
|
+
process.exitCode = 1;
|
|
1494
|
+
return null;
|
|
1495
|
+
}
|
|
1496
|
+
const started = await PairRun.start(repo, opts.pair, { agent: asked?.[0] ?? ids[0], version: currentVersion });
|
|
1497
|
+
if ("error" in started) {
|
|
1498
|
+
console.error(`⚠ couldn't tell Trail about this run (${started.error}); setting up here anyway`);
|
|
1499
|
+
}
|
|
1500
|
+
else {
|
|
1501
|
+
pair = started;
|
|
1502
|
+
console.error(`· Trail's page is following along · ${started.url}`);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1429
1505
|
const wantClaude = ids.includes("claude");
|
|
1430
1506
|
const cliPath = fileURLToPath(import.meta.url);
|
|
1431
1507
|
// Under trail, each repo gets its `.trail/learnings/`, committed with the
|
|
@@ -1452,6 +1528,16 @@ async function runInitCommand(dir, opts) {
|
|
|
1452
1528
|
const reviewRead = TRAIL && wantClaude ? beginReviewRead(repo) : null;
|
|
1453
1529
|
if (reviewRead)
|
|
1454
1530
|
console.error("· reading review comments on this repo's merged PRs for what reviewers keep flagging");
|
|
1531
|
+
if (pair) {
|
|
1532
|
+
if (pastRead)
|
|
1533
|
+
pair.phase("decisions", "running", "", `Reading ${pastRead.sessions} past Claude sessions`);
|
|
1534
|
+
else
|
|
1535
|
+
pair.phase("decisions", "done", "none here");
|
|
1536
|
+
if (reviewRead)
|
|
1537
|
+
pair.phase("prs", "running", "", "Reading review comments on merged PRs");
|
|
1538
|
+
else
|
|
1539
|
+
pair.phase("prs", "done", "none here");
|
|
1540
|
+
}
|
|
1455
1541
|
if (children.length)
|
|
1456
1542
|
console.error(`· workspace: wiring ${repo} and ${children.length} child repo(s) — ${children.join(", ")}`);
|
|
1457
1543
|
// Today's output, file by file, behind --verbose. Everything else gets one
|
|
@@ -1467,6 +1553,7 @@ async function runInitCommand(dir, opts) {
|
|
|
1467
1553
|
// the workspace build, so it covers every child.
|
|
1468
1554
|
let graphLine = null;
|
|
1469
1555
|
if (!verbose) {
|
|
1556
|
+
pair?.phase("files", "running", "", "Mapping the code");
|
|
1470
1557
|
const res = await buildGraphWithProgress(repo, { build: opts.build, cliPath });
|
|
1471
1558
|
for (const m of res.messages)
|
|
1472
1559
|
console.error(m);
|
|
@@ -1491,6 +1578,25 @@ async function runInitCommand(dir, opts) {
|
|
|
1491
1578
|
graphLine = `· skipped the graph build — run ${cmd("graft build")}`;
|
|
1492
1579
|
}
|
|
1493
1580
|
}
|
|
1581
|
+
// --pair hears the same stages --connect does; only the ones InitProgress
|
|
1582
|
+
// has no slot for (a read starting, the PR read, nothing to read) stay inline.
|
|
1583
|
+
const report = pair ? pairProgress(pair) : progress;
|
|
1584
|
+
if (report?.mapped) {
|
|
1585
|
+
const g = loadGraphCached(contextDirFor(repo, children.length ? undefined : program.opts().dir));
|
|
1586
|
+
report.mapped({
|
|
1587
|
+
nodes: g?.meta.nodeCount ?? 0,
|
|
1588
|
+
edges: g?.meta.edgeCount ?? 0,
|
|
1589
|
+
files: g ? g.nodes.filter((n) => n.kind === "file").length : 0,
|
|
1590
|
+
});
|
|
1591
|
+
}
|
|
1592
|
+
// With --pair, one lookup measured against reading the files whole: the
|
|
1593
|
+
// page's token step. It needs the map, so it follows the build.
|
|
1594
|
+
let tokens = null;
|
|
1595
|
+
if (pair) {
|
|
1596
|
+
pair.phase("tokens", "running", "", "Measuring one lookup against reading the files");
|
|
1597
|
+
tokens = tokensOnOneLookup(repo, { contextDir: program.opts().dir });
|
|
1598
|
+
pair.tokensDone(tokens);
|
|
1599
|
+
}
|
|
1494
1600
|
if (!verbose) {
|
|
1495
1601
|
// Warnings and removals in full, whatever else is folded.
|
|
1496
1602
|
const removed = [...new Set(reports.flatMap((r) => r.retracted))];
|
|
@@ -1512,6 +1618,7 @@ async function runInitCommand(dir, opts) {
|
|
|
1512
1618
|
// what reviewers kept flagging on merged PRs, and Claude Code's notes about
|
|
1513
1619
|
// the repo on this machine. What the person kept telling Claude is theirs.
|
|
1514
1620
|
let learnedNow = false;
|
|
1621
|
+
let skillsWritten = [];
|
|
1515
1622
|
let teamSaved = 0;
|
|
1516
1623
|
const memory = TRAIL && wantClaude ? memoryCandidates(repo, { offered: offeredBefore(repo) }) : [];
|
|
1517
1624
|
if (TRAIL && (pastRead || reviewRead || memory.length)) {
|
|
@@ -1525,7 +1632,7 @@ async function runInitCommand(dir, opts) {
|
|
|
1525
1632
|
// first and ticked, their own unticked. A scripted run, or one with
|
|
1526
1633
|
// --yes, keeps the team's and what they told Claude. Cancelling saves
|
|
1527
1634
|
// none, and the next init asks again.
|
|
1528
|
-
const picked = process.stdin.isTTY && process.stderr.isTTY && !opts.yes && fromReviews.length + memory.length + fromSessions.length
|
|
1635
|
+
const picked = process.stdin.isTTY && process.stderr.isTTY && !opts.yes && !pair && fromReviews.length + memory.length + fromSessions.length
|
|
1529
1636
|
? await pickLearnings([
|
|
1530
1637
|
...fromReviews.map((f) => ({ title: f.title, forTeam: true, prs: f.prs })),
|
|
1531
1638
|
...memory.map((c) => ({ title: c.title, forTeam: c.forTeam, memory: true })),
|
|
@@ -1537,10 +1644,13 @@ async function runInitCommand(dir, opts) {
|
|
|
1537
1644
|
? undefined
|
|
1538
1645
|
: async (found) => picked && picked.filter((i) => i >= from && i < from + found.length).map((i) => found[i - from]);
|
|
1539
1646
|
const learned = [];
|
|
1647
|
+
const learnedFrom = [];
|
|
1648
|
+
let sessionsRead = 0;
|
|
1540
1649
|
// Reviews first: which of them are offered depends on the learnings already saved.
|
|
1541
1650
|
if (reviewRead) {
|
|
1542
1651
|
const { result, saved, kept, cancelled } = await finishReviewRead(repo, reviewRead, keepFrom(0));
|
|
1543
1652
|
const offered = fromReviews.length;
|
|
1653
|
+
pair?.phase("prs", "done", `${result.prs} PRs`, `Read ${result.prs} merged PRs: ${saved.length} thing${saved.length === 1 ? "" : "s"} reviewers made authors change`);
|
|
1544
1654
|
if (saved.length) {
|
|
1545
1655
|
const n = saved.length;
|
|
1546
1656
|
const what = n < offered ? `kept ${n} of the ${offered} things` : `learned ${n} thing${n === 1 ? "" : "s"}`;
|
|
@@ -1558,6 +1668,9 @@ async function runInitCommand(dir, opts) {
|
|
|
1558
1668
|
console.error(`· couldn't read PR reviews this time; ${cmd("graft init")} again tries again`);
|
|
1559
1669
|
}
|
|
1560
1670
|
learned.push(...saved);
|
|
1671
|
+
// Not said in past sessions: `sessions: 0` keeps them out of the page's session count.
|
|
1672
|
+
for (const note of saved)
|
|
1673
|
+
learnedFrom.push({ note, sessions: 0 });
|
|
1561
1674
|
}
|
|
1562
1675
|
if (memory.length) {
|
|
1563
1676
|
const { saved, cancelled } = await finishMemoryRead(repo, memory, keepFrom(fromReviews.length));
|
|
@@ -1570,9 +1683,21 @@ async function runInitCommand(dir, opts) {
|
|
|
1570
1683
|
console.error(`· saved none of the ${memory.length} notes your Claude keeps about this repo; ${cmd("graft init")} again asks again`);
|
|
1571
1684
|
}
|
|
1572
1685
|
learned.push(...saved);
|
|
1686
|
+
for (const note of saved)
|
|
1687
|
+
learnedFrom.push({ note, sessions: 0 });
|
|
1573
1688
|
}
|
|
1574
1689
|
if (pastRead) {
|
|
1575
|
-
const { result, saved, kept, cancelled } = await finishPastRead(repo, pastRead, keepFrom(fromReviews.length + memory.length));
|
|
1690
|
+
const { result, saved, kept, skills, cancelled } = await finishPastRead(repo, pastRead, keepFrom(fromReviews.length + memory.length));
|
|
1691
|
+
sessionsRead = result.read ?? 0;
|
|
1692
|
+
skillsWritten = skills;
|
|
1693
|
+
for (const { skill, path } of skills) {
|
|
1694
|
+
console.error(`✓ wrote a skill from a procedure you walked Claude through more than once: ${skill.title}`);
|
|
1695
|
+
console.error(` ${skill.for === "team" ? "for your team" : "just for you "} · ${path}`);
|
|
1696
|
+
}
|
|
1697
|
+
if (!cancelled)
|
|
1698
|
+
for (const line of skippedSkillLines(repo, result.skills, skills))
|
|
1699
|
+
console.error(line);
|
|
1700
|
+
saved.forEach((note, i) => learnedFrom.push({ note, sessions: kept[i]?.sessions.length }));
|
|
1576
1701
|
const offered = result.findings.length;
|
|
1577
1702
|
if (saved.length) {
|
|
1578
1703
|
const n = saved.length;
|
|
@@ -1598,12 +1723,16 @@ async function runInitCommand(dir, opts) {
|
|
|
1598
1723
|
}
|
|
1599
1724
|
learnedNow = learned.length > 0;
|
|
1600
1725
|
teamSaved = learned.filter((s) => s.scope === "repo").length;
|
|
1726
|
+
report?.learned?.({ notes: learnedFrom, sessions: sessionsRead });
|
|
1601
1727
|
if (learnedNow) {
|
|
1602
1728
|
console.error("· Claude follows them from your next session");
|
|
1603
1729
|
if (teamSaved)
|
|
1604
1730
|
console.error(commitLines({}, teammatesOn(repo), "repo").uncommitted);
|
|
1605
1731
|
}
|
|
1606
1732
|
}
|
|
1733
|
+
// Nothing read this run (already read once, or not Claude Code): the page still gets its stage.
|
|
1734
|
+
if (!(TRAIL && (pastRead || reviewRead || memory.length)))
|
|
1735
|
+
report?.learned?.({ notes: [], sessions: 0 });
|
|
1607
1736
|
if (TRAIL && !learnedNow) {
|
|
1608
1737
|
const home = notesHome.get(repo);
|
|
1609
1738
|
if (home) {
|
|
@@ -1660,14 +1789,130 @@ async function runInitCommand(dir, opts) {
|
|
|
1660
1789
|
nodes: graphs.reduce((n, g) => n + g.meta.nodeCount, 0),
|
|
1661
1790
|
edges: graphs.reduce((n, g) => n + g.meta.edgeCount, 0),
|
|
1662
1791
|
}));
|
|
1792
|
+
// Hand what was found to the review page, and leave a child waiting for
|
|
1793
|
+
// the person to connect and review there.
|
|
1794
|
+
if (pair) {
|
|
1795
|
+
// Teammates' branches on this person's files, checked against the
|
|
1796
|
+
// learnings just saved and the repo's own: synchronous, so the finding
|
|
1797
|
+
// exists before the page is told the read is done.
|
|
1798
|
+
pair.phase("team", "running", "", "Checking your team's branches");
|
|
1799
|
+
const teamNotes = listNotes(repo, { branches: false }).filter((n) => n.scope === "repo" && !n.ref);
|
|
1800
|
+
// No remote (or no default branch) means nothing was checked: `teammates`
|
|
1801
|
+
// is left out, since an empty list would say "checked, none".
|
|
1802
|
+
const teammates = teammatesChecked(repo, { learnings: teamNotes });
|
|
1803
|
+
pair.teamDone(teammates);
|
|
1804
|
+
pair.findings({ tokens, sessions: pastRead?.sessions, teammates });
|
|
1805
|
+
await pair.finish(repo, skillsWritten);
|
|
1806
|
+
pair.handOff(repo);
|
|
1807
|
+
console.error(`✓ Trail has what it found · review it in the browser: ${pair.url}`);
|
|
1808
|
+
if (!process.stdout.isTTY)
|
|
1809
|
+
console.error(`[trail] Tell the user, in one line: their Trail page has moved on; review what Trail found there. If it isn't open, the link is ${pair.url}`);
|
|
1810
|
+
}
|
|
1663
1811
|
// Run by an agent, not a person: the last line tells it to ask about the
|
|
1664
1812
|
// commit, since the person never saw the picker and Claude Code folds the rest.
|
|
1665
|
-
|
|
1813
|
+
// With --pair the person reviews them on the Trail page first, so no ask here.
|
|
1814
|
+
if (teamSaved && !pair && !process.stderr.isTTY)
|
|
1666
1815
|
console.error(`→ ${teamSaved} team learning${teamSaved === 1 ? "" : "s"} in ${LEARNINGS_DIR}/ ${teamSaved === 1 ? "isn't" : "aren't"} committed yet. Ask the user: "Commit ${teamSaved === 1 ? "it" : `the ${teamSaved}`} so your teammates' Claude starts from ${teamSaved === 1 ? "it" : "them"}? (yes / no)"`);
|
|
1667
1816
|
// Sorted so `claude,cursor` and `cursor,claude` aggregate as one value.
|
|
1668
1817
|
track("init_completed", { agents: [...ids].sort().join(","), consent: consent === undefined ? "unasked" : String(consent) }, { repo });
|
|
1669
1818
|
return { ids };
|
|
1670
1819
|
}
|
|
1820
|
+
/**
|
|
1821
|
+
* `trail init --connect <CODE>`: the onboarding on team.trailhq.com. Claims the
|
|
1822
|
+
* one-time code (a wrong or spent one stops here, before anything is written),
|
|
1823
|
+
* saves the workspace token where `trail login` keeps it, then runs init as
|
|
1824
|
+
* usual while the page ticks off connected, mapped and learned. At the end,
|
|
1825
|
+
* one summary of the repo goes up (a lookup's tokens saved, the learnings'
|
|
1826
|
+
* titles, teammates' branches from git: never code, diffs or session text),
|
|
1827
|
+
* then `done`. Offline, init still sets the repo up and says how to connect.
|
|
1828
|
+
*/
|
|
1829
|
+
async function runConnectInit(dir, opts) {
|
|
1830
|
+
if (opts.listAgents || opts.dryRun) {
|
|
1831
|
+
if (opts.dryRun)
|
|
1832
|
+
console.error("· --dry-run: not connecting");
|
|
1833
|
+
await runInitCommand(dir, opts);
|
|
1834
|
+
return;
|
|
1835
|
+
}
|
|
1836
|
+
const repo = resolve(dir);
|
|
1837
|
+
if (!useServerOption(opts.server))
|
|
1838
|
+
return;
|
|
1839
|
+
const base = trailUrl();
|
|
1840
|
+
const code = normalizeCode(opts.connect ?? "");
|
|
1841
|
+
if (!code) {
|
|
1842
|
+
console.error(`✗ "${opts.connect ?? ""}" isn't a Trail code · it looks like TRL-7F2A-K9QD, from ${base}/welcome/code`);
|
|
1843
|
+
process.exitCode = 1;
|
|
1844
|
+
return;
|
|
1845
|
+
}
|
|
1846
|
+
const ref = repoRef(repo);
|
|
1847
|
+
const machine = machineName();
|
|
1848
|
+
const got = await claimConnectCode(base, code, { machine, repo: ref });
|
|
1849
|
+
const cloud = "cloud" in got ? got.cloud : null;
|
|
1850
|
+
if ("cloud" in got) {
|
|
1851
|
+
const cloud = got.cloud;
|
|
1852
|
+
writeCloud(cloud);
|
|
1853
|
+
// A sign-in link out from before is moot now.
|
|
1854
|
+
clearPending();
|
|
1855
|
+
console.error(`✓ connected to workspace ${cloud.workspace.name}`);
|
|
1856
|
+
track("brain_signup_settled", { outcome: "linked", mode: "connect", duration_bucket: durationBucket(0) }, { repo });
|
|
1857
|
+
}
|
|
1858
|
+
else if (got.reason === "invalid") {
|
|
1859
|
+
console.error(`✗ ${got.error} · get a new code at ${base}/welcome/code`);
|
|
1860
|
+
process.exitCode = 1;
|
|
1861
|
+
return;
|
|
1862
|
+
}
|
|
1863
|
+
else {
|
|
1864
|
+
console.error(offlineLine(got.error, base, code, cmd("graft init")));
|
|
1865
|
+
}
|
|
1866
|
+
const reporter = cloud ? new OnboardingReporter(cloud, ref, { machine }) : null;
|
|
1867
|
+
void reporter?.stage("connected");
|
|
1868
|
+
// What init learned this run, kept for the summary.
|
|
1869
|
+
const heard = { notes: [], sessions: 0 };
|
|
1870
|
+
const progress = reporter
|
|
1871
|
+
? {
|
|
1872
|
+
mapped: (m) => void reporter.stage("mapped", m),
|
|
1873
|
+
learned: (l) => {
|
|
1874
|
+
Object.assign(heard, l);
|
|
1875
|
+
const team = learningsSummary(repo, l.notes);
|
|
1876
|
+
void reporter.stage("learned", { learnings: team.length, sessions: l.sessions || Math.max(0, ...team.map((t) => t.sessions)) });
|
|
1877
|
+
},
|
|
1878
|
+
}
|
|
1879
|
+
: undefined;
|
|
1880
|
+
// The page's command is pasted into a terminal, but an agent may run it for
|
|
1881
|
+
// them: with no terminal to pick in, wire the agents this machine has.
|
|
1882
|
+
const interactive = process.stdin.isTTY && process.stderr.isTTY;
|
|
1883
|
+
const res = await runInitCommand(dir, interactive ? opts : { ...opts, yes: true }, progress);
|
|
1884
|
+
if (!reporter || !cloud)
|
|
1885
|
+
return;
|
|
1886
|
+
if (!res) {
|
|
1887
|
+
await reporter.flush();
|
|
1888
|
+
return;
|
|
1889
|
+
}
|
|
1890
|
+
// What Trail found, for the page: route B, summaries only.
|
|
1891
|
+
const learnings = learningsSummary(repo, heard.notes);
|
|
1892
|
+
const sessions = heard.sessions || Math.max(0, ...learnings.map((l) => l.sessions));
|
|
1893
|
+
const tokens = tokensOnOneLookup(repo, { contextDir: program.opts().dir });
|
|
1894
|
+
const teamNotes = listNotes(repo, { branches: false }).filter((n) => n.scope === "repo" && !n.ref);
|
|
1895
|
+
const teammates = teammatesFromGit(repo, { learnings: teamNotes });
|
|
1896
|
+
const sent = await reporter.summary({ tokens, ...(sessions ? { sessions } : {}), learnings, teammates });
|
|
1897
|
+
await reporter.stage("done");
|
|
1898
|
+
await reporter.flush();
|
|
1899
|
+
// Claude Code gets the workspace's brains through one user-level `trail` entry.
|
|
1900
|
+
const brainsEntry = res.ids.includes("claude") && opts.global !== false ? installBrainsServer(homedir()) : null;
|
|
1901
|
+
if (sent) {
|
|
1902
|
+
const parts = [
|
|
1903
|
+
tokens ? `one lookup saved ${tokens.pct}% of the tokens` : null,
|
|
1904
|
+
`${learnings.length} learning${learnings.length === 1 ? "" : "s"}`,
|
|
1905
|
+
`${teammates.length} teammate branch${teammates.length === 1 ? "" : "es"} on your files`,
|
|
1906
|
+
].filter(Boolean);
|
|
1907
|
+
console.error(`✓ sent ${cloud.workspace.name} a summary: ${parts.join(", ")} · titles, counts and names only, no code`);
|
|
1908
|
+
console.error(`· see what Trail found: ${base}/welcome/code/found`);
|
|
1909
|
+
}
|
|
1910
|
+
else {
|
|
1911
|
+
console.error(`· couldn't send the summary to Trail this time · with a new code from ${base}/welcome/code, ${connectAgain(cmd("graft init"), "<code>", base)} sends it again`);
|
|
1912
|
+
}
|
|
1913
|
+
if (brainsEntry?.action === "created" || brainsEntry?.action === "updated")
|
|
1914
|
+
console.error(`✓ Claude Code gets your workspace's brains in every project · restart it to pick them up`);
|
|
1915
|
+
}
|
|
1671
1916
|
/** One repo's worth of `init` writes — the parent, then each workspace child. */
|
|
1672
1917
|
function wireTarget(repo, ids, ctx) {
|
|
1673
1918
|
const { home, cliPath, plan, wantClaude } = ctx;
|
|
@@ -1829,7 +2074,7 @@ function loginCommand(name = "login") {
|
|
|
1829
2074
|
return new Command(name)
|
|
1830
2075
|
.description("Connect this machine to a Trail workspace: sign in, pick the repos it gets, invite your team")
|
|
1831
2076
|
.argument("[dir]", "the repo you're in, ticked first in the picker", ".")
|
|
1832
|
-
.option("--server <url>", "a self-hosted Trail, e.g. https://trail.acme.internal (default: Trail cloud)")
|
|
2077
|
+
.option("--server <url>", "a self-hosted Trail, e.g. https://trail.acme.internal (default: Trail cloud, https://team.trailhq.com)")
|
|
1833
2078
|
.action(async (dir, opts) => {
|
|
1834
2079
|
const repo = resolve(dir);
|
|
1835
2080
|
const server = opts.server?.trim().replace(/\/+$/, "");
|
|
@@ -1869,6 +2114,7 @@ function logoutCommand(name = "logout") {
|
|
|
1869
2114
|
.action(() => {
|
|
1870
2115
|
const cloud = readCloud();
|
|
1871
2116
|
clearPending();
|
|
2117
|
+
removeBrainsServer(homedir());
|
|
1872
2118
|
if (!clearCloud()) {
|
|
1873
2119
|
console.error("· not connected to a workspace");
|
|
1874
2120
|
return;
|
|
@@ -2250,6 +2496,9 @@ function statusCommand(name = "status") {
|
|
|
2250
2496
|
if (cloudEnabled())
|
|
2251
2497
|
row("workspace", "not connected · Claude offers a link once there are learnings to share");
|
|
2252
2498
|
}
|
|
2499
|
+
else if (cloud.via === "connect") {
|
|
2500
|
+
row("workspace", `${cloud.workspace.name} · gets a summary of the repos you run ${cmd("graft init")} --connect in · ${cloud.workspace.url}`);
|
|
2501
|
+
}
|
|
2253
2502
|
else
|
|
2254
2503
|
row("workspace", `${cloud.workspace.name} · ${cloud.repos.length} repo${cloud.repos.length === 1 ? "" : "s"}${shared ? ", this one included" : `, not this one (${cmd("graft workspace add")})`} · ${cloud.workspace.url}`);
|
|
2255
2504
|
row("this week", saved > 0 ? `~${shortCount(saved)} tokens saved` : "nothing saved yet");
|