@tryaura/aura-cli 0.1.1 → 0.2.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/bin/aura.js +4 -3
- package/dist/index.d.ts +12 -2
- package/dist/index.js +2 -2
- package/dist/plugins/index.d.ts +1 -1
- package/dist/plugins/index.js +1 -1
- package/dist/{plugins-DDfc7XT9.js → plugins-Dbasvr1u.js} +86 -83
- package/dist/{run-ZDkvqvZb.js → run.boundary-CF5kZTH3.js} +3991 -1377
- package/dist/{shared-link-plan-BigeLxDX.js → shared-link-plan-D8fxdFYv.js} +70 -3
- package/dist/{types-DmBu6g0d.d.ts → types--E7zqKfw.d.ts} +4 -2
- package/package.json +5 -5
- package/schema/check-output-v1.schema.json +18 -1
package/dist/bin/aura.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as OFFICIAL_REGISTRY_OPTIONS, t as OFFICIAL_PLUGINS } from "../plugins-
|
|
3
|
-
import { t as runCli } from "../run-
|
|
2
|
+
import { n as OFFICIAL_REGISTRY_OPTIONS, t as OFFICIAL_PLUGINS } from "../plugins-Dbasvr1u.js";
|
|
3
|
+
import { t as runCli } from "../run.boundary-CF5kZTH3.js";
|
|
4
4
|
//#endregion
|
|
5
5
|
//#region src/bin.ts
|
|
6
6
|
await runCli({
|
|
@@ -8,7 +8,8 @@ await runCli({
|
|
|
8
8
|
command: "aura",
|
|
9
9
|
description: "Agent Unification & Repair Assistant",
|
|
10
10
|
displayName: "Aura",
|
|
11
|
-
|
|
11
|
+
docsUrl: "https://tryaura.sh/docs/introduction",
|
|
12
|
+
version: "0.2.1"
|
|
12
13
|
},
|
|
13
14
|
plugins: OFFICIAL_PLUGINS,
|
|
14
15
|
registry: OFFICIAL_REGISTRY_OPTIONS
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as CliRuntime, i as CliRegistryOptions, n as CliDistro, r as CliExitCode, t as CliBranding } from "./types
|
|
1
|
+
import { a as CliRuntime, i as CliRegistryOptions, n as CliDistro, r as CliExitCode, t as CliBranding } from "./types--E7zqKfw.js";
|
|
2
2
|
import { AdapterSupport, AuraConfigurationProvenance, FindingLocation, FindingPresentation, Fixability, HttpFailureReason, HttpPostRequest, HttpPostResult, JsonObject, Scope, Severity, TelemetryEvent, TelemetrySink, TelemetrySink as TelemetrySink$1 } from "@tryaura/aura-sdk";
|
|
3
3
|
//#region src/http-telemetry-sink.d.ts
|
|
4
4
|
/** A privacy-safe reason one HTTP delivery was dropped. */
|
|
@@ -93,6 +93,14 @@ interface ReportDiagnostic {
|
|
|
93
93
|
readonly path?: string | undefined;
|
|
94
94
|
readonly phase: "check" | "detect" | "files" | "fix" | "parse" | "read" | "support";
|
|
95
95
|
}
|
|
96
|
+
interface ReportRepositoryPreset {
|
|
97
|
+
readonly path: string;
|
|
98
|
+
readonly status: "applied" | "held";
|
|
99
|
+
}
|
|
100
|
+
/** Configuration state that affects how a check document should be interpreted. */
|
|
101
|
+
interface ReportConfiguration {
|
|
102
|
+
readonly repositoryPreset?: ReportRepositoryPreset | undefined;
|
|
103
|
+
}
|
|
96
104
|
type ReportStatus = "clean" | "empty" | "error" | "operational-error" | "warning";
|
|
97
105
|
interface ReportFixOperation {
|
|
98
106
|
readonly conflict?: string | undefined;
|
|
@@ -111,6 +119,7 @@ interface ReportFix {
|
|
|
111
119
|
}
|
|
112
120
|
interface CheckReportV1 {
|
|
113
121
|
readonly apps: readonly ReportApp[];
|
|
122
|
+
readonly configuration?: ReportConfiguration | undefined;
|
|
114
123
|
readonly diagnostics: readonly ReportDiagnostic[];
|
|
115
124
|
readonly findings: readonly ReportFinding[];
|
|
116
125
|
readonly fixes?: readonly ReportFix[] | undefined;
|
|
@@ -122,6 +131,7 @@ interface CheckReportV1 {
|
|
|
122
131
|
}
|
|
123
132
|
type CheckReport = CheckReportV1;
|
|
124
133
|
interface CheckExplanationV1 {
|
|
134
|
+
readonly configuration?: ReportConfiguration | undefined;
|
|
125
135
|
readonly enabled: boolean;
|
|
126
136
|
readonly explain: string;
|
|
127
137
|
readonly fixability: Fixability;
|
|
@@ -149,4 +159,4 @@ type CheckExplanation = CheckExplanationV1;
|
|
|
149
159
|
declare function runCli(distro: CliDistro, runtime?: CliRuntime): Promise<CliExitCode>;
|
|
150
160
|
declare function createHttpTelemetrySink(options: HttpTelemetrySinkOptions): TelemetrySink$1;
|
|
151
161
|
//#endregion
|
|
152
|
-
export { type CheckCounts, type CheckExplanation, type CheckExplanationV1, type CheckReport, type CheckReportV1, type CheckSummary, type CliBranding, type CliDistro, type CliExitCode, type CliRegistryOptions, type CliRuntime, type HttpTelemetryDeliveryFailure, type HttpTelemetrySinkOptions, type PassedCheck, type ReportApp, type ReportDiagnostic, type ReportFinding, type ReportFix, type ReportFixOperation, type ReportStatus, type TelemetryEvent, type TelemetrySink, createHttpTelemetrySink, runCli };
|
|
162
|
+
export { type CheckCounts, type CheckExplanation, type CheckExplanationV1, type CheckReport, type CheckReportV1, type CheckSummary, type CliBranding, type CliDistro, type CliExitCode, type CliRegistryOptions, type CliRuntime, type HttpTelemetryDeliveryFailure, type HttpTelemetrySinkOptions, type PassedCheck, type ReportApp, type ReportConfiguration, type ReportDiagnostic, type ReportFinding, type ReportFix, type ReportFixOperation, type ReportRepositoryPreset, type ReportStatus, type TelemetryEvent, type TelemetrySink, createHttpTelemetrySink, runCli };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as vetHttpUrl, n as clampHttpTimeout, r as failureReason, t as runCli } from "./run-
|
|
2
|
-
//#region ../core/src/http-post.ts
|
|
1
|
+
import { i as vetHttpUrl, n as clampHttpTimeout, r as failureReason, t as runCli } from "./run.boundary-CF5kZTH3.js";
|
|
2
|
+
//#region ../core/src/http-post.boundary.ts
|
|
3
3
|
/**
|
|
4
4
|
* Creates a bounded, TLS-only JSON POST that never rejects.
|
|
5
5
|
*
|
package/dist/plugins/index.d.ts
CHANGED
package/dist/plugins/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as codexPlugin, i as claudeCodePlugin, n as OFFICIAL_REGISTRY_OPTIONS, o as cursorPlugin, r as checksCorePlugin, s as officialContentPlugin, t as OFFICIAL_PLUGINS } from "../plugins-
|
|
1
|
+
import { a as codexPlugin, i as claudeCodePlugin, n as OFFICIAL_REGISTRY_OPTIONS, o as cursorPlugin, r as checksCorePlugin, s as officialContentPlugin, t as OFFICIAL_PLUGINS } from "../plugins-Dbasvr1u.js";
|
|
2
2
|
export { OFFICIAL_PLUGINS, OFFICIAL_REGISTRY_OPTIONS, checksCorePlugin, claudeCodePlugin, codexPlugin, cursorPlugin, officialContentPlugin };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { G as src_default$4, I as createAuraManifestWriteOperation, K as pluralize, S as readManagedBlock, W as SHARED_INSTRUCTIONS_TEMPLATE, _ as planSharedSkillTreeUpdate, b as reconcileManagedSnippet, c as planManifestMcpConvergence, f as isAuraOwnedSkillTarget, g as managedContentRevisionStatus, h as skillDeploymentStatus, i as planMcpSecretRemediation, l as planMcpServerRemoval, m as sharedSkillsRoot, n as canPlanMcpSecretRemediation, o as mcpConvergenceBlockers, p as planSkillDeployment, t as planSharedInstructionLink, v as reconcileParsedManagedBlock, y as diffManagedSnippet } from "./shared-link-plan-
|
|
1
|
+
import { G as src_default$4, I as createAuraManifestWriteOperation, K as pluralize, S as readManagedBlock, W as SHARED_INSTRUCTIONS_TEMPLATE, _ as planSharedSkillTreeUpdate, b as reconcileManagedSnippet, c as planManifestMcpConvergence, f as isAuraOwnedSkillTarget, g as managedContentRevisionStatus, h as skillDeploymentStatus, i as planMcpSecretRemediation, l as planMcpServerRemoval, m as sharedSkillsRoot, n as canPlanMcpSecretRemediation, o as mcpConvergenceBlockers, p as planSkillDeployment, q as displayPath, t as planSharedInstructionLink, v as reconcileParsedManagedBlock, y as diffManagedSnippet } from "./shared-link-plan-D8fxdFYv.js";
|
|
2
2
|
import { EMPTY_COLLECTION, McpWriteError, SHARED_INSTRUCTIONS_TEMPLATE_TOKEN, TIMEOUT_EXIT_CODE, collectJsonMcpServers, collectMcpServers, configStringArray, configStringRecord, defineAdapter, defineCheck, definePlugin, detectExecutable, detectLineEnding, inspectJsonMcpSecrets, isConfigRecord, isFileReference, jsonMcpEntry, jsonMcpSecretTransform, maskMarkdownCode, mcpCommandEntry, mcpEnvironmentVariableNames, mcpWriteResult, normalizeMcpServerDefinition, parseAtImports, parseConfigObject, parseInstalledSkills, parseJsonMcpConfig, redactMcpArguments, referenceTargetPath, sanitizeMcpUrl, skillDirectorySpecs, splitSourceLines, stdioTransport, writeJsonMcpServers } from "@tryaura/aura-sdk";
|
|
3
|
-
import { dirname, extname, isAbsolute, join,
|
|
3
|
+
import { dirname, extname, isAbsolute, join, resolve, sep } from "node:path";
|
|
4
4
|
import { parse, stringify } from "smol-toml";
|
|
5
5
|
import { Buffer } from "node:buffer";
|
|
6
6
|
import { parseTOML } from "toml-eslint-parser";
|
|
@@ -1194,12 +1194,10 @@ function validateToml(content, message) {
|
|
|
1194
1194
|
//#endregion
|
|
1195
1195
|
//#region ../../plugins/adapter-codex/src/project-directories.ts
|
|
1196
1196
|
/**
|
|
1197
|
-
* Every directory
|
|
1197
|
+
* Every directory Codex searches for project instructions, from `cwd` to the repository root.
|
|
1198
1198
|
*
|
|
1199
|
-
*
|
|
1200
|
-
*
|
|
1201
|
-
* reads one `AGENTS.md` per directory from the root down to `cwd`. Both are the same walk read in
|
|
1202
|
-
* opposite directions, so they share it rather than each keeping a copy.
|
|
1199
|
+
* Codex reads one `AGENTS.md` per directory from the root down to `cwd`. Project trust deliberately
|
|
1200
|
+
* does not share this walk: Codex checks only the exact cwd and the primary Git checkout for trust.
|
|
1203
1201
|
*
|
|
1204
1202
|
* Without a repository root there is nothing to walk to: every ancestor of the working directory is
|
|
1205
1203
|
* a different project as far as Codex is concerned, so only `cwd` is considered. The same answer
|
|
@@ -1351,11 +1349,10 @@ function remainingBytes(selected, files, remaining) {
|
|
|
1351
1349
|
/**
|
|
1352
1350
|
* Reads the current project's trust marker from Codex's shared configuration.
|
|
1353
1351
|
*
|
|
1354
|
-
* Codex
|
|
1355
|
-
*
|
|
1356
|
-
*
|
|
1357
|
-
*
|
|
1358
|
-
* recorded answer wins.
|
|
1352
|
+
* Codex first checks the exact directory it was launched in, then the primary Git checkout. The
|
|
1353
|
+
* second identity matters for linked worktrees: Codex resolves their `.git` pointer back to the
|
|
1354
|
+
* main checkout, so trusting that checkout covers every associated worktree unless an exact cwd
|
|
1355
|
+
* entry overrides it.
|
|
1359
1356
|
*/
|
|
1360
1357
|
function parseProjectTrust(file, lookup) {
|
|
1361
1358
|
const root = parseConfigObject(file.content, parse);
|
|
@@ -1363,7 +1360,7 @@ function parseProjectTrust(file, lookup) {
|
|
|
1363
1360
|
const projects = root["projects"];
|
|
1364
1361
|
if (!isConfigRecord(projects)) return "unknown";
|
|
1365
1362
|
const entries = new Map(Object.entries(projects).map(([key, value]) => [normalize(key), value]));
|
|
1366
|
-
for (const directory of
|
|
1363
|
+
for (const directory of trustDirectories(lookup)) {
|
|
1367
1364
|
const project = entries.get(directory);
|
|
1368
1365
|
if (!isConfigRecord(project)) continue;
|
|
1369
1366
|
const trust = project["trust_level"];
|
|
@@ -1371,6 +1368,12 @@ function parseProjectTrust(file, lookup) {
|
|
|
1371
1368
|
}
|
|
1372
1369
|
return "unknown";
|
|
1373
1370
|
}
|
|
1371
|
+
function trustDirectories(lookup) {
|
|
1372
|
+
const cwd = normalize(lookup.cwd);
|
|
1373
|
+
if (lookup.gitMainWorktreeRoot === void 0) return [cwd];
|
|
1374
|
+
const mainWorktreeRoot = normalize(lookup.gitMainWorktreeRoot);
|
|
1375
|
+
return cwd === mainWorktreeRoot ? [cwd] : [cwd, mainWorktreeRoot];
|
|
1376
|
+
}
|
|
1374
1377
|
/** Collapses separators and trailing slashes so a config key and a scanned path compare equal. */
|
|
1375
1378
|
function normalize(directory) {
|
|
1376
1379
|
return resolve(directory);
|
|
@@ -1401,7 +1404,7 @@ const codexAdapter = defineAdapter({
|
|
|
1401
1404
|
mcpWrite: writeMcpServers$1,
|
|
1402
1405
|
mcpSecrets: transformMcpSecrets$1,
|
|
1403
1406
|
parse: (input) => {
|
|
1404
|
-
const { cwd, files,
|
|
1407
|
+
const { cwd, files, gitMainWorktreeRoot, homeDir } = input;
|
|
1405
1408
|
const mcp = files.get(CODEX_SOURCE_IDS.mcp);
|
|
1406
1409
|
const mcpConfig = mcp === void 0 ? EMPTY_MCP : parseMcpServers$1(mcp);
|
|
1407
1410
|
const instructions = selectInstructionFiles(files, {
|
|
@@ -1414,7 +1417,7 @@ const codexAdapter = defineAdapter({
|
|
|
1414
1417
|
mcpSecretSightings: mcpConfig.secretSightings ?? [],
|
|
1415
1418
|
metadata: { [CODEX_PROJECT_TRUST_KEY]: mcp === void 0 ? "unknown" : parseProjectTrust(mcp, {
|
|
1416
1419
|
cwd,
|
|
1417
|
-
|
|
1420
|
+
gitMainWorktreeRoot
|
|
1418
1421
|
}) },
|
|
1419
1422
|
problems: [...shadowedEntryProblems(instructions.shadowed), ...unusableConfig(mcp, mcpConfig.malformed)],
|
|
1420
1423
|
skills: parseInstalledSkills(CODEX_ADAPTER_ID, input, SKILL_DIRECTORIES),
|
|
@@ -2162,7 +2165,7 @@ const env004 = defineCheck({
|
|
|
2162
2165
|
detect: (model) => detectConflicts(model),
|
|
2163
2166
|
explain: `Claude Code can appear unable to work when its effective default permission mode is plan or dontAsk. Codex skips project-scoped configuration when a project is untrusted, so Aura also reports projects that are not explicitly trusted.
|
|
2164
2167
|
|
|
2165
|
-
Claude Code: edit the settings file named by the finding and choose default or acceptEdits as appropriate. Codex: edit ~/.codex/config.toml and
|
|
2168
|
+
Claude Code: edit the settings file named by the finding and choose default or acceptEdits as appropriate. Codex: after reviewing the repository, edit ~/.codex/config.toml and trust the exact working directory or the primary Git checkout. Codex resolves linked worktrees back to that primary checkout.`,
|
|
2166
2169
|
fix: (finding, model) => guidedFix$2(finding, model),
|
|
2167
2170
|
fixability: "guided",
|
|
2168
2171
|
id: "ENV-004",
|
|
@@ -2198,7 +2201,7 @@ function codexFindings(app) {
|
|
|
2198
2201
|
if (trust === "trusted" || trust === "unreadable") return [];
|
|
2199
2202
|
const path = sourcePath$2(app, CODEX_SOURCE_IDS.mcp);
|
|
2200
2203
|
return [{
|
|
2201
|
-
details: trust === "untrusted" ? "Codex explicitly marks this project untrusted and skips its project-scoped configuration." : "Codex has no trusted entry for this
|
|
2204
|
+
details: trust === "untrusted" ? "Codex explicitly marks this project untrusted and skips its project-scoped configuration." : "Codex has no trusted entry for this working directory or its primary Git checkout, so project-scoped configuration may be unavailable until trust is confirmed.",
|
|
2202
2205
|
id: `codex-project-trust:${trust}`,
|
|
2203
2206
|
...path === void 0 ? {} : { locations: [{ path }] },
|
|
2204
2207
|
message: trust === "untrusted" ? "Codex marks this project as untrusted." : "Codex does not mark this project as trusted.",
|
|
@@ -2223,11 +2226,14 @@ function guidedFix$2(finding, model) {
|
|
|
2223
2226
|
summary: "Change Claude Code's restrictive default permission mode."
|
|
2224
2227
|
};
|
|
2225
2228
|
}
|
|
2226
|
-
if (appId === "codex" && model.projectRoot !== void 0)
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2229
|
+
if (appId === "codex" && model.projectRoot !== void 0) {
|
|
2230
|
+
const trustRoot = model.gitMainWorktreeRoot ?? model.cwd;
|
|
2231
|
+
return {
|
|
2232
|
+
manualSteps: [`After reviewing the repository, add [projects.${JSON.stringify(trustRoot)}] with trust_level = "trusted" in ~/.codex/config.toml.`, "Restart Codex in the project and run `aura check` again."],
|
|
2233
|
+
operations: [],
|
|
2234
|
+
summary: "Trust the current project in Codex."
|
|
2235
|
+
};
|
|
2236
|
+
}
|
|
2231
2237
|
}
|
|
2232
2238
|
//#endregion
|
|
2233
2239
|
//#region ../../plugins/checks-core/src/hashing.ts
|
|
@@ -2454,19 +2460,15 @@ function compareParagraphs$1(left, right) {
|
|
|
2454
2460
|
//#region ../../plugins/checks-core/src/instruction-paths.ts
|
|
2455
2461
|
/** Names an instruction file the way a user can address it from the current workspace. */
|
|
2456
2462
|
function displayInstructionPath(path, model) {
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2463
|
+
return displayPath(path, {
|
|
2464
|
+
cwd: model.cwd,
|
|
2465
|
+
homeDir: model.homeDir,
|
|
2466
|
+
...model.projectRoot === void 0 ? {} : { projectRoot: model.projectRoot }
|
|
2467
|
+
});
|
|
2461
2468
|
}
|
|
2462
2469
|
function instructionLineRange(startLine, endLine) {
|
|
2463
2470
|
return startLine === endLine ? String(startLine) : `${String(startLine)}-${String(endLine)}`;
|
|
2464
2471
|
}
|
|
2465
|
-
function pathInside(root, path) {
|
|
2466
|
-
const difference = relative(root, path);
|
|
2467
|
-
if (difference.length === 0 || difference === ".." || difference.startsWith(`..${sep}`) || isAbsolute(difference)) return;
|
|
2468
|
-
return difference.split(sep).join("/");
|
|
2469
|
-
}
|
|
2470
2472
|
//#endregion
|
|
2471
2473
|
//#region ../../plugins/checks-core/src/ins-003/clusters.ts
|
|
2472
2474
|
/** Groups duplicate-pair edges into transitive connected components. */
|
|
@@ -2641,6 +2643,11 @@ const duplicateInstructionsCheck = defineCheck({
|
|
|
2641
2643
|
explain: `Repeated guidance across agent instruction files is easy to update in one place and forget in another. Similar copies also consume context repeatedly and can diverge into subtly different rules.
|
|
2642
2644
|
|
|
2643
2645
|
Review each reported cluster and keep its clearest version in the shared instruction source. Remove the redundant copies only after confirming their scopes and conditions are preserved.`,
|
|
2646
|
+
findingGroup: {
|
|
2647
|
+
description: "Keep each piece of guidance in one canonical source.",
|
|
2648
|
+
id: "checks-core/duplicate-instructions",
|
|
2649
|
+
title: "Consolidate duplicated instruction guidance"
|
|
2650
|
+
},
|
|
2644
2651
|
fixability: "manual",
|
|
2645
2652
|
id: "INS-003",
|
|
2646
2653
|
scope: "global",
|
|
@@ -2755,7 +2762,7 @@ const legacyInstructionsCheck = defineCheck({
|
|
|
2755
2762
|
detect: (model) => legacyDocuments(model.instructionFiles).map((legacy) => toFinding(legacy, model)),
|
|
2756
2763
|
explain: `Legacy instruction files are easy to forget after changing agent applications or configuration formats. They may still be loaded unexpectedly, or hold useful guidance that newer application files never received.
|
|
2757
2764
|
|
|
2758
|
-
Re-run the check with \`--fix
|
|
2765
|
+
Re-run the check with \`--fix\` to review the suggested migration steps, then use the \`setup\` command to consolidate selected content. Aura archives originals through its reversible backup history instead of deleting them silently.`,
|
|
2759
2766
|
fix: guidedFix$1,
|
|
2760
2767
|
fixability: "guided",
|
|
2761
2768
|
id: "INS-004",
|
|
@@ -3465,7 +3472,7 @@ const instructionLinkIntegrityCheck = defineCheck({
|
|
|
3465
3472
|
detect: detectLinkProblems,
|
|
3466
3473
|
explain: `Instruction imports must point to files the application can load without cycles or excessive nesting. Broken or unsupported chains silently discard guidance and can leave an agent running with only part of the intended instructions.
|
|
3467
3474
|
|
|
3468
|
-
Re-run the check with \`--fix
|
|
3475
|
+
Re-run the check with \`--fix\` to review the affected source and target paths. Create or correct missing targets, remove one edge from cycles, and flatten chains that exceed the named application's supported depth.`,
|
|
3469
3476
|
fix: guidedFix,
|
|
3470
3477
|
fixability: "guided",
|
|
3471
3478
|
id: "INS-006",
|
|
@@ -4016,6 +4023,11 @@ function findingForProjectSignals(document, report, model) {
|
|
|
4016
4023
|
//#endregion
|
|
4017
4024
|
//#region ../../plugins/checks-core/src/instructions.ts
|
|
4018
4025
|
const READY = "Aura can add the missing link with check --fix.";
|
|
4026
|
+
const SHARED_INSTRUCTION_GROUP = Object.freeze({
|
|
4027
|
+
description: "Create the shared source and connect supported agent applications.",
|
|
4028
|
+
id: "checks-core/shared-instructions",
|
|
4029
|
+
title: "Complete the shared instruction setup"
|
|
4030
|
+
});
|
|
4019
4031
|
const sharedInstructionsCheck = defineCheck({
|
|
4020
4032
|
defaultSeverity: "error",
|
|
4021
4033
|
detect(model) {
|
|
@@ -4036,6 +4048,7 @@ const sharedInstructionsCheck = defineCheck({
|
|
|
4036
4048
|
explain: `A non-empty shared instruction source gives every configured agent application one canonical set of guidance. Without it, application-specific files become independent copies that drift as preferences change.
|
|
4037
4049
|
|
|
4038
4050
|
Re-run the check with \`--fix\` to create the shared source from Aura's starter template. Review the generated ~/agents/AGENTS.md, add personal guidance there, and check again.`,
|
|
4051
|
+
findingGroup: SHARED_INSTRUCTION_GROUP,
|
|
4039
4052
|
fix(_finding, model) {
|
|
4040
4053
|
const shared = model.sharedInstructions;
|
|
4041
4054
|
if (shared.problem !== void 0 || (shared.content?.trim().length ?? 0) > 0) return;
|
|
@@ -4062,6 +4075,7 @@ const sharedInstructionLinksCheck = defineCheck({
|
|
|
4062
4075
|
explain: `Each detected agent application must load the canonical shared instructions through a mechanism its adapter understands. A missing import, native copy, or symlink leaves that application working from different rules even when the shared source is correct.
|
|
4063
4076
|
|
|
4064
4077
|
Re-run the check with \`--fix\` to add the adapter-supported link without replacing unrelated instructions. Inspect the preview first, apply it, then restart the affected application if it caches instruction files.`,
|
|
4078
|
+
findingGroup: SHARED_INSTRUCTION_GROUP,
|
|
4065
4079
|
fix(finding, model) {
|
|
4066
4080
|
const app = model.apps.find((candidate) => candidate.adapterId === findingAppId(finding));
|
|
4067
4081
|
if (app === void 0) return;
|
|
@@ -4079,6 +4093,7 @@ function detectMissingLink(app, model) {
|
|
|
4079
4093
|
const sharedPath = resolve(model.sharedInstructions.path);
|
|
4080
4094
|
if (shared !== void 0 && linksToShared(app, shared, sharedPath)) return [];
|
|
4081
4095
|
const outcome = planSharedInstructionLink(app, model);
|
|
4096
|
+
if ("plan" in outcome && outcome.plan.operations.length === 0) return [];
|
|
4082
4097
|
const blocked = "blocked" in outcome;
|
|
4083
4098
|
return [{
|
|
4084
4099
|
details: blocked ? outcome.blocked : READY,
|
|
@@ -4089,10 +4104,16 @@ function detectMissingLink(app, model) {
|
|
|
4089
4104
|
metadata: { appId: app.adapterId }
|
|
4090
4105
|
}];
|
|
4091
4106
|
}
|
|
4092
|
-
/**
|
|
4107
|
+
/**
|
|
4108
|
+
* Whether the declared entry already carries a link the declared mechanism would have written.
|
|
4109
|
+
*
|
|
4110
|
+
* Target validity belongs to INS-001 and INS-006. INS-002 only owns the link's mechanism and
|
|
4111
|
+
* destination; treating a missing shared source as a missing link produces a zero-operation fix
|
|
4112
|
+
* because the planner correctly sees that the link itself is already converged.
|
|
4113
|
+
*/
|
|
4093
4114
|
function linksToShared(app, shared, sharedPath) {
|
|
4094
4115
|
const entryPath = resolve(shared.entryPath);
|
|
4095
|
-
return app.instructionFiles.some((document) => resolve(document.path) === entryPath && document.links.some((link) =>
|
|
4116
|
+
return app.instructionFiles.some((document) => resolve(document.path) === entryPath && document.links.some((link) => compatibleLink(shared.kind, link.kind) && resolve(link.targetPath) === sharedPath));
|
|
4096
4117
|
}
|
|
4097
4118
|
/** Which parsed link kinds each declared mechanism can be satisfied by. */
|
|
4098
4119
|
function compatibleLink(declared, found) {
|
|
@@ -4269,9 +4290,9 @@ function isSymlinkDocument(document, model) {
|
|
|
4269
4290
|
}
|
|
4270
4291
|
//#endregion
|
|
4271
4292
|
//#region ../../plugins/checks-core/src/mgd-001-fixes.ts
|
|
4272
|
-
const CHECK_ID$
|
|
4293
|
+
const CHECK_ID$4 = "MGD-001";
|
|
4273
4294
|
function guidedFixes$2(finding, model) {
|
|
4274
|
-
if (finding.checkId !== CHECK_ID$
|
|
4295
|
+
if (finding.checkId !== CHECK_ID$4) return [];
|
|
4275
4296
|
const kind = finding.metadata?.["kind"];
|
|
4276
4297
|
if (kind === "malformed") return [malformedMergeChoice(finding)];
|
|
4277
4298
|
if (kind === "unterminated-fence") return [unterminatedFenceChoice(finding)];
|
|
@@ -4442,7 +4463,7 @@ const managedBlockHashCheck = defineCheck({
|
|
|
4442
4463
|
detect: detectManagedBlockDrift,
|
|
4443
4464
|
explain: `Aura hashes each managed snippet so hand edits cannot be overwritten silently. A mismatch means the installed text no longer matches the registered version, so a later setup run must not guess which side should win.
|
|
4444
4465
|
|
|
4445
|
-
Re-run the check with \`--fix
|
|
4466
|
+
Re-run the check with \`--fix\` and choose Keep yours to adopt the edit, Restore to return to registered content, or Merge to review both versions and reconcile them manually. Every executable choice is previewed and backed up before Aura writes.`,
|
|
4446
4467
|
fix: () => void 0,
|
|
4447
4468
|
fixability: "guided",
|
|
4448
4469
|
guidedFixes: guidedFixes$2,
|
|
@@ -4464,7 +4485,7 @@ function findingsForDocument(document, model) {
|
|
|
4464
4485
|
const manifestHash = manifestHashes.get(snippet.id);
|
|
4465
4486
|
return !snippet.hashMatches || manifestHash !== void 0 && manifestHash !== snippet.computedHash;
|
|
4466
4487
|
}).map((snippet) => ({
|
|
4467
|
-
details: "Run `aura check --fix
|
|
4488
|
+
details: "Run `aura check --fix` and choose Keep yours, Restore, or Merge before running setup again.",
|
|
4468
4489
|
id: `${document.sourceId}:${snippet.id}`,
|
|
4469
4490
|
locations: [{
|
|
4470
4491
|
line: snippet.startLine,
|
|
@@ -4480,7 +4501,7 @@ function findingsForDocument(document, model) {
|
|
|
4480
4501
|
}
|
|
4481
4502
|
function unterminatedFenceFinding(document, line, model) {
|
|
4482
4503
|
return {
|
|
4483
|
-
details: "Close the Markdown fence, then run `aura check --fix
|
|
4504
|
+
details: "Close the Markdown fence, then run `aura check --fix` again. Aura will not reconcile this document while its markers are hidden.",
|
|
4484
4505
|
id: `${document.sourceId}:unterminated-fence`,
|
|
4485
4506
|
locations: [{
|
|
4486
4507
|
...line === void 0 ? {} : { line },
|
|
@@ -4682,7 +4703,7 @@ function resolveDriftFirst(contentId) {
|
|
|
4682
4703
|
id: "resolve-drift",
|
|
4683
4704
|
label: "Resolve local edits first",
|
|
4684
4705
|
plan: {
|
|
4685
|
-
manualSteps: [`Run \`aura check --only MGD-001 --fix
|
|
4706
|
+
manualSteps: [`Run \`aura check --only MGD-001 --fix\` and resolve edits to ${contentId}, then review this update again.`],
|
|
4686
4707
|
operations: [],
|
|
4687
4708
|
summary: `Resolve local edits to ${contentId} before updating it.`
|
|
4688
4709
|
}
|
|
@@ -4702,7 +4723,7 @@ function resolveSkillDriftFirst(contentId) {
|
|
|
4702
4723
|
const managedContentUpdateCheck = defineCheck({
|
|
4703
4724
|
defaultSeverity: "info",
|
|
4704
4725
|
detect: detectManagedContentUpdates,
|
|
4705
|
-
explain: "Aura records the exact version and content hash of each managed snippet and skill. When an installed plugin offers a different revision, Aura reports it and waits for a reviewed change instead of silently replacing managed content. A revision that is not newer — a rollback, or one this build cannot order — is reported too, because Aura keeps the recorded revision either way and an unreported hold would look like nothing to do. Pinned selections remain quiet until they are unpinned.\n\nRun `aura check --fix
|
|
4726
|
+
explain: "Aura records the exact version and content hash of each managed snippet and skill. When an installed plugin offers a different revision, Aura reports it and waits for a reviewed change instead of silently replacing managed content. A revision that is not newer — a rollback, or one this build cannot order — is reported too, because Aura keeps the recorded revision either way and an unreported hold would look like nothing to do. Pinned selections remain quiet until they are unpinned.\n\nRun `aura check --fix` to review bundled revisions and vanished snippets. Locally edited content must be resolved first; directory-sourced skill updates stay in `aura setup`, where network and credential approval are explicit.",
|
|
4706
4727
|
fix: () => void 0,
|
|
4707
4728
|
fixability: "guided",
|
|
4708
4729
|
guidedFixes: managedContentUpdateChoices,
|
|
@@ -4794,6 +4815,11 @@ const unmanagedDetectedAppCheck = defineCheck({
|
|
|
4794
4815
|
defaultSeverity: "info",
|
|
4795
4816
|
detect: detectUnmanagedApps,
|
|
4796
4817
|
explain: "Aura can inspect an installed agent application without managing it. This informational check highlights detected applications that have never been accepted or ignored in the Aura manifest.\n\nRun `aura setup` to add the application, or leave it unchecked once to record that Aura should ignore it. There is no automatic fix: the decision belongs to the apps step, and this check never starts a nested command.",
|
|
4818
|
+
findingGroup: {
|
|
4819
|
+
description: "Run `aura setup` to manage them or record an ignore decision.",
|
|
4820
|
+
id: "checks-core/application-management",
|
|
4821
|
+
title: "Decide which detected applications Aura should manage"
|
|
4822
|
+
},
|
|
4797
4823
|
fixability: "manual",
|
|
4798
4824
|
id: "MGD-003",
|
|
4799
4825
|
scope: "global",
|
|
@@ -5053,36 +5079,26 @@ function inlineCredential(transport) {
|
|
|
5053
5079
|
/**
|
|
5054
5080
|
* One row per state, rather than the same three-way branch spelled out for each string.
|
|
5055
5081
|
*
|
|
5056
|
-
* The
|
|
5057
|
-
*
|
|
5058
|
-
*
|
|
5082
|
+
* The strings a state needs were previously parallel ternaries in two functions, so adding a state
|
|
5083
|
+
* meant finding all of them and nothing made them agree. Keyed by state, the compiler requires the
|
|
5084
|
+
* row and the lookups cannot drift.
|
|
5059
5085
|
*/
|
|
5060
5086
|
const CURSOR_STATE_ACTIONS = Object.freeze({
|
|
5061
5087
|
disabled: {
|
|
5062
|
-
choiceId: "enable-in-cursor",
|
|
5063
|
-
choiceLabel: "Enable in Cursor",
|
|
5064
5088
|
guidance: (name) => `Open Cursor, open MCP settings, and enable server ${name}.`,
|
|
5065
|
-
message: (name, displayName) => `MCP server ${name} is disabled in ${displayName}
|
|
5066
|
-
summary: (name) => `Enable MCP server ${name} in Cursor.`
|
|
5089
|
+
message: (name, displayName) => `MCP server ${name} is disabled in ${displayName}.`
|
|
5067
5090
|
},
|
|
5068
5091
|
error: {
|
|
5069
|
-
choiceId: "repair-in-cursor",
|
|
5070
|
-
choiceLabel: "Repair in Cursor",
|
|
5071
5092
|
guidance: (name) => `Open Cursor's MCP settings, inspect the connection error for server ${name}, and repair its configuration or service.`,
|
|
5072
|
-
message: (name, displayName) => `MCP server ${name} in ${displayName} cannot be reached because Cursor reported a connection error
|
|
5073
|
-
summary: (name) => `Repair MCP server ${name} in Cursor.`
|
|
5093
|
+
message: (name, displayName) => `MCP server ${name} in ${displayName} cannot be reached because Cursor reported a connection error.`
|
|
5074
5094
|
},
|
|
5075
5095
|
"needs-approval": {
|
|
5076
|
-
choiceId: "approve-in-cursor",
|
|
5077
|
-
choiceLabel: "Approve in Cursor",
|
|
5078
5096
|
guidance: (name) => `Open Cursor, open MCP settings, and approve server ${name}.`,
|
|
5079
|
-
message: (name, displayName) => `MCP server ${name} in ${displayName} needs approval
|
|
5080
|
-
summary: (name) => `Approve MCP server ${name} in Cursor.`
|
|
5097
|
+
message: (name, displayName) => `MCP server ${name} in ${displayName} needs approval.`
|
|
5081
5098
|
}
|
|
5082
5099
|
});
|
|
5083
5100
|
//#endregion
|
|
5084
5101
|
//#region ../../plugins/checks-core/src/mcp-003-cursor.ts
|
|
5085
|
-
const CHECK_ID$1 = "MCP-003";
|
|
5086
5102
|
/**
|
|
5087
5103
|
* Cursor runtime-state findings that are not superseded by a concrete transport failure.
|
|
5088
5104
|
*
|
|
@@ -5104,23 +5120,6 @@ function cursorMcpStateFindings(app, concretelyFailed) {
|
|
|
5104
5120
|
return state === "error" && concretelyFailed.has(mcpServerNameKey(app.adapterId, name)) ? [] : [cursorStateFinding(app, name, state)];
|
|
5105
5121
|
});
|
|
5106
5122
|
}
|
|
5107
|
-
/** Zero-operation guided action for one Cursor-owned runtime-state finding. */
|
|
5108
|
-
function cursorMcpStateChoice(finding) {
|
|
5109
|
-
if (finding.checkId !== CHECK_ID$1 || finding.metadata?.["appId"] !== "cursor" || finding.metadata?.["kind"] !== "cursor-state") return;
|
|
5110
|
-
const name = finding.metadata["serverName"];
|
|
5111
|
-
const state = finding.metadata["state"];
|
|
5112
|
-
if (typeof name !== "string" || !isActionableState(state)) return;
|
|
5113
|
-
const action = CURSOR_STATE_ACTIONS[state];
|
|
5114
|
-
return {
|
|
5115
|
-
id: action.choiceId,
|
|
5116
|
-
label: action.choiceLabel,
|
|
5117
|
-
plan: {
|
|
5118
|
-
manualSteps: [action.guidance(name), "Run `aura check` again."],
|
|
5119
|
-
operations: [],
|
|
5120
|
-
summary: action.summary(name)
|
|
5121
|
-
}
|
|
5122
|
-
};
|
|
5123
|
-
}
|
|
5124
5123
|
/** Stable identity for the name-level state Cursor reports. */
|
|
5125
5124
|
function mcpServerNameKey(appId, name) {
|
|
5126
5125
|
return `${appId}\0${name}`;
|
|
@@ -5129,6 +5128,7 @@ function cursorStateFinding(app, name, state) {
|
|
|
5129
5128
|
const action = CURSOR_STATE_ACTIONS[state];
|
|
5130
5129
|
return {
|
|
5131
5130
|
details: action.guidance(name),
|
|
5131
|
+
fixability: "manual",
|
|
5132
5132
|
id: `${app.adapterId}:${name}:cursor-${state}`,
|
|
5133
5133
|
message: action.message(name, app.displayName),
|
|
5134
5134
|
metadata: {
|
|
@@ -5150,6 +5150,7 @@ function cursorStateFinding(app, name, state) {
|
|
|
5150
5150
|
function unknownStateFinding(app, name) {
|
|
5151
5151
|
return {
|
|
5152
5152
|
details: `Run \`cursor-agent mcp list\` to see what ${app.displayName} reports for server ${name}, and check whether server ${name} is approved and enabled in its MCP settings.`,
|
|
5153
|
+
fixability: "manual",
|
|
5153
5154
|
id: `${app.adapterId}:${name}:cursor-unknown`,
|
|
5154
5155
|
message: `MCP server ${name}'s state in ${app.displayName} could not be understood.`,
|
|
5155
5156
|
metadata: {
|
|
@@ -5165,6 +5166,7 @@ function unavailableFinding(app, reason) {
|
|
|
5165
5166
|
const cause = reason === "timeout" ? "did not finish in time" : "exited unsuccessfully";
|
|
5166
5167
|
return {
|
|
5167
5168
|
details: `Run \`cursor-agent mcp list\` to see why, then re-run \`aura check\`. Approval and enablement of ${app.displayName}'s MCP servers were not checked; every other MCP check still ran.`,
|
|
5169
|
+
fixability: "manual",
|
|
5168
5170
|
id: `${app.adapterId}:cursor-state-unavailable`,
|
|
5169
5171
|
message: `${app.displayName}'s MCP server states were not read because \`cursor-agent mcp list\` ${cause}.`,
|
|
5170
5172
|
metadata: {
|
|
@@ -5175,9 +5177,6 @@ function unavailableFinding(app, reason) {
|
|
|
5175
5177
|
severity: "info"
|
|
5176
5178
|
};
|
|
5177
5179
|
}
|
|
5178
|
-
function isActionableState(value) {
|
|
5179
|
-
return value === "needs-approval" || value === "disabled" || value === "error";
|
|
5180
|
-
}
|
|
5181
5180
|
//#endregion
|
|
5182
5181
|
//#region ../../plugins/checks-core/src/mcp-003.ts
|
|
5183
5182
|
const CHECK_ID = "MCP-003";
|
|
@@ -5186,7 +5185,7 @@ const mcp003 = defineCheck({
|
|
|
5186
5185
|
detect: detectDeadServers,
|
|
5187
5186
|
explain: `Aura checks stdio commands with filesystem-only PATH resolution, and starts no MCP server of its own. Package launchers such as npx, uvx, and bunx are checked, but Aura does not guess whether the requested package is installed or cached.
|
|
5188
5187
|
|
|
5189
|
-
Remote URLs are silent and generate no network traffic unless \`check --online\` is supplied. Online probes use short, bounded requests without configured authentication headers, and they skip an endpoint whose credentials Aura stripped, because the remaining URL no longer addresses the configured server. A redirect to a private address is reported rather than followed. A timeout or a server-side fault is a warning, not an error: it may not repeat. Re-run with \`--fix
|
|
5188
|
+
Remote URLs are silent and generate no network traffic unless \`check --online\` is supplied. Online probes use short, bounded requests without configured authentication headers, and they skip an endpoint whose credentials Aura stripped, because the remaining URL no longer addresses the configured server. A redirect to a private address is reported rather than followed. A timeout or a server-side fault is a warning, not an error: it may not repeat. Re-run with \`--fix\` to choose whether to repair or remove a server that definitely failed its probe. Cursor separately requires its MCP servers to be approved and enabled in its own settings, which no file records; Aura reads those states by running \`cursor-agent mcp list\` when that CLI is installed and identifies itself. The command is Cursor's, and it connects to servers to answer, so Aura runs it from your home directory: only your own global configuration takes part, never a \`.cursor/mcp.json\` committed to the repository you are in. Aura never approves, enables, or retries a server itself, and every state it reports this way is a warning. Aura also reports an informational reminder when a desired MCP transport references an unset environment variable. It retains only the variable name and whether it is set; credential values never enter the workspace model or report.`,
|
|
5190
5189
|
fix: () => void 0,
|
|
5191
5190
|
fixability: "guided",
|
|
5192
5191
|
guidedFixes: guidedFixes$1,
|
|
@@ -5218,6 +5217,7 @@ function unsetEnvironmentFindings(model) {
|
|
|
5218
5217
|
const credential = catalog?.manifest.credentialEnv.find((candidate) => candidate.name === variableName);
|
|
5219
5218
|
return [{
|
|
5220
5219
|
details: credentialDetails(server.name, variableName, credential, catalog?.manifest.docsUrl),
|
|
5220
|
+
fixability: "manual",
|
|
5221
5221
|
id: `environment:${String(serverIndex)}:${variableName}`,
|
|
5222
5222
|
locations: [{ path: model.manifest.path }],
|
|
5223
5223
|
message: `MCP server ${server.name} needs environment variable ${variableName}.`,
|
|
@@ -5259,8 +5259,6 @@ function findingFor(server, probe, model) {
|
|
|
5259
5259
|
};
|
|
5260
5260
|
}
|
|
5261
5261
|
function guidedFixes$1(finding, model) {
|
|
5262
|
-
const cursorChoice = cursorMcpStateChoice(finding);
|
|
5263
|
-
if (cursorChoice !== void 0) return [cursorChoice];
|
|
5264
5262
|
const server = findingServer(finding, model);
|
|
5265
5263
|
const kind = finding.metadata?.["kind"];
|
|
5266
5264
|
if (server === void 0 || kind !== "command" && kind !== "url") return [];
|
|
@@ -5325,7 +5323,12 @@ const mcp004 = defineCheck({
|
|
|
5325
5323
|
detect: detectInlineSecrets,
|
|
5326
5324
|
explain: `Inline credentials in MCP configuration can leak through source control, logs, diagnostics, and copied configuration. Aura identifies credential-bearing fields without retaining their values, prefixes, or lengths.
|
|
5327
5325
|
|
|
5328
|
-
Re-run with \`--fix
|
|
5326
|
+
Re-run with \`--fix\` to replace every behavior-preserving sighting in the same source file with an environment reference. Copy the current values directly from the named file before applying the rewrite; Aura never displays or stores those values outside the protected undo payload, which stays owner-only under \`~/agents/.backups\` until twenty later fixes have pushed it out of the journal. Then rotate each credential at its issuer: moving a value behind an environment reference stops it leaking again, not from wherever it has already reached.`,
|
|
5327
|
+
findingGroup: {
|
|
5328
|
+
description: "Replace inline credentials with environment-variable references.",
|
|
5329
|
+
id: "checks-core/mcp-credentials",
|
|
5330
|
+
title: "Protect credentials stored in MCP configuration"
|
|
5331
|
+
},
|
|
5329
5332
|
fix: remediation,
|
|
5330
5333
|
fixability: "guided",
|
|
5331
5334
|
guidedFixes,
|
|
@@ -5560,7 +5563,7 @@ const mcp005 = defineCheck({
|
|
|
5560
5563
|
detect: detectScopePlacement,
|
|
5561
5564
|
explain: `The Aura manifest distinguishes personal MCP servers from team servers. Personal servers belong in global configuration; putting one in repository configuration can publish it to teammates through source control. Team servers belong in project configuration; keeping one only in personal configuration means teammates do not receive it and their setup drifts. Placement is judged by the file an entry is written in, not by the scope label alone, because an application can keep both kinds in one document.
|
|
5562
5565
|
|
|
5563
|
-
Re-run with \`--fix
|
|
5566
|
+
Re-run with \`--fix\` to move an Aura-owned entry through the same manifest convergence and undo machinery as other MCP fixes. Aura never removes a name outside its ownership ledger automatically.`,
|
|
5564
5567
|
fix: placementFix,
|
|
5565
5568
|
fixability: "guided",
|
|
5566
5569
|
id: MCP_005_ID,
|