@uniqbit/mate-core 0.18.5 → 1.0.0-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/claude-plugin/hooks/companion-instructions.mjs +9 -0
- package/claude-plugin/hooks/hooks.json +12 -2
- package/package.json +10 -2
- package/src/brand/art.generated.ts +69 -0
- package/src/brand/index.ts +12 -0
- package/src/brand/palette.ts +19 -0
- package/src/brand/svg.generated.ts +8 -0
- package/src/brand/terminal.ts +83 -0
- package/src/brand/types.ts +33 -0
- package/src/cli/commands/artifact/artifact.ts +8 -0
- package/src/cli/commands/artifact/delivery/archive.ts +117 -0
- package/src/cli/commands/artifact/delivery/branch-flags.ts +55 -0
- package/src/cli/commands/artifact/delivery/environment.ts +104 -0
- package/src/cli/commands/artifact/delivery/link.ts +154 -0
- package/src/cli/commands/artifact/delivery/output.ts +58 -0
- package/src/cli/commands/artifact/finish/command.ts +33 -3
- package/src/cli/commands/artifact/finish/engine.ts +47 -3
- package/src/cli/commands/artifact/finish/finisher.ts +10 -0
- package/src/cli/commands/artifact/finish/openspec.ts +177 -138
- package/src/cli/commands/artifact/finish/secret-scan.ts +43 -0
- package/src/cli/commands/artifact/pending/command.ts +31 -3
- package/src/cli/commands/artifact/pending/discovery.ts +21 -57
- package/src/cli/commands/cap/graphify.ts +52 -3
- package/src/cli/commands/cap/index-cmd.ts +8 -1
- package/src/cli/commands/cap/openspec.ts +13 -25
- package/src/cli/commands/companion/open.ts +56 -39
- package/src/cli/commands/companion/update.ts +75 -42
- package/src/cli/commands/doctor.ts +176 -3
- package/src/cli/commands/plugin/install.ts +9 -4
- package/src/cli/commands/plugin/plugin.ts +3 -2
- package/src/cli/commands/report/adapter.ts +11 -2
- package/src/cli/commands/report/contract.ts +21 -0
- package/src/cli/commands/report/highlight.ts +34 -4
- package/src/cli/commands/report/markdown.ts +110 -0
- package/src/cli/commands/report/palette.ts +118 -0
- package/src/cli/commands/report/renderer.ts +456 -153
- package/src/cli/commands/report/types.ts +16 -0
- package/src/cli/commands/setup.ts +7 -15
- package/src/cli/commands/studio/client-asset.ts +16 -0
- package/src/cli/commands/studio/openspec-cli.ts +10 -58
- package/src/cli/commands/studio/routes.ts +2 -0
- package/src/cli/commands/studio/selection.ts +19 -1
- package/src/cli/commands/studio/server.ts +42 -1
- package/src/cli/commands/studio/views/client.ts +6 -616
- package/src/cli/commands/studio/views/dashboard/changes.tsx +5 -10
- package/src/cli/commands/studio/views/document.tsx +137 -69
- package/src/cli/commands/studio/views/markdown.tsx +250 -0
- package/src/cli/commands/studio/views/palette.ts +134 -0
- package/src/cli/commands/studio/views/reports/index.tsx +2 -7
- package/src/cli/commands/studio/views/skills/index.tsx +43 -62
- package/src/cli/commands/studio/views/specs/index.tsx +7 -15
- package/src/cli/commands/studio/views/studio-client/actions.ts +51 -0
- package/src/cli/commands/studio/views/studio-client/companion.ts +13 -0
- package/src/cli/commands/studio/views/studio-client/index.ts +32 -0
- package/src/cli/commands/studio/views/studio-client/keys.ts +3 -0
- package/src/cli/commands/studio/views/studio-client/main.ts +3 -0
- package/src/cli/commands/studio/views/studio-client/page.ts +146 -0
- package/src/cli/commands/studio/views/studio-client/panels.ts +57 -0
- package/src/cli/commands/studio/views/studio-client/reports.ts +122 -0
- package/src/cli/commands/studio/views/studio-client/theme.ts +63 -0
- package/src/cli/commands/studio/views/studio-client/vault-editor.ts +166 -0
- package/src/cli/commands/studio/views/studio-client/vault-pane.ts +202 -0
- package/src/cli/commands/studio/views/studio-client/vault-tree.ts +258 -0
- package/src/cli/commands/studio/views/studio-client.generated.ts +2 -0
- package/src/cli/commands/studio/views/styles.ts +217 -206
- package/src/cli/commands/studio/views/vault/state.ts +3 -5
- package/src/cli/commands/studio/views/workflow/delivery-path.tsx +370 -0
- package/src/cli/commands/studio/views/workflow/graph.ts +220 -0
- package/src/cli/commands/studio/views/workflow/index.tsx +2 -3
- package/src/cli/commands/studio/views/workflow/steps.ts +228 -287
- package/src/cli/commands/wrap.ts +5 -13
- package/src/cli/main.ts +4 -1
- package/src/cli/parse-flags.ts +25 -7
- package/src/cli/setup-selector.tsx +38 -162
- package/src/cli/usage.ts +4 -0
- package/src/hooks/companion-instructions.ts +190 -0
- package/src/hooks/hook-io.ts +63 -0
- package/src/hooks/session-banner.ts +21 -29
- package/src/hooks/session-guidance.ts +9 -17
- package/src/hooks/session-prepare.ts +115 -28
- package/src/hooks/validate-artifact-path.ts +82 -24
- package/src/index.ts +4 -0
- package/src/lib/change-layout.ts +154 -0
- package/src/lib/components/wizard-header.tsx +3 -1
- package/src/lib/context-mode-package.ts +24 -11
- package/src/lib/delivery/archive-change.ts +154 -0
- package/src/lib/delivery/branches.ts +108 -0
- package/src/lib/delivery/environment.ts +29 -0
- package/src/lib/delivery/forge.ts +279 -0
- package/src/lib/delivery/overlap.ts +202 -0
- package/src/lib/delivery/record-delivery.ts +196 -0
- package/src/lib/delivery/record.ts +343 -0
- package/src/lib/delivery/refresh.ts +174 -0
- package/src/lib/delivery/repository-access.ts +97 -0
- package/src/lib/delivery/stages.ts +111 -0
- package/src/lib/delivery/token.ts +58 -0
- package/src/lib/frontmatter.ts +18 -0
- package/src/lib/opencode-plugin-package.ts +5 -5
- package/src/lib/openspec-cli.ts +116 -0
- package/src/lib/openspec-scopes.ts +86 -0
- package/src/lib/orchestrator/adapters/claude-args.ts +50 -0
- package/src/lib/orchestrator/adapters/claude.ts +48 -40
- package/src/lib/orchestrator/adapters/opencode.ts +2 -0
- package/src/lib/orchestrator/editor.ts +9 -9
- package/src/lib/orchestrator/openspec-store.ts +14 -54
- package/src/lib/orchestrator/projection-claude-commands.ts +36 -0
- package/src/lib/orchestrator/projection-claude-links.ts +159 -0
- package/src/lib/orchestrator/projection-claude-skills.ts +19 -137
- package/src/lib/orchestrator/projection-entries.ts +45 -14
- package/src/lib/orchestrator/projection-runtime-documents.ts +15 -6
- package/src/lib/orchestrator/projection-types.ts +3 -0
- package/src/lib/orchestrator/refresh-working-claude-links.ts +87 -0
- package/src/lib/orchestrator/session-prepare.ts +45 -5
- package/src/lib/orchestrator/setup-compatibilities.ts +18 -75
- package/src/lib/orchestrator/types.ts +2 -2
- package/src/lib/orchestrator/wrap-pass.ts +22 -1
- package/src/lib/package-paths.ts +8 -0
- package/src/opencode/companion-hooks.ts +64 -5
- package/src/opencode/companion-policy.ts +37 -18
- package/src/opencode/projected-guidance.ts +4 -1
- package/src/opencode/session-prepare.ts +2 -1
- package/src/opencode/tui.tsx +4 -2
- package/src/runtime/artifact-refusal.ts +63 -0
- package/src/runtime/claude-delivery-plan.ts +89 -7
- package/src/runtime/commit-attribution-guard.ts +181 -0
- package/src/runtime/companion-guidance.ts +15 -3
- package/src/runtime/companion-instructions.ts +340 -0
- package/src/runtime/error-message.ts +4 -0
- package/src/runtime/index.ts +5 -0
- package/src/runtime/managed-block.ts +117 -0
- package/src/runtime/markdown-scan.ts +266 -0
- package/src/runtime/policy.ts +15 -1
- package/src/runtime/projected-flag.ts +7 -0
- package/src/runtime/projected-guidance.ts +1 -0
- package/src/runtime/runtime-document-manifest.ts +62 -11
- package/src/runtime/secret-guard.ts +148 -0
- package/src/runtime/secret-patterns.ts +164 -0
- package/src/runtime/secret-scan.ts +90 -0
- package/src/runtime/session-kind.ts +13 -0
- package/src/runtime/shell-heredoc.ts +81 -0
- package/src/runtime/wrap-state.ts +36 -2
- package/src/runtime/write-atomic.ts +64 -0
- package/src/templates/capabilities/openspec-cap/mate-minimal/schema.yaml +8 -6
- package/src/templates/capabilities/openspec-cap/mate-minimal/templates/spec.md +3 -5
- package/src/templates/capabilities/openspec-cap/mate-v1/schema.yaml +7 -9
- package/src/templates/capabilities/openspec-cap/mate-v1/templates/spec.md +3 -5
- package/src/templates/capabilities/openspec-cap/openspec-conventions.yaml +10 -12
- package/src/templates/mate-skills/THIRD-PARTY-NOTICES.md +40 -0
- package/src/templates/mate-skills/agents/mate-apply-change/SKILL.md +76 -0
- package/src/templates/mate-skills/agents/mate-apply-change/references/openspec-apply-change.md +198 -0
- package/src/templates/mate-skills/agents/mate-archive-change/SKILL.md +59 -0
- package/src/templates/mate-skills/{claude/mate-openspec-backfill → agents/mate-backfill-spec}/SKILL.md +4 -4
- package/src/templates/mate-skills/agents/mate-clarify-intent/SKILL.md +95 -0
- package/src/templates/mate-skills/agents/mate-explore-change/SKILL.md +50 -0
- package/src/templates/mate-skills/agents/mate-explore-change/references/openspec-explore.md +348 -0
- package/src/templates/mate-skills/agents/mate-grill-me/SKILL.md +3 -3
- package/src/templates/mate-skills/agents/mate-interview-me/SKILL.md +5 -5
- package/src/templates/mate-skills/agents/mate-propose-change/SKILL.md +103 -0
- package/src/templates/mate-skills/agents/mate-propose-change/references/openspec-propose.md +167 -0
- package/src/templates/mate-skills/agents/mate-propose-change/references/openspec-update-change.md +101 -0
- package/src/templates/mate-skills/{claude/mate-artifact-publish → agents/mate-publish-artifact}/SKILL.md +91 -23
- package/src/templates/mate-skills/agents/{mate-artifact-publish → mate-publish-artifact}/references/openspec.md +4 -3
- package/src/templates/mate-skills/agents/mate-show-me/SKILL.md +74 -16
- package/src/templates/mate-skills/agents/mate-simplify-code/SKILL.md +74 -68
- package/src/templates/mate-skills/claude/mate-apply-change/SKILL.md +76 -0
- package/src/templates/mate-skills/claude/mate-apply-change/references/openspec-apply-change.md +198 -0
- package/src/templates/mate-skills/claude/mate-archive-change/SKILL.md +59 -0
- package/src/templates/mate-skills/{agents/mate-openspec-backfill → claude/mate-backfill-spec}/SKILL.md +4 -4
- package/src/templates/mate-skills/claude/mate-clarify-intent/SKILL.md +95 -0
- package/src/templates/mate-skills/claude/mate-explore-change/SKILL.md +50 -0
- package/src/templates/mate-skills/claude/mate-explore-change/references/openspec-explore.md +348 -0
- package/src/templates/mate-skills/claude/mate-grill-me/SKILL.md +3 -3
- package/src/templates/mate-skills/claude/mate-interview-me/SKILL.md +5 -5
- package/src/templates/mate-skills/claude/mate-propose-change/SKILL.md +103 -0
- package/src/templates/mate-skills/claude/mate-propose-change/references/openspec-propose.md +167 -0
- package/src/templates/mate-skills/claude/mate-propose-change/references/openspec-update-change.md +101 -0
- package/src/templates/mate-skills/{agents/mate-artifact-publish → claude/mate-publish-artifact}/SKILL.md +91 -23
- package/src/templates/mate-skills/claude/{mate-artifact-publish → mate-publish-artifact}/references/openspec.md +4 -3
- package/src/templates/mate-skills/claude/mate-show-me/SKILL.md +74 -16
- package/src/templates/mate-skills/claude/mate-simplify-code/SKILL.md +74 -68
- package/src/templates/mate-skills/openspec-references.ts +140 -0
- package/src/templates/root/TEMPLATE_AGENTS.md +2 -2
- package/src/tools/setup/__snapshots__/runtime-surface-golden.test.ts.snap +3727 -320
- package/src/tools/setup/capabilities/context-mode.ts +25 -5
- package/src/tools/setup/capabilities/graphify-gate.ts +31 -0
- package/src/tools/setup/capabilities/graphify-secrets.ts +255 -0
- package/src/tools/setup/capabilities/graphify.ts +12 -0
- package/src/tools/setup/capabilities/openspec.ts +151 -270
- package/src/tools/setup/capabilities/tokensave.ts +36 -3
- package/src/tools/setup/context-services.ts +9 -17
- package/src/tools/setup/dynamic-plugins/install.ts +24 -28
- package/src/tools/setup/engine.ts +97 -21
- package/src/tools/setup/managed-output.ts +51 -0
- package/src/tools/setup/mate.ts +86 -11
- package/src/tools/setup/plugin.ts +35 -0
- package/src/tools/setup/plugins/guidance.ts +7 -4
- package/src/tools/setup/providers/agent-file-sections.ts +4 -2
- package/src/tools/setup/providers/claude-attribution.ts +65 -0
- package/src/tools/setup/providers/claude-plugin-folders.ts +625 -0
- package/src/tools/setup/providers/claude-plugin-hooks.ts +39 -19
- package/src/tools/setup/providers/claude.ts +284 -8
- package/src/tools/setup/providers/opencode.ts +180 -1
- package/src/tools/setup/utils.ts +14 -4
- package/src/tools/setup.ts +126 -10
- package/wrappers/bin/graphify +52 -4
- package/wrappers/bin/openspec +33 -9
- package/wrappers/lib/graphify-gate.mjs +8 -0
- package/src/cli/commands/studio/views/workflow/transcript.tsx +0 -190
- package/src/tools/setup/runtime-documents.ts +0 -291
|
@@ -4,6 +4,17 @@ import path from "node:path";
|
|
|
4
4
|
|
|
5
5
|
import { FRAMEWORK_NAME } from "../../../framework";
|
|
6
6
|
import { isLegacyMateOpenCodePluginReference } from "../../../lib/opencode-plugin-package";
|
|
7
|
+
import { resolveSecretPolicy } from "../../../runtime/policy";
|
|
8
|
+
import { runtimeOpenCodePluginRoot } from "../../../runtime/runtime-directory";
|
|
9
|
+
import {
|
|
10
|
+
OPENCODE_CONFIG_DOCUMENT,
|
|
11
|
+
OPENCODE_MCP_SERVERS_AT,
|
|
12
|
+
renderedDocument,
|
|
13
|
+
type ManagedRegion,
|
|
14
|
+
type RenderedRuntimeDocument,
|
|
15
|
+
type RenderedRuntimeDocuments,
|
|
16
|
+
} from "../../../runtime/runtime-document-manifest";
|
|
17
|
+
import { projectableSecretDenyPatterns } from "../../../runtime/secret-patterns";
|
|
7
18
|
import { refreshFromTemplate, stripGuidanceBlock } from "../plugins/guidance";
|
|
8
19
|
import { stripSectionFromFile, type RemoveHeadingSectionOptions } from "./agent-file-sections";
|
|
9
20
|
import { reconcileSharedSkillTree } from "./agents-skill-root";
|
|
@@ -502,7 +513,7 @@ async function reconcileOpenCodeMcpContributions(
|
|
|
502
513
|
}
|
|
503
514
|
|
|
504
515
|
/** The Mate-managed V2 `mcp.servers` map of one pass, as a value. */
|
|
505
|
-
|
|
516
|
+
function renderManagedOpenCodeMcpServers(
|
|
506
517
|
contributions: CapabilityContributionInput[] = [],
|
|
507
518
|
): Record<string, unknown> {
|
|
508
519
|
const servers: Record<string, unknown> = {};
|
|
@@ -529,6 +540,174 @@ export function renderCompanionExternalDirectoryPermissions(
|
|
|
529
540
|
];
|
|
530
541
|
}
|
|
531
542
|
|
|
543
|
+
/**
|
|
544
|
+
* V2 deny rules for the default secret files: `read`, and `edit`, which covers
|
|
545
|
+
* write and patch. Only patterns that can't match an allow-listed file are
|
|
546
|
+
* rendered, as for Claude; the middleware enforces the rest of the set.
|
|
547
|
+
*/
|
|
548
|
+
export function renderSecretDenyPermissions(
|
|
549
|
+
companionPath: string,
|
|
550
|
+
): Array<{ action: string; resource: string; effect: string }> {
|
|
551
|
+
if (!resolveSecretPolicy(companionPath).guardrails) return [];
|
|
552
|
+
return projectableSecretDenyPatterns().flatMap((pattern) =>
|
|
553
|
+
["read", "edit"].map((action) => ({ action, resource: `**/${pattern}`, effect: "deny" })),
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* The working target's OpenCode document, rendered as a value, with the
|
|
559
|
+
* companion's `.opencode/opencode.json` folded in.
|
|
560
|
+
*
|
|
561
|
+
* The Mate plugin root is what makes an Unmanaged OpenCode session load the
|
|
562
|
+
* companion guidance at all: OpenCode has no config channel for a generated
|
|
563
|
+
* system prompt, so the plugin is the only injection point. It is named through
|
|
564
|
+
* the runtime directory, so a reinstall does not strand a wrapped repository.
|
|
565
|
+
* The managed launch carries no overlay of its own, so this document is the one
|
|
566
|
+
* place every OpenCode session in the repository loads it from.
|
|
567
|
+
*/
|
|
568
|
+
export async function renderOpenCodeWorkingDocuments(
|
|
569
|
+
ctx: SetupContext,
|
|
570
|
+
inputs: CapabilityContributionInput[],
|
|
571
|
+
): Promise<RenderedRuntimeDocuments> {
|
|
572
|
+
const documents = renderedDocument(OPENCODE_CONFIG_DOCUMENT, [
|
|
573
|
+
{
|
|
574
|
+
at: ["plugins"],
|
|
575
|
+
kind: "list",
|
|
576
|
+
values: [runtimeOpenCodePluginRoot()],
|
|
577
|
+
},
|
|
578
|
+
{
|
|
579
|
+
at: [...OPENCODE_MCP_SERVERS_AT],
|
|
580
|
+
kind: "map",
|
|
581
|
+
entries: renderManagedOpenCodeMcpServers(inputs),
|
|
582
|
+
},
|
|
583
|
+
{
|
|
584
|
+
at: ["permissions"],
|
|
585
|
+
kind: "list",
|
|
586
|
+
values: [
|
|
587
|
+
...renderCompanionExternalDirectoryPermissions(ctx.companionPath),
|
|
588
|
+
...renderSecretDenyPermissions(ctx.companionPath),
|
|
589
|
+
],
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
at: ["skills"],
|
|
593
|
+
kind: "list",
|
|
594
|
+
values: [path.join(ctx.companionPath, ".agents", "skills")],
|
|
595
|
+
},
|
|
596
|
+
{ at: ["references"], kind: "map", entries: { mate: ctx.companionPath } },
|
|
597
|
+
]);
|
|
598
|
+
if (ctx.target !== "working") return { documents, warnings: [] };
|
|
599
|
+
return mergeCompanionOpenCodeConfig(ctx.companionPath, documents);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/** Keys Mate renders its own regions for; the companion's values join those regions. */
|
|
603
|
+
const MATE_OPENCODE_KEYS = new Set(["plugins", "permissions", "skills", "mcp", "references"]);
|
|
604
|
+
|
|
605
|
+
function relativePathValues(value: unknown, at: string[]): string[] {
|
|
606
|
+
if (typeof value === "string") {
|
|
607
|
+
return value.startsWith("./") || value.startsWith("../") ? [at.join(".")] : [];
|
|
608
|
+
}
|
|
609
|
+
if (Array.isArray(value)) {
|
|
610
|
+
return value.flatMap((entry, index) => relativePathValues(entry, [...at, String(index)]));
|
|
611
|
+
}
|
|
612
|
+
if (isRecord(value)) {
|
|
613
|
+
return Object.entries(value).flatMap(([key, entry]) => relativePathValues(entry, [...at, key]));
|
|
614
|
+
}
|
|
615
|
+
return [];
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/** Replaces the region at `at` with what `merge` builds from it, or appends one. */
|
|
619
|
+
function upsertRegion(
|
|
620
|
+
regions: ManagedRegion[],
|
|
621
|
+
at: string[],
|
|
622
|
+
merge: (found: ManagedRegion | undefined) => ManagedRegion,
|
|
623
|
+
): void {
|
|
624
|
+
const key = JSON.stringify(at);
|
|
625
|
+
const index = regions.findIndex((region) => JSON.stringify(region.at) === key);
|
|
626
|
+
if (index === -1) regions.push(merge(undefined));
|
|
627
|
+
else regions[index] = merge(regions[index]);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/** Mate's own values stay; companion values it does not already list go first. */
|
|
631
|
+
function mergeListRegion(regions: ManagedRegion[], at: string[], extra: unknown[]): void {
|
|
632
|
+
upsertRegion(regions, at, (found) => {
|
|
633
|
+
const own = found?.kind === "list" ? found.values : [];
|
|
634
|
+
const seen = new Set(own.map((value) => JSON.stringify(value)));
|
|
635
|
+
const values = [...extra.filter((value) => !seen.has(JSON.stringify(value))), ...own];
|
|
636
|
+
return { at, kind: "list", values };
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/** Mate's own entries win over companion entries of the same name. */
|
|
641
|
+
function mergeMapRegion(
|
|
642
|
+
regions: ManagedRegion[],
|
|
643
|
+
at: string[],
|
|
644
|
+
extra: Record<string, unknown>,
|
|
645
|
+
): void {
|
|
646
|
+
upsertRegion(regions, at, (found) => {
|
|
647
|
+
const own = found?.kind === "map" ? found.entries : {};
|
|
648
|
+
return { at, kind: "map", entries: { ...extra, ...own } };
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/** Relative reference paths resolved against the companion's `.opencode/`. */
|
|
653
|
+
function resolveReferences(
|
|
654
|
+
references: Record<string, unknown>,
|
|
655
|
+
companionDir: string,
|
|
656
|
+
): Record<string, unknown> {
|
|
657
|
+
return Object.fromEntries(
|
|
658
|
+
Object.entries(references).map(([name, reference]) => [
|
|
659
|
+
name,
|
|
660
|
+
typeof reference === "string" && !path.isAbsolute(reference)
|
|
661
|
+
? path.resolve(companionDir, reference)
|
|
662
|
+
: reference,
|
|
663
|
+
]),
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Folds the companion's `.opencode/opencode.json` into the wrapped document.
|
|
669
|
+
* Mate's regions beat companion values; other top-level keys yield to the
|
|
670
|
+
* repository's. `references` resolve against the companion's `.opencode/`;
|
|
671
|
+
* other relative paths are reported, not rewritten.
|
|
672
|
+
*/
|
|
673
|
+
async function mergeCompanionOpenCodeConfig(
|
|
674
|
+
companionPath: string,
|
|
675
|
+
documents: RenderedRuntimeDocument[],
|
|
676
|
+
): Promise<RenderedRuntimeDocuments> {
|
|
677
|
+
const [rendered] = documents;
|
|
678
|
+
const companionConfigPath = path.join(companionPath, ".opencode", "opencode.json");
|
|
679
|
+
const companion = rendered ? await readOpenCodeConfig(companionConfigPath) : null;
|
|
680
|
+
if (!rendered || !companion?.present) return { documents, warnings: [] };
|
|
681
|
+
|
|
682
|
+
const regions = [...rendered.regions] as ManagedRegion[];
|
|
683
|
+
const warnings: string[] = [];
|
|
684
|
+
|
|
685
|
+
const companionDir = path.dirname(companionConfigPath);
|
|
686
|
+
for (const [key, value] of Object.entries(companion.config)) {
|
|
687
|
+
if (key === "$schema") continue;
|
|
688
|
+
if (key === "references" && isRecord(value)) {
|
|
689
|
+
mergeMapRegion(regions, ["references"], resolveReferences(value, companionDir));
|
|
690
|
+
continue;
|
|
691
|
+
}
|
|
692
|
+
for (const at of relativePathValues(value, [key])) {
|
|
693
|
+
warnings.push(
|
|
694
|
+
`${companionConfigPath}: ${at} is a relative path, which resolves against the working repository once merged into ${OPENCODE_CONFIG_DOCUMENT}; use an absolute path.`,
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
if (MATE_OPENCODE_KEYS.has(key)) {
|
|
698
|
+
if (key === "mcp" && isRecord(value) && isRecord(value.servers)) {
|
|
699
|
+
mergeMapRegion(regions, [...OPENCODE_MCP_SERVERS_AT], value.servers);
|
|
700
|
+
} else if (Array.isArray(value)) {
|
|
701
|
+
mergeListRegion(regions, [key], value);
|
|
702
|
+
}
|
|
703
|
+
continue;
|
|
704
|
+
}
|
|
705
|
+
regions.push({ at: [key], kind: "value", value, yields: true });
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
return { documents: [{ path: OPENCODE_CONFIG_DOCUMENT, regions }], warnings };
|
|
709
|
+
}
|
|
710
|
+
|
|
532
711
|
/**
|
|
533
712
|
* Reconcile declared agent definition files under `.opencode/agents/`. Runs
|
|
534
713
|
* in both companion and hub scope — an agent definition is fully
|
package/src/tools/setup/utils.ts
CHANGED
|
@@ -65,21 +65,31 @@ function waitForClose(child: ChildProcess, formatError: (code: number) => string
|
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
export interface RunCommandOptions {
|
|
69
|
+
cwd?: string;
|
|
70
|
+
/** Merged over `process.env` for the child only; Mate's own env is untouched. */
|
|
71
|
+
env?: Record<string, string>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function childEnv(options: RunCommandOptions): { env?: NodeJS.ProcessEnv } {
|
|
75
|
+
return options.env ? { env: { ...process.env, ...options.env } } : {};
|
|
76
|
+
}
|
|
77
|
+
|
|
68
78
|
export async function runCommand(
|
|
69
79
|
command: string,
|
|
70
80
|
args: string[],
|
|
71
|
-
options:
|
|
81
|
+
options: RunCommandOptions = {},
|
|
72
82
|
): Promise<void> {
|
|
73
|
-
const child = spawn(command, args, { cwd: options.cwd, stdio: "inherit" });
|
|
83
|
+
const child = spawn(command, args, { cwd: options.cwd, stdio: "inherit", ...childEnv(options) });
|
|
74
84
|
await waitForClose(child, (code) => `${command} ${args.join(" ")} exited with code ${code}`);
|
|
75
85
|
}
|
|
76
86
|
|
|
77
87
|
export async function runCommandSilently(
|
|
78
88
|
command: string,
|
|
79
89
|
args: string[],
|
|
80
|
-
options:
|
|
90
|
+
options: RunCommandOptions = {},
|
|
81
91
|
): Promise<void> {
|
|
82
|
-
const child = spawn(command, args, { cwd: options.cwd, stdio: "pipe" });
|
|
92
|
+
const child = spawn(command, args, { cwd: options.cwd, stdio: "pipe", ...childEnv(options) });
|
|
83
93
|
await waitForClose(child, (code) => `${command} ${args.join(" ")} exited with code ${code}`);
|
|
84
94
|
}
|
|
85
95
|
|
package/src/tools/setup.ts
CHANGED
|
@@ -18,11 +18,25 @@ import {
|
|
|
18
18
|
type CapabilityConfig,
|
|
19
19
|
type FrameworkConfig,
|
|
20
20
|
} from "../lib/orchestrator/types";
|
|
21
|
+
import { getClaudePluginRoot } from "../lib/package-paths";
|
|
22
|
+
import type { RenderedRuntimeDocuments } from "../runtime/runtime-document-manifest";
|
|
21
23
|
import {
|
|
22
24
|
collectManagedGitignoreEntries,
|
|
23
25
|
writeManagedGitignoreBlock,
|
|
24
26
|
} from "./setup/plugins/gitignore";
|
|
25
|
-
import
|
|
27
|
+
import { createManagedOutputCollector } from "./setup/managed-output";
|
|
28
|
+
import type {
|
|
29
|
+
ManagedOutputReport,
|
|
30
|
+
PluginRegistration,
|
|
31
|
+
SetupContext,
|
|
32
|
+
SetupScope,
|
|
33
|
+
} from "./setup/plugin";
|
|
34
|
+
import {
|
|
35
|
+
inspectClaudePluginFolders,
|
|
36
|
+
type ClaudePluginContributionFailure,
|
|
37
|
+
type ClaudePluginDirectoryReport,
|
|
38
|
+
type ClaudePluginFolders,
|
|
39
|
+
} from "./setup/providers/claude-plugin-folders";
|
|
26
40
|
import { getActiveDistribution } from "../distribution";
|
|
27
41
|
import { createUvPlugin } from "./setup/package-managers/uv";
|
|
28
42
|
import type { PackageManagerSetupDeps } from "./setup/package-managers/uv";
|
|
@@ -38,10 +52,12 @@ import { hydrateDynamicPlugins } from "./setup/dynamic-plugins/hydrate";
|
|
|
38
52
|
import { installDeclaredPlugins } from "./setup/dynamic-plugins/install";
|
|
39
53
|
import {
|
|
40
54
|
buildSetupInstallationPlan,
|
|
55
|
+
collectRuntimeContributionInputs,
|
|
41
56
|
executeSetupInstallationPlan,
|
|
57
|
+
publishRuntimeClaudePluginMarketplaces,
|
|
42
58
|
renderRuntimeDocuments,
|
|
43
|
-
type RenderedRuntimeDocuments,
|
|
44
59
|
type SetupInstallationOutcome,
|
|
60
|
+
type SetupInstallationPlan,
|
|
45
61
|
} from "./setup/engine";
|
|
46
62
|
|
|
47
63
|
export interface SetupInput {
|
|
@@ -57,6 +73,16 @@ export interface SetupDependencies {
|
|
|
57
73
|
globalConfigStore?: GlobalConfigStore;
|
|
58
74
|
}
|
|
59
75
|
|
|
76
|
+
export interface CompanionSyncOptions {
|
|
77
|
+
/** Regenerates OpenSpec CLI output; set only by `mate companion update`. */
|
|
78
|
+
regenerateOpenSpec?: boolean;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface CompanionSyncOutcome extends SetupInstallationOutcome {
|
|
82
|
+
/** The managed output this pass wrote or removed. */
|
|
83
|
+
managedOutput: ManagedOutputReport;
|
|
84
|
+
}
|
|
85
|
+
|
|
60
86
|
export async function applySetupCompatibilities(
|
|
61
87
|
companionPath: string,
|
|
62
88
|
config: FrameworkConfig,
|
|
@@ -64,11 +90,23 @@ export async function applySetupCompatibilities(
|
|
|
64
90
|
plugins: PluginRegistration[] = getActiveDistribution().registry.getEntries(),
|
|
65
91
|
repoPath?: string,
|
|
66
92
|
scope: SetupScope = config.type === "hub" ? "hub" : "companion",
|
|
67
|
-
|
|
93
|
+
options: CompanionSyncOptions = {},
|
|
94
|
+
): Promise<CompanionSyncOutcome> {
|
|
68
95
|
const plan = buildSetupInstallationPlan(config, plugins);
|
|
69
96
|
const activeProviders = plan.activeProviders;
|
|
70
|
-
const
|
|
71
|
-
|
|
97
|
+
const managedOutput = createManagedOutputCollector(companionPath);
|
|
98
|
+
const ctx: SetupContext = {
|
|
99
|
+
companionPath,
|
|
100
|
+
config,
|
|
101
|
+
mode,
|
|
102
|
+
activeProviders,
|
|
103
|
+
repoPath,
|
|
104
|
+
scope,
|
|
105
|
+
...(options.regenerateOpenSpec ? { regenerateOpenSpec: true } : {}),
|
|
106
|
+
managedOutput: managedOutput.recorder,
|
|
107
|
+
};
|
|
108
|
+
const outcome = await executeSetupInstallationPlan(ctx, plugins, plan);
|
|
109
|
+
return { ...outcome, managedOutput: managedOutput.report() };
|
|
72
110
|
}
|
|
73
111
|
|
|
74
112
|
/**
|
|
@@ -82,16 +120,83 @@ export async function renderWorkingRuntimeDocuments(
|
|
|
82
120
|
repoPath: string,
|
|
83
121
|
plugins: PluginRegistration[] = getActiveDistribution().registry.getAll(),
|
|
84
122
|
): Promise<RenderedRuntimeDocuments> {
|
|
123
|
+
const { plan, ctx } = planSyncPass(companionPath, config, plugins, {
|
|
124
|
+
repoPath,
|
|
125
|
+
target: "working",
|
|
126
|
+
});
|
|
127
|
+
return renderRuntimeDocuments(ctx, plugins, plan);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Publishes the enabled Claude plugin folders for a Working Repository's wrap
|
|
132
|
+
* pass, before it renders; see {@link publishRuntimeClaudePluginMarketplaces}.
|
|
133
|
+
*/
|
|
134
|
+
export async function publishWorkingClaudePluginMarketplaces(
|
|
135
|
+
companionPath: string,
|
|
136
|
+
config: FrameworkConfig,
|
|
137
|
+
repoPath: string,
|
|
138
|
+
plugins: PluginRegistration[] = getActiveDistribution().registry.getAll(),
|
|
139
|
+
): Promise<ClaudePluginFolders> {
|
|
140
|
+
const { plan, ctx } = planSyncPass(companionPath, config, plugins, {
|
|
141
|
+
repoPath,
|
|
142
|
+
target: "working",
|
|
143
|
+
});
|
|
144
|
+
return publishRuntimeClaudePluginMarketplaces(ctx, plugins, plan);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** A sync pass's plan and context, for a caller that runs no plugin phase. */
|
|
148
|
+
function planSyncPass(
|
|
149
|
+
companionPath: string,
|
|
150
|
+
config: FrameworkConfig,
|
|
151
|
+
plugins: PluginRegistration[],
|
|
152
|
+
extra: Pick<SetupContext, "repoPath" | "target"> = {},
|
|
153
|
+
): { plan: SetupInstallationPlan; ctx: SetupContext } {
|
|
85
154
|
const plan = buildSetupInstallationPlan(config, plugins);
|
|
86
155
|
const ctx: SetupContext = {
|
|
87
156
|
companionPath,
|
|
88
157
|
config,
|
|
89
158
|
mode: "sync",
|
|
90
159
|
activeProviders: plan.activeProviders,
|
|
91
|
-
|
|
92
|
-
|
|
160
|
+
...extra,
|
|
161
|
+
};
|
|
162
|
+
return { plan, ctx };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** What an operator sees of the enabled Capabilities' Claude plugin folders. */
|
|
166
|
+
export interface ClaudePluginDirectoryInspection {
|
|
167
|
+
plugins: ClaudePluginDirectoryReport[];
|
|
168
|
+
/** Capabilities whose contributions rejected; the other Capabilities are still listed. */
|
|
169
|
+
failures: ClaudePluginContributionFailure[];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Enabled Capabilities' declared Claude plugin folders and whether `mate claude`
|
|
174
|
+
* passes each, checked against the running install's bundled plugin. Read-only:
|
|
175
|
+
* runs no plugin phase and reconciles nothing.
|
|
176
|
+
*/
|
|
177
|
+
export async function inspectClaudePluginDirectories(
|
|
178
|
+
companionPath: string,
|
|
179
|
+
config: FrameworkConfig,
|
|
180
|
+
plugins: PluginRegistration[] = getActiveDistribution().registry.getEntries(),
|
|
181
|
+
): Promise<ClaudePluginDirectoryInspection> {
|
|
182
|
+
const { plan, ctx } = planSyncPass(companionPath, config, plugins);
|
|
183
|
+
const failures: ClaudePluginContributionFailure[] = [];
|
|
184
|
+
const inputs = await collectRuntimeContributionInputs(ctx, plugins, plan, (capability, error) =>
|
|
185
|
+
failures.push({
|
|
186
|
+
capability,
|
|
187
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
188
|
+
}),
|
|
189
|
+
);
|
|
190
|
+
return {
|
|
191
|
+
plugins: [
|
|
192
|
+
...(
|
|
193
|
+
await inspectClaudePluginFolders(inputs.get("claude") ?? [], {
|
|
194
|
+
bundledPluginRoot: getClaudePluginRoot(),
|
|
195
|
+
})
|
|
196
|
+
).report,
|
|
197
|
+
],
|
|
198
|
+
failures,
|
|
93
199
|
};
|
|
94
|
-
return renderRuntimeDocuments(ctx, plugins, plan);
|
|
95
200
|
}
|
|
96
201
|
|
|
97
202
|
export async function updateProjectGitignore(
|
|
@@ -104,18 +209,29 @@ export async function updateProjectGitignore(
|
|
|
104
209
|
await writeManagedGitignoreBlock(path.join(companionPath, ".gitignore"), FRAMEWORK_NAME, entries);
|
|
105
210
|
}
|
|
106
211
|
|
|
212
|
+
export interface CompanionSyncResult {
|
|
213
|
+
/** For a launch to pass and report; every other caller ignores them. */
|
|
214
|
+
claudePluginFolders: ClaudePluginFolders;
|
|
215
|
+
/** For `mate companion update` to sort changed paths; a launch ignores it. */
|
|
216
|
+
managedOutput: ManagedOutputReport;
|
|
217
|
+
}
|
|
218
|
+
|
|
107
219
|
export async function syncCompanionFiles(
|
|
108
220
|
companionPath: string,
|
|
109
221
|
config: FrameworkConfig,
|
|
110
222
|
repoPath?: string,
|
|
111
|
-
|
|
112
|
-
|
|
223
|
+
options: CompanionSyncOptions = {},
|
|
224
|
+
): Promise<CompanionSyncResult> {
|
|
225
|
+
const outcome = await applySetupCompatibilities(
|
|
113
226
|
companionPath,
|
|
114
227
|
config,
|
|
115
228
|
"sync",
|
|
116
229
|
getActiveDistribution().registry.getAll(),
|
|
117
230
|
repoPath,
|
|
231
|
+
undefined,
|
|
232
|
+
options,
|
|
118
233
|
);
|
|
234
|
+
return { claudePluginFolders: outcome.claudePluginFolders, managedOutput: outcome.managedOutput };
|
|
119
235
|
}
|
|
120
236
|
|
|
121
237
|
export const setupToolDeps = {
|
package/wrappers/bin/graphify
CHANGED
|
@@ -69,6 +69,34 @@ _graphify_root="$(dirname "$_graphify_out")"
|
|
|
69
69
|
_graph_json="$_graphify_out/graph.json"
|
|
70
70
|
export GRAPHIFY_OUT="$_graphify_out"
|
|
71
71
|
|
|
72
|
+
# Secret gate: leaves secret files out of every extraction and prunes any
|
|
73
|
+
# secret that still reaches the output. It never stops graphify: when the gate
|
|
74
|
+
# can't run, the wrapper warns and runs graphify anyway.
|
|
75
|
+
_gate="$_this_dir/../lib/graphify-gate.mjs"
|
|
76
|
+
_secret_excludes=()
|
|
77
|
+
_secret_pre() {
|
|
78
|
+
local _out _p
|
|
79
|
+
if ! _out="$(node "$_gate" pre "$_companion" "$_repo_path")"; then
|
|
80
|
+
echo "graphify: warning: the secret gate did not run; secret files may be indexed" >&2
|
|
81
|
+
return
|
|
82
|
+
fi
|
|
83
|
+
while IFS= read -r _p; do
|
|
84
|
+
[ -n "$_p" ] && _secret_excludes+=(--exclude "$_p")
|
|
85
|
+
done <<< "$_out"
|
|
86
|
+
}
|
|
87
|
+
_secret_post() {
|
|
88
|
+
node "$_gate" post "$_companion" "$_graphify_out" ||
|
|
89
|
+
echo "graphify: warning: the graphify output was not checked for secrets" >&2
|
|
90
|
+
}
|
|
91
|
+
# Runs an extraction that accepts --exclude, then prunes its output.
|
|
92
|
+
_extract() {
|
|
93
|
+
_secret_pre
|
|
94
|
+
"$_real" "$@" "${_secret_excludes[@]}"
|
|
95
|
+
local _status=$?
|
|
96
|
+
_secret_post
|
|
97
|
+
exit "$_status"
|
|
98
|
+
}
|
|
99
|
+
|
|
72
100
|
_cmd="${1:-}"
|
|
73
101
|
case "$_cmd" in
|
|
74
102
|
build)
|
|
@@ -81,16 +109,32 @@ case "$_cmd" in
|
|
|
81
109
|
*) _rest+=("$_a") ;;
|
|
82
110
|
esac
|
|
83
111
|
done
|
|
84
|
-
|
|
112
|
+
_extract extract "$_repo_path" --out "$_graphify_root" "${_rest[@]}"
|
|
85
113
|
;;
|
|
86
114
|
update)
|
|
87
115
|
if [ "$#" -eq 1 ] || [[ "$2" == -* ]]; then
|
|
88
|
-
|
|
116
|
+
_extract "$_repo_path" --update "${@:2}"
|
|
117
|
+
else
|
|
118
|
+
_extract "$2" --update "${@:3}"
|
|
119
|
+
fi
|
|
120
|
+
;;
|
|
121
|
+
extract)
|
|
122
|
+
if [ "$#" -eq 1 ] || [[ "$2" == -* ]]; then
|
|
123
|
+
_extract extract "$_repo_path" "${@:2}"
|
|
124
|
+
else
|
|
125
|
+
_extract "$@"
|
|
126
|
+
fi
|
|
127
|
+
;;
|
|
128
|
+
watch)
|
|
129
|
+
# Long-running: only the ignore region applies; there is no output to prune.
|
|
130
|
+
_secret_pre
|
|
131
|
+
if [ "$#" -eq 1 ] || [[ "$2" == -* ]]; then
|
|
132
|
+
exec "$_real" watch "$_repo_path" "${@:2}"
|
|
89
133
|
else
|
|
90
|
-
exec "$_real" "
|
|
134
|
+
exec "$_real" "$@"
|
|
91
135
|
fi
|
|
92
136
|
;;
|
|
93
|
-
|
|
137
|
+
cluster-only|label|check-update)
|
|
94
138
|
if [ "$#" -eq 1 ] || [[ "$2" == -* ]]; then
|
|
95
139
|
exec "$_real" "$_cmd" "$_repo_path" "${@:2}"
|
|
96
140
|
else
|
|
@@ -120,6 +164,10 @@ case "$_cmd" in
|
|
|
120
164
|
fi
|
|
121
165
|
;;
|
|
122
166
|
*)
|
|
167
|
+
# A direct `graphify <path> --update` is an extraction too.
|
|
168
|
+
for _a in "$@"; do
|
|
169
|
+
[ "$_a" = "--update" ] && _extract "$@"
|
|
170
|
+
done
|
|
123
171
|
exec "$_real" "$@"
|
|
124
172
|
;;
|
|
125
173
|
esac
|
package/wrappers/bin/openspec
CHANGED
|
@@ -50,16 +50,25 @@ if [ -z "$_companion" ]; then
|
|
|
50
50
|
fi
|
|
51
51
|
[ -n "$_companion" ] || { echo "openspec: no mate context here — run \`mate wrap\` in this repository" >&2; exit 1; }
|
|
52
52
|
|
|
53
|
+
# The OpenSpec CLI Mate ships with, found the way Node resolves it: upward from
|
|
54
|
+
# the package root, hoisted or nested under mate-core (distribution packages).
|
|
55
|
+
# Never an openspec on PATH, so a global install of another version is ignored.
|
|
56
|
+
# Physical path: the runtime directory reaches wrappers/ through a symlink.
|
|
53
57
|
_real=""
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
_dir="$(cd -P "$_this_dir" && cd ../.. && pwd -P)"
|
|
59
|
+
while [ -z "$_real" ]; do
|
|
60
|
+
for _candidate in \
|
|
61
|
+
"$_dir/node_modules/@fission-ai/openspec/bin/openspec.js" \
|
|
62
|
+
"$_dir/node_modules/@uniqbit/mate-core/node_modules/@fission-ai/openspec/bin/openspec.js"; do
|
|
63
|
+
if [ -f "$_candidate" ]; then
|
|
64
|
+
_real="$_candidate"
|
|
65
|
+
break 2
|
|
66
|
+
fi
|
|
67
|
+
done
|
|
68
|
+
[ "$_dir" = "/" ] && break
|
|
69
|
+
_dir="$(dirname "$_dir")"
|
|
60
70
|
done
|
|
61
|
-
|
|
62
|
-
[ -n "$_real" ] || { echo "openspec wrapper: real binary not found in PATH" >&2; exit 1; }
|
|
71
|
+
[ -n "$_real" ] || { echo "openspec: bundled OpenSpec CLI is missing. Reinstall Mate to restore it." >&2; exit 1; }
|
|
63
72
|
command="${1-}"
|
|
64
73
|
if [ "$command" = "templates" ]; then
|
|
65
74
|
has_schema=0
|
|
@@ -133,4 +142,19 @@ case "$command" in
|
|
|
133
142
|
_mate_use_store_pointer
|
|
134
143
|
;;
|
|
135
144
|
esac
|
|
136
|
-
|
|
145
|
+
# A JS entry's `#!/usr/bin/env node` shebang needs an executable bit and `node`
|
|
146
|
+
# on PATH; without either (Bun-only installs) it runs on an explicit runtime.
|
|
147
|
+
_shebang=""
|
|
148
|
+
[ "${_real%.js}" != "$_real" ] && { IFS= read -r _shebang < "$_real" || true; }
|
|
149
|
+
if [ -n "$_shebang" ] && {
|
|
150
|
+
[ ! -x "$_real" ] ||
|
|
151
|
+
{ [ "$_shebang" = "#!/usr/bin/env node" ] && ! command -v node >/dev/null 2>&1; }
|
|
152
|
+
}; then
|
|
153
|
+
_runtime="$(command -v node || command -v bun || true)"
|
|
154
|
+
[ -n "$_runtime" ] || { echo "openspec: neither node nor bun is on PATH to run $_real" >&2; exit 1; }
|
|
155
|
+
set -- "$_real" "$@"
|
|
156
|
+
_real="$_runtime"
|
|
157
|
+
fi
|
|
158
|
+
# Mate decides the OpenSpec version, so OpenSpec's update hint is wrong advice
|
|
159
|
+
# here; both variables reach the delegated binary only.
|
|
160
|
+
exec env -C "$_cwd" OPENSPEC_TELEMETRY=0 OPENSPEC_NO_UPDATE_CHECK=1 "$_real" "$@"
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Thin shim: the gate lives in src/tools/setup/capabilities/graphify-gate.ts,
|
|
3
|
+
// loaded through the plugin's ts-loader because the installed package sits
|
|
4
|
+
// inside node_modules where node's native type stripping is disabled.
|
|
5
|
+
import "../../claude-plugin/hooks/ts-loader.mjs";
|
|
6
|
+
|
|
7
|
+
const { runGraphifyGate } = await import("../../src/tools/setup/capabilities/graphify-gate.ts");
|
|
8
|
+
process.exitCode = await runGraphifyGate(process.argv.slice(2));
|