auriga-cli 1.18.2 → 1.18.4
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/api-types.d.ts +6 -0
- package/dist/catalog.d.ts +28 -0
- package/dist/catalog.json +40 -8
- package/dist/scan-catalog.js +53 -126
- package/dist/state.d.ts +6 -0
- package/dist/state.js +50 -0
- package/package.json +3 -3
package/dist/api-types.d.ts
CHANGED
|
@@ -63,6 +63,12 @@ export interface PluginState {
|
|
|
63
63
|
* "user" (Codex has no project-scope plugin concept). See WorkflowState
|
|
64
64
|
* comment on why this is typed optional. */
|
|
65
65
|
observedScope?: ScanScope;
|
|
66
|
+
/** True for plugins whose source lives in an upstream marketplace, not in
|
|
67
|
+
* this repo (skill-creator / claude-md-management / codex). The scanner
|
|
68
|
+
* short-circuits update-available reporting for these — upgrades go
|
|
69
|
+
* through `claude plugins update`, not us. The UI renders an EXTERNAL
|
|
70
|
+
* badge to make the "not our jurisdiction" signal explicit. */
|
|
71
|
+
external?: boolean;
|
|
66
72
|
}
|
|
67
73
|
export interface HookState {
|
|
68
74
|
name: string;
|
package/dist/catalog.d.ts
CHANGED
|
@@ -1,9 +1,37 @@
|
|
|
1
1
|
export interface CatalogEntry {
|
|
2
2
|
name: string;
|
|
3
3
|
description: string;
|
|
4
|
+
/** Build-time-baked plugin version. Set ONLY for plugin entries whose
|
|
5
|
+
* source lives in this repo's `plugins/<name>/` directory — the scanner
|
|
6
|
+
* uses it to surface "update-available" when the user's installed copy
|
|
7
|
+
* is older. Absent for skill / hook entries and for external-marketplace
|
|
8
|
+
* plugins (whose manifest lives upstream). Must be baked at build time
|
|
9
|
+
* because `plugins/<name>/.claude-plugin/plugin.json` is NOT shipped in
|
|
10
|
+
* the npm tarball (see `package.json` `files` field). */
|
|
11
|
+
expectedVersion?: string;
|
|
12
|
+
/** Build-time-baked agent map for plugin entries. Derived from
|
|
13
|
+
* `.claude/plugins.json` ∪ `.agents/plugins/install.json` — those config
|
|
14
|
+
* files are NOT shipped in the npm tarball, so the scanner can't read
|
|
15
|
+
* them at runtime. Baking here lets `/api/state` correctly classify
|
|
16
|
+
* dual-Agent plugins as `["claude","codex"]` for installed users.
|
|
17
|
+
* Absent on skill / hook entries. */
|
|
18
|
+
agents?: ("claude" | "codex")[];
|
|
19
|
+
/** True for plugins whose source lives in an UPSTREAM marketplace
|
|
20
|
+
* (skill-creator / claude-md-management / codex), not in this repo. The
|
|
21
|
+
* scanner uses this to disable update-available reporting — those
|
|
22
|
+
* plugins update through `claude plugins update`, not through us. UI
|
|
23
|
+
* surfaces an EXTERNAL badge so users know where to look. */
|
|
24
|
+
external?: boolean;
|
|
4
25
|
}
|
|
5
26
|
export interface Catalog {
|
|
6
27
|
generatedAt: string;
|
|
28
|
+
/** Workflow content version baked from `CLAUDE.md`'s `# auriga Workflow (vX.Y.Z)`
|
|
29
|
+
* header at build time. MUST live here rather than be read at runtime
|
|
30
|
+
* because `CLAUDE.md` is NOT in the npm tarball — `package.json` `files`
|
|
31
|
+
* allowlists only `dist/`. Empty string when the header is unparseable;
|
|
32
|
+
* the scanner then degrades to "trust whatever the user has" rather than
|
|
33
|
+
* forcing phantom update-available against an empty expected value. */
|
|
34
|
+
workflowVersion: string;
|
|
7
35
|
workflowSkills: CatalogEntry[];
|
|
8
36
|
recommendedSkills: CatalogEntry[];
|
|
9
37
|
plugins: CatalogEntry[];
|
package/dist/catalog.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generatedAt": "2026-05-
|
|
2
|
+
"generatedAt": "2026-05-12T15:14:34.188Z",
|
|
3
|
+
"workflowVersion": "1.7.0",
|
|
3
4
|
"workflowSkills": [
|
|
4
5
|
{
|
|
5
6
|
"name": "brainstorming",
|
|
@@ -75,31 +76,62 @@
|
|
|
75
76
|
"plugins": [
|
|
76
77
|
{
|
|
77
78
|
"name": "skill-creator",
|
|
78
|
-
"description": "Create and manage custom skills"
|
|
79
|
+
"description": "Create and manage custom skills",
|
|
80
|
+
"agents": [
|
|
81
|
+
"claude"
|
|
82
|
+
],
|
|
83
|
+
"external": true
|
|
79
84
|
},
|
|
80
85
|
{
|
|
81
86
|
"name": "claude-md-management",
|
|
82
|
-
"description": "Audit and improve CLAUDE.md files"
|
|
87
|
+
"description": "Audit and improve CLAUDE.md files",
|
|
88
|
+
"agents": [
|
|
89
|
+
"claude"
|
|
90
|
+
],
|
|
91
|
+
"external": true
|
|
83
92
|
},
|
|
84
93
|
{
|
|
85
94
|
"name": "codex",
|
|
86
|
-
"description": "Cross-model collaboration with Codex"
|
|
95
|
+
"description": "Cross-model collaboration with Codex",
|
|
96
|
+
"agents": [
|
|
97
|
+
"claude"
|
|
98
|
+
],
|
|
99
|
+
"external": true
|
|
87
100
|
},
|
|
88
101
|
{
|
|
89
102
|
"name": "auriga-go",
|
|
90
|
-
"description": "(Claude/Codex) Workflow autopilot for the auriga workflow. Reminder-based navigation across CLAUDE.md's phases. Bundles a /goalify skill that plans an autonomous goal from a spec or work-in-progress and dispatches it via Claude Code's built-in /goal command."
|
|
103
|
+
"description": "(Claude/Codex) Workflow autopilot for the auriga workflow. Reminder-based navigation across CLAUDE.md's phases. Bundles a /goalify skill that plans an autonomous goal from a spec or work-in-progress and dispatches it via Claude Code's built-in /goal command.",
|
|
104
|
+
"agents": [
|
|
105
|
+
"claude",
|
|
106
|
+
"codex"
|
|
107
|
+
],
|
|
108
|
+
"expectedVersion": "1.1.0"
|
|
91
109
|
},
|
|
92
110
|
{
|
|
93
111
|
"name": "auriga-git-guards",
|
|
94
|
-
"description": "(Claude/Codex) Git lifecycle guardrails: commit-reminder + PR-create snapshot inject + PR-ready structural block. Bundles the git-workflow skill (Claude Code + Codex)."
|
|
112
|
+
"description": "(Claude/Codex) Git lifecycle guardrails: commit-reminder + PR-create snapshot inject + PR-ready structural block. Bundles the git-workflow skill (Claude Code + Codex).",
|
|
113
|
+
"agents": [
|
|
114
|
+
"claude",
|
|
115
|
+
"codex"
|
|
116
|
+
],
|
|
117
|
+
"expectedVersion": "1.1.0"
|
|
95
118
|
},
|
|
96
119
|
{
|
|
97
120
|
"name": "deep-review",
|
|
98
|
-
"description": "(Claude/Codex) Multi-dimensional PR review orchestrator. Dispatches parallel reviewers (spec-conformance, correctness, test-quality, docs-sync, robustness, security, ux, performance, structure, code-quality, skill-plugin-quality) and synthesizes findings into an actionable punch list. Supports project-level custom reviewers via docs/rules/review/ and ships a reviewer-creator skill for scaffolding them."
|
|
121
|
+
"description": "(Claude/Codex) Multi-dimensional PR review orchestrator. Dispatches parallel reviewers (spec-conformance, correctness, test-quality, docs-sync, robustness, security, ux, performance, structure, code-quality, skill-plugin-quality) and synthesizes findings into an actionable punch list. Supports project-level custom reviewers via docs/rules/review/ and ships a reviewer-creator skill for scaffolding them.",
|
|
122
|
+
"agents": [
|
|
123
|
+
"claude",
|
|
124
|
+
"codex"
|
|
125
|
+
],
|
|
126
|
+
"expectedVersion": "0.3.1"
|
|
99
127
|
},
|
|
100
128
|
{
|
|
101
129
|
"name": "session-instructions-loader",
|
|
102
|
-
"description": "(Codex) Injects extra instruction files on session start"
|
|
130
|
+
"description": "(Codex) Injects extra instruction files on session start",
|
|
131
|
+
"agents": [
|
|
132
|
+
"codex"
|
|
133
|
+
],
|
|
134
|
+
"expectedVersion": "1.0.0"
|
|
103
135
|
}
|
|
104
136
|
],
|
|
105
137
|
"hooks": [
|
package/dist/scan-catalog.js
CHANGED
|
@@ -1,61 +1,28 @@
|
|
|
1
|
-
// Build the scan-time Catalog (the shape src/state.ts consumes) from
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
1
|
+
// Build the scan-time Catalog (the shape src/state.ts consumes) from the
|
|
2
|
+
// build-time `dist/catalog.json`. This module is intentionally a *thin
|
|
3
|
+
// adapter* — it must NOT read any file outside `dist/catalog.json`, because
|
|
4
|
+
// the npm tarball's `files` field allowlists only `dist/`. Reading from
|
|
5
|
+
// `packageRoot/CLAUDE.md`, `packageRoot/.claude/plugins.json`, or
|
|
6
|
+
// `packageRoot/.agents/skills/<name>/SKILL.md` succeeds in dev (where
|
|
7
|
+
// packageRoot === repoRoot) but silently returns empty for npm-installed
|
|
8
|
+
// users, leaving the scanner unable to surface real update signals.
|
|
5
9
|
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// skills-lock.json — expected SHA256 for every vendored skill
|
|
9
|
-
// .claude/plugins.json — Claude plugin entries (agent = "claude")
|
|
10
|
-
// .agents/plugins/install.json — Codex plugin entries (agent = "codex")
|
|
11
|
-
// .claude/hooks/hooks.json — registers settingsEvents per hook (event /
|
|
12
|
-
// matcher / if) used by state.ts for drift
|
|
13
|
-
// detection in <scope>/.claude/settings.json
|
|
14
|
-
// CLAUDE.md — `# auriga Workflow (vX.Y.Z)` provides
|
|
15
|
-
// workflowVersion
|
|
10
|
+
// Anything the scanner needs beyond what's already in catalog.json must
|
|
11
|
+
// first be baked at build time in `src/build/generate-catalog.ts`.
|
|
16
12
|
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
|
|
13
|
+
// Scope of the current bake (covered fields):
|
|
14
|
+
// - workflowVersion — from CLAUDE.md header
|
|
15
|
+
// - plugin agents map — from .claude/plugins.json ∪ .agents/plugins/install.json
|
|
16
|
+
// - plugin expectedVersion — from plugins/<name>/.claude-plugin/plugin.json
|
|
17
|
+
// - plugin external flag — derived (no in-tree manifest = external)
|
|
18
|
+
//
|
|
19
|
+
// Out of scope for v1.18.4 (follow-up PRs):
|
|
20
|
+
// - hook expectedEvent / expectedMatcher / expectedIf (from .claude/hooks/hooks.json)
|
|
21
|
+
// - apply-time installer config (the install path reads .claude/plugins.json
|
|
22
|
+
// directly — that needs runWebUi → fetchContentRoot rewire, not bake).
|
|
22
23
|
import { readFile } from "node:fs/promises";
|
|
23
24
|
import path from "node:path";
|
|
24
25
|
import { loadCatalog } from "./catalog.js";
|
|
25
|
-
async function sha256SkillMd(skillsRoot, name) {
|
|
26
|
-
try {
|
|
27
|
-
const buf = await readFile(path.join(skillsRoot, name, "SKILL.md"));
|
|
28
|
-
return createHash("sha256").update(buf).digest("hex");
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
31
|
-
return "";
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
/** Read `plugins/<name>/.claude-plugin/plugin.json` (or `.codex-plugin/plugin.json`
|
|
35
|
-
* as fallback) and return the `version` field. Returns "" when no manifest
|
|
36
|
-
* exists or the JSON is malformed — the scanner then leaves expectedVersion
|
|
37
|
-
* unset, which means external-marketplace plugins (whose source lives
|
|
38
|
-
* upstream, not in this repo) get the "trust installed" classification. */
|
|
39
|
-
async function readPluginManifestVersion(packageRoot, name) {
|
|
40
|
-
const candidates = [
|
|
41
|
-
path.join(packageRoot, "plugins", name, ".claude-plugin", "plugin.json"),
|
|
42
|
-
path.join(packageRoot, "plugins", name, ".codex-plugin", "plugin.json"),
|
|
43
|
-
];
|
|
44
|
-
for (const p of candidates) {
|
|
45
|
-
try {
|
|
46
|
-
const raw = await readFile(p, "utf8");
|
|
47
|
-
const parsed = JSON.parse(raw);
|
|
48
|
-
if (typeof parsed.version === "string" && parsed.version.length > 0) {
|
|
49
|
-
return parsed.version;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
53
|
-
/* try next candidate */
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return "";
|
|
57
|
-
}
|
|
58
|
-
const WORKFLOW_VERSION_RE = /^#\s*auriga Workflow\s*\(v([\d.]+)\)/m;
|
|
59
26
|
async function tryReadFile(p) {
|
|
60
27
|
try {
|
|
61
28
|
return await readFile(p, "utf8");
|
|
@@ -66,24 +33,21 @@ async function tryReadFile(p) {
|
|
|
66
33
|
}
|
|
67
34
|
export async function buildScanCatalog(packageRoot) {
|
|
68
35
|
const dist = loadCatalog(packageRoot);
|
|
69
|
-
// Workflow version
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
// hashes the entire skill directory (every file, sorted), which doesn't
|
|
80
|
-
// line up with the scanner's per-file model — we deliberately ignore it.
|
|
81
|
-
const skillsRoot = path.join(packageRoot, ".agents", "skills");
|
|
36
|
+
// Workflow version — baked from CLAUDE.md header at build time. See
|
|
37
|
+
// module comment for the "no runtime reads outside dist/" rule.
|
|
38
|
+
const workflowVersion = dist.workflowVersion ?? "";
|
|
39
|
+
// Skills: drift detection deliberately deferred to `npx skills update
|
|
40
|
+
// --project`, which already compares against the skill's own upstream
|
|
41
|
+
// repo HEAD. Our catalog snapshot would only know "what auriga-cli
|
|
42
|
+
// shipped at this CLI release" — at best a stale proxy that mis-reports
|
|
43
|
+
// legitimate user-side updates as drift. Setting expectedHash to "" puts
|
|
44
|
+
// classifySkillByFile into wildcard mode: row reports installed if
|
|
45
|
+
// SKILL.md exists, not-installed otherwise; never update-available.
|
|
82
46
|
const skills = {};
|
|
83
47
|
for (const entry of dist.workflowSkills) {
|
|
84
48
|
skills[entry.name] = {
|
|
85
49
|
description: entry.description,
|
|
86
|
-
expectedHash:
|
|
50
|
+
expectedHash: "",
|
|
87
51
|
isWorkflow: true,
|
|
88
52
|
};
|
|
89
53
|
}
|
|
@@ -91,74 +55,37 @@ export async function buildScanCatalog(packageRoot) {
|
|
|
91
55
|
for (const entry of dist.recommendedSkills) {
|
|
92
56
|
recommendedSkills[entry.name] = {
|
|
93
57
|
description: entry.description,
|
|
94
|
-
expectedHash:
|
|
58
|
+
expectedHash: "",
|
|
95
59
|
};
|
|
96
60
|
}
|
|
97
|
-
// Plugins:
|
|
98
|
-
//
|
|
99
|
-
//
|
|
61
|
+
// Plugins: agents + expectedVersion + external all come from
|
|
62
|
+
// dist/catalog.json now (baked in src/build/generate-catalog.ts). The
|
|
63
|
+
// previous version of this module read .claude/plugins.json +
|
|
64
|
+
// .agents/plugins/install.json at runtime — those files are NOT in the
|
|
65
|
+
// npm tarball, so for installed users every plugin defaulted to a
|
|
66
|
+
// ["claude"] agent classification (root cause of dual-Agent plugin
|
|
67
|
+
// mis-classification in v1.18.x).
|
|
100
68
|
const plugins = {};
|
|
101
|
-
const claudePluginsText = await tryReadFile(path.join(packageRoot, ".claude", "plugins.json"));
|
|
102
|
-
const claudeNames = new Set();
|
|
103
|
-
if (claudePluginsText) {
|
|
104
|
-
try {
|
|
105
|
-
const parsed = JSON.parse(claudePluginsText);
|
|
106
|
-
for (const p of parsed.plugins ?? []) {
|
|
107
|
-
if (p.name)
|
|
108
|
-
claudeNames.add(p.name);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
catch {
|
|
112
|
-
/* ignore */
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
const codexInstallText = await tryReadFile(path.join(packageRoot, ".agents", "plugins", "install.json"));
|
|
116
|
-
const codexNames = new Set();
|
|
117
|
-
if (codexInstallText) {
|
|
118
|
-
try {
|
|
119
|
-
const parsed = JSON.parse(codexInstallText);
|
|
120
|
-
for (const p of parsed.plugins ?? []) {
|
|
121
|
-
if (p.name)
|
|
122
|
-
codexNames.add(p.name);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
catch {
|
|
126
|
-
/* ignore */
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
69
|
for (const entry of dist.plugins) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
// Apply installs to each side.
|
|
134
|
-
const agents = [];
|
|
135
|
-
if (claudeNames.has(entry.name))
|
|
136
|
-
agents.push("claude");
|
|
137
|
-
if (codexNames.has(entry.name))
|
|
138
|
-
agents.push("codex");
|
|
139
|
-
if (agents.length === 0)
|
|
140
|
-
agents.push("claude"); // unknown defaults to claude
|
|
141
|
-
// Bake expectedVersion from the owned plugin's manifest. For Claude-side
|
|
142
|
-
// plugins prefer plugins/<name>/.claude-plugin/plugin.json; fall back to
|
|
143
|
-
// .codex-plugin/plugin.json for codex-only plugins (e.g.
|
|
144
|
-
// session-instructions-loader). External-marketplace plugins (skill-creator,
|
|
145
|
-
// claude-md-management, codex) have no local manifest — they install from
|
|
146
|
-
// their upstream marketplace, so we deliberately leave expectedVersion
|
|
147
|
-
// undefined. The scanner then falls through to "trust whatever is installed",
|
|
148
|
-
// which matches what the user agreed to when they registered the upstream.
|
|
149
|
-
const expectedVersion = await readPluginManifestVersion(packageRoot, entry.name);
|
|
70
|
+
const agents = Array.isArray(entry.agents) && entry.agents.length > 0
|
|
71
|
+
? [...entry.agents]
|
|
72
|
+
: ["claude"]; // safety fallback: unknown shape defaults to claude
|
|
150
73
|
plugins[entry.name] = {
|
|
151
74
|
description: entry.description,
|
|
152
75
|
agents,
|
|
153
|
-
...(expectedVersion
|
|
76
|
+
...(typeof entry.expectedVersion === "string" && entry.expectedVersion.length > 0
|
|
77
|
+
? { expectedVersion: entry.expectedVersion }
|
|
78
|
+
: {}),
|
|
79
|
+
...(entry.external === true ? { external: true } : {}),
|
|
154
80
|
};
|
|
155
81
|
}
|
|
156
|
-
// Hooks:
|
|
157
|
-
//
|
|
158
|
-
//
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
//
|
|
82
|
+
// Hooks: TODO follow-up — bake expectedEvent / expectedMatcher / expectedIf
|
|
83
|
+
// into dist/catalog.json the same way agents are baked. Currently the
|
|
84
|
+
// runtime read of packageRoot/.claude/hooks/hooks.json works in dev
|
|
85
|
+
// (packageRoot === repoRoot) but fails silently for npm-installed users
|
|
86
|
+
// — `package.json` `files` allowlist doesn't ship `.claude/`. So hook
|
|
87
|
+
// drift detection is correct in dev and degraded (always "installed" if
|
|
88
|
+
// marker present) in production. Follow-up bake closes the dev/prod gap.
|
|
162
89
|
const hooksJsonPath = path.join(packageRoot, ".claude", "hooks", "hooks.json");
|
|
163
90
|
const hooksJsonRaw = await tryReadFile(hooksJsonPath);
|
|
164
91
|
const hooksJson = hooksJsonRaw ? JSON.parse(hooksJsonRaw) : {};
|
package/dist/state.d.ts
CHANGED
|
@@ -15,6 +15,12 @@ export interface Catalog {
|
|
|
15
15
|
/** Agents this plugin can install into. Length 1 or 2. */
|
|
16
16
|
agents: ("claude" | "codex")[];
|
|
17
17
|
expectedVersion?: string;
|
|
18
|
+
/** When true, this plugin is published in an UPSTREAM marketplace
|
|
19
|
+
* (skill-creator / claude-md-management / codex), not in this repo.
|
|
20
|
+
* Classifier MUST NOT report `update-available` for external plugins —
|
|
21
|
+
* those upgrade through `claude plugins update`, not us. The UI surfaces
|
|
22
|
+
* an EXTERNAL badge so users know to defer to the upstream tool. */
|
|
23
|
+
external?: boolean;
|
|
18
24
|
}>;
|
|
19
25
|
hooks: Record<string, {
|
|
20
26
|
description: string;
|
package/dist/state.js
CHANGED
|
@@ -373,9 +373,13 @@ function degradedClaudeRow(id, def, scope) {
|
|
|
373
373
|
expectedVersion: def.expectedVersion,
|
|
374
374
|
versionSource: "upstream-live",
|
|
375
375
|
observedScope: scope,
|
|
376
|
+
...(def.external === true ? { external: true } : {}),
|
|
376
377
|
};
|
|
377
378
|
}
|
|
378
379
|
function classifyClaudePlugin(id, def, installed, available, scope) {
|
|
380
|
+
// `external` propagates onto every return below so the UI can surface the
|
|
381
|
+
// EXTERNAL badge regardless of install state.
|
|
382
|
+
const externalFlag = def.external === true ? { external: true } : {};
|
|
379
383
|
if (!installed || typeof installed.version !== "string") {
|
|
380
384
|
return {
|
|
381
385
|
id,
|
|
@@ -385,9 +389,31 @@ function classifyClaudePlugin(id, def, installed, available, scope) {
|
|
|
385
389
|
expectedVersion: typeof available?.source?.ref === "string" ? available.source.ref : def.expectedVersion,
|
|
386
390
|
versionSource: "upstream-live",
|
|
387
391
|
observedScope: scope,
|
|
392
|
+
...externalFlag,
|
|
388
393
|
};
|
|
389
394
|
}
|
|
390
395
|
const installedVersion = installed.version;
|
|
396
|
+
// External plugin short-circuit: we don't own these, so we don't claim
|
|
397
|
+
// authority on "what version they should be at". `claude plugins update`
|
|
398
|
+
// is the right channel — the scanner just confirms presence. Status stays
|
|
399
|
+
// "installed" even if installed.version differs from any signal we have.
|
|
400
|
+
// The catalog deliberately omits `expectedVersion` for externals, but we
|
|
401
|
+
// double-down with this guard so a future regression that accidentally
|
|
402
|
+
// populates expectedVersion still can't flip externals to update-available.
|
|
403
|
+
if (def.external === true) {
|
|
404
|
+
return {
|
|
405
|
+
id,
|
|
406
|
+
description: def.description,
|
|
407
|
+
status: "installed",
|
|
408
|
+
agents: ["claude"],
|
|
409
|
+
currentVersion: installedVersion,
|
|
410
|
+
// Don't surface any "expected" on externals — the upstream tool owns
|
|
411
|
+
// the version conversation.
|
|
412
|
+
versionSource: "upstream-live",
|
|
413
|
+
observedScope: scope,
|
|
414
|
+
...externalFlag,
|
|
415
|
+
};
|
|
416
|
+
}
|
|
391
417
|
const ref = available?.source?.ref;
|
|
392
418
|
const normalizedAvailable = parseRef(typeof ref === "string" ? ref : undefined);
|
|
393
419
|
const normalizedInstalled = parseRef(installedVersion);
|
|
@@ -421,6 +447,7 @@ function classifyClaudePlugin(id, def, installed, available, scope) {
|
|
|
421
447
|
expectedVersion: expectedRaw,
|
|
422
448
|
versionSource,
|
|
423
449
|
observedScope: scope,
|
|
450
|
+
...externalFlag,
|
|
424
451
|
};
|
|
425
452
|
}
|
|
426
453
|
if (normalizedInstalled !== null && normalizedInstalled === expectedNormalized) {
|
|
@@ -433,6 +460,7 @@ function classifyClaudePlugin(id, def, installed, available, scope) {
|
|
|
433
460
|
expectedVersion: expectedRaw,
|
|
434
461
|
versionSource,
|
|
435
462
|
observedScope: scope,
|
|
463
|
+
...externalFlag,
|
|
436
464
|
};
|
|
437
465
|
}
|
|
438
466
|
return {
|
|
@@ -444,6 +472,7 @@ function classifyClaudePlugin(id, def, installed, available, scope) {
|
|
|
444
472
|
expectedVersion: expectedRaw,
|
|
445
473
|
versionSource,
|
|
446
474
|
observedScope: scope,
|
|
475
|
+
...externalFlag,
|
|
447
476
|
};
|
|
448
477
|
}
|
|
449
478
|
// ---------------------------------------------------------------------------
|
|
@@ -529,10 +558,12 @@ function degradedCodexRow(id, def) {
|
|
|
529
558
|
expectedVersion: def.expectedVersion,
|
|
530
559
|
versionSource: "catalog",
|
|
531
560
|
observedScope: "user",
|
|
561
|
+
...(def.external === true ? { external: true } : {}),
|
|
532
562
|
};
|
|
533
563
|
}
|
|
534
564
|
function classifyCodexPlugin(id, def, enabled, fsVersion) {
|
|
535
565
|
const expectedVersion = def.expectedVersion;
|
|
566
|
+
const externalFlag = def.external === true ? { external: true } : {};
|
|
536
567
|
if (!enabled) {
|
|
537
568
|
return {
|
|
538
569
|
id,
|
|
@@ -542,6 +573,7 @@ function classifyCodexPlugin(id, def, enabled, fsVersion) {
|
|
|
542
573
|
expectedVersion,
|
|
543
574
|
versionSource: "catalog",
|
|
544
575
|
observedScope: "user",
|
|
576
|
+
...externalFlag,
|
|
545
577
|
};
|
|
546
578
|
}
|
|
547
579
|
if (!fsVersion) {
|
|
@@ -553,6 +585,22 @@ function classifyCodexPlugin(id, def, enabled, fsVersion) {
|
|
|
553
585
|
expectedVersion,
|
|
554
586
|
versionSource: "catalog",
|
|
555
587
|
observedScope: "user",
|
|
588
|
+
...externalFlag,
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
// External plugin short-circuit, same rationale as classifyClaudePlugin:
|
|
592
|
+
// we defer authority to `codex plugin marketplace update` and never flag
|
|
593
|
+
// update-available for upstream-owned plugins.
|
|
594
|
+
if (def.external === true) {
|
|
595
|
+
return {
|
|
596
|
+
id,
|
|
597
|
+
description: def.description,
|
|
598
|
+
status: "installed",
|
|
599
|
+
agents: ["codex"],
|
|
600
|
+
currentVersion: fsVersion,
|
|
601
|
+
versionSource: "catalog",
|
|
602
|
+
observedScope: "user",
|
|
603
|
+
...externalFlag,
|
|
556
604
|
};
|
|
557
605
|
}
|
|
558
606
|
if (!expectedVersion || fsVersion === expectedVersion) {
|
|
@@ -565,6 +613,7 @@ function classifyCodexPlugin(id, def, enabled, fsVersion) {
|
|
|
565
613
|
expectedVersion,
|
|
566
614
|
versionSource: "catalog",
|
|
567
615
|
observedScope: "user",
|
|
616
|
+
...externalFlag,
|
|
568
617
|
};
|
|
569
618
|
}
|
|
570
619
|
return {
|
|
@@ -576,6 +625,7 @@ function classifyCodexPlugin(id, def, enabled, fsVersion) {
|
|
|
576
625
|
expectedVersion,
|
|
577
626
|
versionSource: "catalog",
|
|
578
627
|
observedScope: "user",
|
|
628
|
+
...externalFlag,
|
|
579
629
|
};
|
|
580
630
|
}
|
|
581
631
|
/** Return the set of plugin ids whose `[plugins."<id>"]` table has
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "auriga-cli",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.4",
|
|
4
4
|
"description": "Interactive CLI to install Claude Code harness modules (Workflow, Skills, Recommended Skills, Plugins, Hooks)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"dev": "tsc --watch",
|
|
26
26
|
"start": "node dist/cli.js",
|
|
27
27
|
"pretest": "npm run build",
|
|
28
|
-
"test": "tsc -p tsconfig.test.json && DEV=1 node --test --experimental-test-module-mocks dist-test/tests/hooks.test.js dist-test/tests/hooks-uninstall.test.js dist-test/tests/skills.test.js dist-test/tests/skills-uninstall.test.js dist-test/tests/catalog.test.js dist-test/tests/cli-parse.test.js dist-test/tests/install-nontty.test.js dist-test/tests/plugins.test.js dist-test/tests/plugins-uninstall.test.js dist-test/tests/content-fetch.test.js dist-test/tests/utils.test.js dist-test/tests/guide.test.js dist-test/tests/validators.test.js dist-test/tests/entrypoint.test.js dist-test/tests/state.test.js dist-test/tests/server.test.js dist-test/tests/server-auth.test.js dist-test/tests/server-apply.test.js dist-test/tests/apply-handlers.test.js dist-test/tests/ui-fetch.test.js dist-test/tests/workflow-uninstall.test.js",
|
|
29
|
-
"test:watch": "tsc -p tsconfig.test.json --watch & node --test --watch --experimental-test-module-mocks dist-test/tests/hooks.test.js dist-test/tests/hooks-uninstall.test.js dist-test/tests/skills.test.js dist-test/tests/skills-uninstall.test.js dist-test/tests/catalog.test.js dist-test/tests/cli-parse.test.js dist-test/tests/install-nontty.test.js dist-test/tests/plugins.test.js dist-test/tests/plugins-uninstall.test.js dist-test/tests/content-fetch.test.js dist-test/tests/utils.test.js dist-test/tests/guide.test.js dist-test/tests/validators.test.js dist-test/tests/entrypoint.test.js dist-test/tests/state.test.js dist-test/tests/server.test.js dist-test/tests/server-auth.test.js dist-test/tests/server-apply.test.js dist-test/tests/apply-handlers.test.js dist-test/tests/ui-fetch.test.js dist-test/tests/workflow-uninstall.test.js",
|
|
28
|
+
"test": "tsc -p tsconfig.test.json && DEV=1 node --test --experimental-test-module-mocks dist-test/tests/hooks.test.js dist-test/tests/hooks-uninstall.test.js dist-test/tests/skills.test.js dist-test/tests/skills-uninstall.test.js dist-test/tests/catalog.test.js dist-test/tests/cli-parse.test.js dist-test/tests/install-nontty.test.js dist-test/tests/plugins.test.js dist-test/tests/plugins-uninstall.test.js dist-test/tests/content-fetch.test.js dist-test/tests/utils.test.js dist-test/tests/guide.test.js dist-test/tests/validators.test.js dist-test/tests/entrypoint.test.js dist-test/tests/state.test.js dist-test/tests/server.test.js dist-test/tests/server-auth.test.js dist-test/tests/server-apply.test.js dist-test/tests/apply-handlers.test.js dist-test/tests/ui-fetch.test.js dist-test/tests/workflow-uninstall.test.js dist-test/tests/tarball-shape.test.js",
|
|
29
|
+
"test:watch": "tsc -p tsconfig.test.json --watch & node --test --watch --experimental-test-module-mocks dist-test/tests/hooks.test.js dist-test/tests/hooks-uninstall.test.js dist-test/tests/skills.test.js dist-test/tests/skills-uninstall.test.js dist-test/tests/catalog.test.js dist-test/tests/cli-parse.test.js dist-test/tests/install-nontty.test.js dist-test/tests/plugins.test.js dist-test/tests/plugins-uninstall.test.js dist-test/tests/content-fetch.test.js dist-test/tests/utils.test.js dist-test/tests/guide.test.js dist-test/tests/validators.test.js dist-test/tests/entrypoint.test.js dist-test/tests/state.test.js dist-test/tests/server.test.js dist-test/tests/server-auth.test.js dist-test/tests/server-apply.test.js dist-test/tests/apply-handlers.test.js dist-test/tests/ui-fetch.test.js dist-test/tests/workflow-uninstall.test.js dist-test/tests/tarball-shape.test.js",
|
|
30
30
|
"pretest:e2e": "npm run build",
|
|
31
31
|
"test:e2e": "tsc -p tsconfig.test.json && node --test dist-test/tests/e2e-install.test.js",
|
|
32
32
|
"pretest:web-ui-e2e": "npm run build && npm --prefix ui ci && npm --prefix ui run build",
|