@akanjs/devkit 3.0.0-beta.19 → 3.0.0-beta.20
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/abstractDoc.test.ts +6 -15
- package/abstractDoc.ts +1 -4
- package/agentsIndex.test.ts +4 -7
- package/agentsIndex.ts +6 -22
- package/akanApp/BackendImportGraph.test.ts +8 -22
- package/akanApp/BackendImportGraph.ts +1 -20
- package/akanApp/akanApp.host.test.ts +1 -3
- package/akanApp/akanApp.host.ts +64 -250
- package/akanApp/devHostPolicy.test.ts +10 -34
- package/akanApp/devHostPolicy.ts +12 -98
- package/akanConfig/akanConfig.test.ts +30 -39
- package/akanConfig/akanConfig.ts +40 -136
- package/akanContext.ts +106 -159
- package/akanMcpContract.ts +28 -73
- package/appSelectionMemory.ts +1 -4
- package/applicationBuildReporter.ts +37 -5
- package/applicationBuildRunner.ts +25 -59
- package/applicationReleasePackager.ts +24 -44
- package/applicationTestPreload.ts +3 -12
- package/artifact/implicitRootLayout.test.ts +3 -19
- package/artifact/implicitRootLayout.ts +34 -91
- package/artifact/routeSeedIndex.ts +11 -44
- package/biomeBase.ts +2 -5
- package/capacitorApp.test.ts +4 -14
- package/capacitorApp.ts +86 -235
- package/cloud/cloudApi.test.ts +202 -0
- package/cloud/cloudApi.ts +33 -57
- package/cloud/configLock.test.ts +64 -0
- package/cloud/configLock.ts +96 -0
- package/cloud/constants.ts +3 -2
- package/cloud/globalConfig.ts +64 -31
- package/codeAgent/agent/AkanCodeServices.ts +15 -57
- package/codeAgent/agent/AkanContextFiles.ts +5 -28
- package/codeAgent/agent/CodeAgent.ts +33 -108
- package/codeAgent/agent/CodeAgentAsks.ts +7 -30
- package/codeAgent/agent/CodeAgentEventMapper.ts +9 -52
- package/codeAgent/agent/CodeAgentGate.ts +8 -34
- package/codeAgent/agent/CodeAgentProxy.ts +4 -13
- package/codeAgent/agent/CodeAgentRpcHost.ts +3 -16
- package/codeAgent/agent/CodeAgentRpcListener.ts +2 -10
- package/codeAgent/agent/CodeAgentStreamPrinter.ts +4 -15
- package/codeAgent/agent/CodeAgentSuspended.ts +1 -8
- package/codeAgent/agent/CodeAgentUi.ts +2 -7
- package/codeAgent/agent/CodeMailbox.ts +7 -34
- package/codeAgent/agent/CodeSessionFork.ts +4 -19
- package/codeAgent/agent/CodeSessionIndex.ts +5 -31
- package/codeAgent/agent/SubagentPool.ts +48 -58
- package/codeAgent/agent/akanCodeModel.ts +5 -39
- package/codeAgent/agent/akanCodePaths.ts +4 -24
- package/codeAgent/agent/akanContextFiles.test.ts +0 -2
- package/codeAgent/agent/akanSystemPrompt.ts +1 -9
- package/codeAgent/agent/codeAgent.test.ts +178 -0
- package/codeAgent/agent/codeAgentContract.test.ts +5 -28
- package/codeAgent/agent/codeMailbox.test.ts +0 -4
- package/codeAgent/agent/codeSessionFork.test.ts +0 -2
- package/codeAgent/agent/codeSessionIndex.test.ts +9 -4
- package/codeAgent/agent/consoleToStderr.ts +2 -12
- package/codeAgent/agent/jsonLines.ts +29 -0
- package/codeAgent/agent/stringArg.ts +5 -0
- package/codeAgent/feedback/DevLogFeedback.ts +3 -18
- package/codeAgent/feedback/PreviewChrome.ts +5 -29
- package/codeAgent/feedback/PreviewFeedback.ts +2 -9
- package/codeAgent/feedback/PreviewView.ts +3 -15
- package/codeAgent/feedback/TurnFeedback.ts +2 -17
- package/codeAgent/feedback/VerifyFeedback.ts +1 -7
- package/codeAgent/feedback/previewChrome.test.ts +1 -1
- package/codeAgent/index.ts +2 -10
- package/codeAgent/skills/akan-code/SKILL.md +12 -4
- package/codeAgent/tools/AkanCli.ts +4 -16
- package/codeAgent/tools/AkanCodePlugins.ts +21 -43
- package/codeAgent/tools/AkanEditScope.ts +2 -12
- package/codeAgent/tools/AkanEnvKeys.ts +3 -11
- package/codeAgent/tools/AkanToolPack.ts +6 -28
- package/codeAgent/tools/AkanVerifier.ts +1 -8
- package/codeAgent/tools/AskToolPack.ts +3 -15
- package/codeAgent/tools/MailToolPack.ts +0 -9
- package/codeAgent/tools/McpClient.ts +3 -24
- package/codeAgent/tools/McpOAuth.ts +6 -41
- package/codeAgent/tools/McpOAuthLoopback.ts +2 -15
- package/codeAgent/tools/McpServerConfig.ts +7 -26
- package/codeAgent/tools/McpSignIn.ts +46 -49
- package/codeAgent/tools/McpTokenStore.ts +6 -17
- package/codeAgent/tools/McpToolPack.ts +107 -35
- package/codeAgent/tools/SessionToolPack.ts +1 -11
- package/codeAgent/tools/WebToolPack.ts +1 -7
- package/codeAgent/tools/akanCodePlugins.test.ts +231 -63
- package/codeAgent/tools/askToolPack.test.ts +0 -3
- package/codeAgent/tools/mcpOAuth.test.ts +315 -27
- package/codeAgent/tools/mcpServerConfig.test.ts +21 -14
- package/codegenLock.test.ts +4 -13
- package/codegenLock.ts +3 -17
- package/commandDecorators/argMeta.ts +1 -5
- package/commandDecorators/camelToKebabCase.ts +1 -0
- package/commandDecorators/command.ts +44 -102
- package/commandDecorators/commandBuilder.ts +30 -61
- package/commandDecorators/commandDecorators.test.ts +1 -9
- package/commandDecorators/dependencyBuilder.ts +10 -1
- package/commandDecorators/helpFormatter.ts +66 -144
- package/commandDecorators/index.ts +0 -2
- package/commandDecorators/targetMeta.ts +9 -7
- package/createTunnel.ts +7 -14
- package/dependencyScanner.test.ts +4 -16
- package/dependencyScanner.ts +27 -78
- package/devkitUtils.test.ts +47 -19
- package/executors.test.ts +114 -60
- package/executors.ts +165 -484
- package/fileEditor.ts +9 -37
- package/{getDirname.test.ts → fileSys.test.ts} +1 -1
- package/fileSys.ts +6 -8
- package/formSetterScanner.ts +3 -16
- package/frontendBuild/allRoutesBuilder.ts +7 -21
- package/frontendBuild/autoImportSync.test.ts +14 -38
- package/frontendBuild/autoImportSync.ts +15 -67
- package/frontendBuild/buildRouteClient.test.ts +10 -36
- package/frontendBuild/bundleDefine.ts +12 -0
- package/frontendBuild/clientBuildTypes.ts +5 -36
- package/frontendBuild/clientEntriesBundler.ts +9 -40
- package/frontendBuild/clientEntryDiscovery.ts +6 -41
- package/frontendBuild/csrArtifactBuilder.ts +6 -25
- package/frontendBuild/cssCandidateCache.test.ts +0 -6
- package/frontendBuild/cssCandidateCache.ts +6 -41
- package/frontendBuild/cssCompiler.ts +29 -78
- package/frontendBuild/cssImportResolver.ts +5 -18
- package/frontendBuild/devChangePlanner.ts +7 -10
- package/frontendBuild/devGeneratedIndexSync.test.ts +12 -27
- package/frontendBuild/devGeneratedIndexSync.ts +1 -4
- package/frontendBuild/fontOptimizer.test.ts +5 -13
- package/frontendBuild/fontOptimizer.ts +15 -72
- package/frontendBuild/fontPruner.test.ts +5 -10
- package/frontendBuild/fontPruner.ts +5 -20
- package/frontendBuild/frontendBuild.test.ts +27 -52
- package/frontendBuild/hmrChangeClassifier.ts +2 -2
- package/frontendBuild/hmrWatcher.test.ts +7 -31
- package/frontendBuild/hmrWatcher.ts +14 -71
- package/frontendBuild/pagesBundleBuilder.ts +4 -29
- package/frontendBuild/precompressArtifacts.ts +5 -18
- package/frontendBuild/routeClientBuilder.ts +7 -47
- package/frontendBuild/routesManifestArtifactSerializer.ts +5 -36
- package/frontendBuild/sourceMtimeIndex.test.ts +37 -94
- package/frontendBuild/sourceMtimeIndex.ts +19 -130
- package/frontendBuild/ssrBaseArtifactBuilder.ts +2 -8
- package/frontendBuild/styleContract.ts +1 -8
- package/frontendBuild/themeValidator.ts +4 -26
- package/frontendBuild/watchRootResolver.test.ts +23 -42
- package/frontendBuild/watchRootResolver.ts +5 -27
- package/getRelatedCnsts.ts +12 -92
- package/incrementalBuilder/buildBatch.proc.ts +22 -57
- package/incrementalBuilder/buildBatchProtocol.ts +8 -36
- package/incrementalBuilder/buildBatchRunner.test.ts +34 -0
- package/incrementalBuilder/buildBatchRunner.ts +10 -31
- package/incrementalBuilder/builderChannel.test.ts +24 -49
- package/incrementalBuilder/builderChannel.ts +6 -37
- package/incrementalBuilder/builderRequestRouter.test.ts +0 -8
- package/incrementalBuilder/builderRequestRouter.ts +5 -24
- package/incrementalBuilder/devWatchBatch.test.ts +14 -18
- package/incrementalBuilder/incrementalBuilder.host.test.ts +18 -55
- package/incrementalBuilder/incrementalBuilder.host.ts +18 -76
- package/incrementalBuilder/incrementalBuilder.proc.test.ts +81 -0
- package/incrementalBuilder/incrementalBuilder.proc.ts +48 -161
- package/index.ts +3 -15
- package/integration/devResourceProbe.ts +50 -56
- package/integration/devStability.integration.test.ts +47 -194
- package/integration/devStabilityHarness.test.ts +9 -29
- package/integration/devStabilityHarness.ts +65 -330
- package/integration/ssrMemoryProbe.ts +41 -167
- package/libSource.test.ts +4 -15
- package/libSource.ts +19 -31
- package/lint/gritRules.test.ts +6 -23
- package/linter.test.ts +1 -2
- package/linter.ts +22 -115
- package/mobile/mobileTarget.ts +14 -13
- package/package.json +2 -2
- package/packageExports.test.ts +3 -18
- package/packageExportsMap.ts +3 -19
- package/piDependencyPins.test.ts +3 -14
- package/platformTest/IdleWatchedProcess.test.ts +5 -13
- package/platformTest/IdleWatchedProcess.ts +1 -5
- package/platformTest/LinuxDockerTarget.ts +20 -35
- package/platformTest/PlatformTestRun.test.ts +5 -9
- package/platformTest/PlatformTestTarget.ts +24 -2
- package/platformTest/TestSnapshot.test.ts +6 -14
- package/platformTest/TestSnapshot.ts +1 -5
- package/platformTest/WindowsSshTarget.ts +6 -22
- package/prompter.ts +3 -6
- package/qualityScanner.test.ts +6 -24
- package/qualityScanner.ts +196 -284
- package/recipeScanner.test.ts +7 -12
- package/recipeScanner.ts +9 -38
- package/repoIdentity.ts +2 -9
- package/routeSourceValidator.ts +7 -30
- package/scanInfo.ts +82 -214
- package/selectModel.ts +1 -2
- package/semver.ts +3 -5
- package/slicePlanner.test.ts +6 -24
- package/slicePlanner.ts +11 -32
- package/spinner.test.ts +3 -8
- package/spinner.ts +4 -16
- package/sshTunnel.ts +1 -6
- package/ssrScanner.test.ts +1 -6
- package/ssrScanner.ts +103 -113
- package/subspace.test.ts +6 -25
- package/subspace.ts +31 -109
- package/subspaceConfig.ts +3 -11
- package/testHelpers.ts +49 -34
- package/transforms/asyncDefaultExportDetector.ts +3 -11
- package/transforms/barrelAnalyzer.ts +43 -135
- package/transforms/barrelImportsPlugin.ts +38 -175
- package/transforms/externalizeFrameworkPlugin.test.ts +39 -118
- package/transforms/externalizeFrameworkPlugin.ts +13 -87
- package/transforms/moduleSyntax.ts +32 -0
- package/transforms/rscUseClientTransform.ts +35 -20
- package/transforms/transforms.test.ts +153 -44
- package/transforms/tsconfigPackageResolver.test.ts +6 -24
- package/transforms/useClientBundlePlugin.ts +2 -22
- package/typeChecker.ts +7 -63
- package/uploadRelease.ts +10 -25
- package/workflow/artifacts.ts +18 -0
- package/workflow/executor.test.ts +1 -12
- package/workflow/executor.ts +85 -146
- package/workflow/index.ts +0 -1
- package/workflow/moduleIndex.test.ts +4 -15
- package/workflow/moduleIndex.ts +9 -49
- package/workflow/plan.ts +18 -25
- package/workflow/render.ts +80 -96
- package/workflow/source.ts +33 -56
- package/workflow/sourceAst.ts +50 -0
- package/workspaceLayout.ts +4 -19
- package/commandDecorators/commandMeta.ts +0 -7
- package/commandDecorators/types.ts +0 -10
- package/getDirname.ts +0 -4
- package/local/optimize-resource/ipcprobe/child.ts +0 -1
- package/local/optimize-resource/ipcprobe/parent.ts +0 -11
- package/workflow/primitive.ts +0 -59
|
@@ -36,6 +36,15 @@ export interface PlatformRunContext {
|
|
|
36
36
|
export abstract class PlatformTestTarget {
|
|
37
37
|
static readonly installIdleMs = 5 * 60_000;
|
|
38
38
|
static readonly testIdleMs = 2 * 60_000;
|
|
39
|
+
protected static readonly gitIdentityEnv = {
|
|
40
|
+
GIT_AUTHOR_NAME: "akan-test",
|
|
41
|
+
GIT_AUTHOR_EMAIL: "akan-test@localhost",
|
|
42
|
+
GIT_COMMITTER_NAME: "akan-test",
|
|
43
|
+
GIT_COMMITTER_EMAIL: "akan-test@localhost",
|
|
44
|
+
GIT_CONFIG_COUNT: "1",
|
|
45
|
+
GIT_CONFIG_KEY_0: "init.defaultBranch",
|
|
46
|
+
GIT_CONFIG_VALUE_0: "main",
|
|
47
|
+
};
|
|
39
48
|
|
|
40
49
|
abstract readonly platform: RemoteTestPlatform;
|
|
41
50
|
abstract readonly policy: PlatformGatePolicy;
|
|
@@ -103,8 +112,7 @@ export abstract class PlatformTestTarget {
|
|
|
103
112
|
const tolerable =
|
|
104
113
|
failedScripts.length > 0 && failedScripts.every((pkg) => this.tolerateScriptFailures.includes(pkg));
|
|
105
114
|
if (!tolerable) throw new Error(`bun install failed — see ${logPath}`);
|
|
106
|
-
//* A failed lifecycle script makes bun skip linking the
|
|
107
|
-
//* spawn from there disappears; a second pass without scripts links them.
|
|
115
|
+
//* A failed lifecycle script makes bun skip linking the root `.bin`; a second pass without scripts links it.
|
|
108
116
|
envWarnings.push(`install script failed for ${failedScripts.join(", ")} — tolerated on ${this.platform}`);
|
|
109
117
|
const relink = await this.exec(
|
|
110
118
|
"bun install --frozen-lockfile --ignore-scripts",
|
|
@@ -117,4 +125,18 @@ export abstract class PlatformTestTarget {
|
|
|
117
125
|
#logPath(context: PlatformRunContext, name: string) {
|
|
118
126
|
return path.join(context.logDir, this.platform, `${name}.log`);
|
|
119
127
|
}
|
|
128
|
+
|
|
129
|
+
protected static async spawnText(command: string[], stdin?: string) {
|
|
130
|
+
const proc = Bun.spawn(command, {
|
|
131
|
+
stdin: stdin === undefined ? "ignore" : new Response(stdin),
|
|
132
|
+
stdout: "pipe",
|
|
133
|
+
stderr: "pipe",
|
|
134
|
+
});
|
|
135
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
136
|
+
new Response(proc.stdout).text(),
|
|
137
|
+
new Response(proc.stderr).text(),
|
|
138
|
+
proc.exited,
|
|
139
|
+
]);
|
|
140
|
+
return { stdout, stderr, exitCode };
|
|
141
|
+
}
|
|
120
142
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import os from "node:os";
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { unlink } from "node:fs/promises";
|
|
4
3
|
import path from "node:path";
|
|
4
|
+
import { tempDirs, writeText } from "../testHelpers";
|
|
5
5
|
import { TestSnapshot } from "./TestSnapshot";
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const makeRoot = tempDirs("akan-snapshot-");
|
|
8
8
|
const git = async (cwd: string, ...args: string[]) => {
|
|
9
9
|
const proc = Bun.spawn(["git", ...args], {
|
|
10
10
|
cwd,
|
|
@@ -20,13 +20,9 @@ const git = async (cwd: string, ...args: string[]) => {
|
|
|
20
20
|
});
|
|
21
21
|
expect(await proc.exited).toBe(0);
|
|
22
22
|
};
|
|
23
|
-
const write = async (root: string, file: string, content: string) =>
|
|
24
|
-
await mkdir(path.dirname(path.join(root, file)), { recursive: true });
|
|
25
|
-
await writeFile(path.join(root, file), content);
|
|
26
|
-
};
|
|
23
|
+
const write = async (root: string, file: string, content: string) => await writeText(path.join(root, file), content);
|
|
27
24
|
const makeRepo = async () => {
|
|
28
|
-
const root = await
|
|
29
|
-
roots.push(root);
|
|
25
|
+
const root = await makeRoot();
|
|
30
26
|
await git(root, "init", "-q");
|
|
31
27
|
await write(root, ".gitignore", "ignored/\nlocal/\n.env\n");
|
|
32
28
|
await write(root, "tracked.ts", "export {};\n");
|
|
@@ -44,10 +40,6 @@ const tarEntries = async (tarPath: string) => {
|
|
|
44
40
|
return (await new Response(proc.stdout).text()).split(/\r?\n/).filter(Boolean).sort();
|
|
45
41
|
};
|
|
46
42
|
|
|
47
|
-
afterAll(async () => {
|
|
48
|
-
await Promise.all(roots.map((root) => rm(root, { recursive: true, force: true })));
|
|
49
|
-
});
|
|
50
|
-
|
|
51
43
|
describe("TestSnapshot", () => {
|
|
52
44
|
test("packs what git would show — tracked and untracked, never ignored or deleted", async () => {
|
|
53
45
|
const root = await makeRepo();
|
|
@@ -7,11 +7,7 @@ export interface SnapshotDrift {
|
|
|
7
7
|
removed: string[];
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
* The exact bytes a platform run tests: every tracked file plus every untracked one git would show, which is
|
|
12
|
-
* what `akan deploy-akan` goes on to build and publish. The per-file hashes are kept so the tree can be
|
|
13
|
-
* compared again before publishing — a test run is only a gate if nothing changed underneath it.
|
|
14
|
-
*/
|
|
10
|
+
//? Per-file hashes are kept so the tree is re-checked before publishing: a run gates only if nothing changed under it.
|
|
15
11
|
export class TestSnapshot {
|
|
16
12
|
static readonly #secretPatterns = [
|
|
17
13
|
/(^|\/)\.env(\.(?!(template|example|sample)$)[^/]+)?$/,
|
|
@@ -48,7 +48,7 @@ export class WindowsSshTarget extends PlatformTestTarget {
|
|
|
48
48
|
[context.snapshot.tarPath, "src.tar"],
|
|
49
49
|
[context.envPath, "env"],
|
|
50
50
|
] as const) {
|
|
51
|
-
const copied = await WindowsSshTarget
|
|
51
|
+
const copied = await WindowsSshTarget.spawnText([
|
|
52
52
|
...this.#scpBase(),
|
|
53
53
|
local,
|
|
54
54
|
this.#remoteScpPath(`${runDir}\\${remoteName}`),
|
|
@@ -71,13 +71,7 @@ export class WindowsSshTarget extends PlatformTestTarget {
|
|
|
71
71
|
"$ProgressPreference = 'SilentlyContinue'",
|
|
72
72
|
"[Console]::OutputEncoding = [Text.Encoding]::UTF8",
|
|
73
73
|
"'PID=' + $PID",
|
|
74
|
-
|
|
75
|
-
"$env:GIT_AUTHOR_EMAIL = 'akan-test@localhost'",
|
|
76
|
-
"$env:GIT_COMMITTER_NAME = 'akan-test'",
|
|
77
|
-
"$env:GIT_COMMITTER_EMAIL = 'akan-test@localhost'",
|
|
78
|
-
"$env:GIT_CONFIG_COUNT = '1'",
|
|
79
|
-
"$env:GIT_CONFIG_KEY_0 = 'init.defaultBranch'",
|
|
80
|
-
"$env:GIT_CONFIG_VALUE_0 = 'main'",
|
|
74
|
+
...Object.entries(PlatformTestTarget.gitIdentityEnv).map(([key, value]) => `$env:${key} = '${value}'`),
|
|
81
75
|
`Set-Location -LiteralPath '${runDir}\\w'`,
|
|
82
76
|
`cmd /c "${command} 2>&1"`,
|
|
83
77
|
"exit $LASTEXITCODE",
|
|
@@ -112,10 +106,10 @@ export class WindowsSshTarget extends PlatformTestTarget {
|
|
|
112
106
|
const vm = this.#config.utmVm;
|
|
113
107
|
if (!vm || !existsSync(WindowsSshTarget.utmctlPath))
|
|
114
108
|
throw new Error(`cannot reach ${this.#config.user}@${this.#host} over ssh`);
|
|
115
|
-
const status = (await WindowsSshTarget
|
|
116
|
-
if (status !== "started") await WindowsSshTarget
|
|
109
|
+
const status = (await WindowsSshTarget.spawnText([WindowsSshTarget.utmctlPath, "status", vm])).stdout.trim();
|
|
110
|
+
if (status !== "started") await WindowsSshTarget.spawnText([WindowsSshTarget.utmctlPath, "start", vm]);
|
|
117
111
|
for (let attempt = 0; attempt < 24; attempt++) {
|
|
118
|
-
const addresses = (await WindowsSshTarget
|
|
112
|
+
const addresses = (await WindowsSshTarget.spawnText([WindowsSshTarget.utmctlPath, "ip-address", vm])).stdout;
|
|
119
113
|
const ipv4 = addresses.split(/\s+/).find((address) => /^\d+\.\d+\.\d+\.\d+$/.test(address));
|
|
120
114
|
if (ipv4) this.#host = ipv4;
|
|
121
115
|
if ((await this.#ssh("exit 0")).exitCode === 0) return;
|
|
@@ -152,16 +146,6 @@ export class WindowsSshTarget extends PlatformTestTarget {
|
|
|
152
146
|
}
|
|
153
147
|
|
|
154
148
|
async #ssh(script: string) {
|
|
155
|
-
return await WindowsSshTarget
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
static async #run(command: string[]) {
|
|
159
|
-
const proc = Bun.spawn(command, { stdin: "ignore", stdout: "pipe", stderr: "pipe" });
|
|
160
|
-
const [stdout, stderr, exitCode] = await Promise.all([
|
|
161
|
-
new Response(proc.stdout).text(),
|
|
162
|
-
new Response(proc.stderr).text(),
|
|
163
|
-
proc.exited,
|
|
164
|
-
]);
|
|
165
|
-
return { stdout, stderr, exitCode };
|
|
149
|
+
return await WindowsSshTarget.spawnText([...this.#sshBase(), script]);
|
|
166
150
|
}
|
|
167
151
|
}
|
package/prompter.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fsPromise from "node:fs/promises";
|
|
2
2
|
import { input, select } from "@inquirer/prompts";
|
|
3
3
|
|
|
4
|
-
import { getDirname } from "./
|
|
4
|
+
import { getDirname } from "./fileSys";
|
|
5
5
|
|
|
6
6
|
interface FileUpdateRequestProps {
|
|
7
7
|
context: string;
|
|
@@ -33,11 +33,8 @@ export class Prompter {
|
|
|
33
33
|
const guidelineRoot = await Prompter.#getGuidelineRoot();
|
|
34
34
|
return (await fsPromise.readdir(guidelineRoot)).filter((name) => !name.startsWith("_")).sort();
|
|
35
35
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
* it arrives from an MCP tool argument, and an unknown one has to name the valid set instead of
|
|
39
|
-
* surfacing an ENOENT that carries the host's own paths.
|
|
40
|
-
*/
|
|
36
|
+
// Checked against the listing, not interpolated into a path: the name is an MCP tool argument, and an unknown one
|
|
37
|
+
// must not surface an ENOENT carrying the host's paths.
|
|
41
38
|
static async getInstruction(guideName: string): Promise<string> {
|
|
42
39
|
const guideNames = await Prompter.listGuidelines();
|
|
43
40
|
if (!guideNames.includes(guideName))
|
package/qualityScanner.test.ts
CHANGED
|
@@ -1,30 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
3
|
-
import os from "node:os";
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
4
2
|
import path from "node:path";
|
|
5
3
|
import { AbstractDoc } from "./abstractDoc";
|
|
6
4
|
import { AkanQualityScanner, type QualityScanResult } from "./qualityScanner";
|
|
5
|
+
import { tempDirs, writeText } from "./testHelpers";
|
|
7
6
|
|
|
8
|
-
const
|
|
7
|
+
const makeTempRoot = tempDirs("akan-quality-scanner-");
|
|
9
8
|
|
|
10
9
|
const makeWorkspace = async (files: Record<string, string>) => {
|
|
11
|
-
const root = await
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const absolutePath = path.join(root, filePath);
|
|
15
|
-
await mkdir(path.dirname(absolutePath), { recursive: true });
|
|
16
|
-
await writeFile(absolutePath, content);
|
|
17
|
-
}
|
|
10
|
+
const root = await makeTempRoot();
|
|
11
|
+
for (const [filePath, content] of Object.entries({ ".gitignore": "node_modules\n", ...files }))
|
|
12
|
+
await writeText(path.join(root, filePath), content);
|
|
18
13
|
return root;
|
|
19
14
|
};
|
|
20
15
|
|
|
21
16
|
const abstractOf = (lineNum: number) =>
|
|
22
17
|
["# post Abstract", ...Array.from({ length: lineNum - 1 }, (_, idx) => `- rule ${idx}`)].join("\n");
|
|
23
18
|
|
|
24
|
-
afterEach(async () => {
|
|
25
|
-
await Promise.all(tempRoots.splice(0).map((root) => rm(root, { recursive: true, force: true })));
|
|
26
|
-
});
|
|
27
|
-
|
|
28
19
|
describe("AkanQualityScanner abstract rule", () => {
|
|
29
20
|
test("warns on an abstract over the line limit and says how to trim it", async () => {
|
|
30
21
|
const root = await makeWorkspace({
|
|
@@ -185,15 +176,6 @@ describe("AkanQualityScanner ssr rules", () => {
|
|
|
185
176
|
});
|
|
186
177
|
});
|
|
187
178
|
|
|
188
|
-
const signalOf = (entries: string) =>
|
|
189
|
-
[
|
|
190
|
-
`import { endpoint, slice } from "akanjs/signal";`,
|
|
191
|
-
`export class PostSlice extends slice(srv.post, { guards: {}, mcp: { get: true } }, (init) => ({`,
|
|
192
|
-
entries,
|
|
193
|
-
`})) {}`,
|
|
194
|
-
"",
|
|
195
|
-
].join("\n");
|
|
196
|
-
|
|
197
179
|
describe("AkanQualityScanner layout rules", () => {
|
|
198
180
|
test("flags an unknown app root file but not a facet entrypoint", async () => {
|
|
199
181
|
const root = await makeWorkspace({
|