skyl.dev 0.1.1 → 0.1.2
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.js +2265 -2
- package/package.json +7 -10
- package/dist/bin.d.ts +0 -3
- package/dist/bin.d.ts.map +0 -1
- package/dist/bin.js.map +0 -1
- package/dist/cli.d.ts +0 -2
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -158
- package/dist/cli.js.map +0 -1
- package/dist/commands/add.d.ts +0 -10
- package/dist/commands/add.d.ts.map +0 -1
- package/dist/commands/add.js +0 -38
- package/dist/commands/add.js.map +0 -1
- package/dist/commands/audit.d.ts +0 -16
- package/dist/commands/audit.d.ts.map +0 -1
- package/dist/commands/audit.js +0 -91
- package/dist/commands/audit.js.map +0 -1
- package/dist/commands/context.d.ts +0 -17
- package/dist/commands/context.d.ts.map +0 -1
- package/dist/commands/context.js +0 -47
- package/dist/commands/context.js.map +0 -1
- package/dist/commands/diff.d.ts +0 -12
- package/dist/commands/diff.d.ts.map +0 -1
- package/dist/commands/diff.js +0 -79
- package/dist/commands/diff.js.map +0 -1
- package/dist/commands/learn.d.ts +0 -18
- package/dist/commands/learn.d.ts.map +0 -1
- package/dist/commands/learn.js +0 -115
- package/dist/commands/learn.js.map +0 -1
- package/dist/commands/lint.d.ts +0 -14
- package/dist/commands/lint.d.ts.map +0 -1
- package/dist/commands/lint.js +0 -109
- package/dist/commands/lint.js.map +0 -1
- package/dist/commands/list.d.ts +0 -6
- package/dist/commands/list.d.ts.map +0 -1
- package/dist/commands/list.js +0 -60
- package/dist/commands/list.js.map +0 -1
- package/dist/commands/remove.d.ts +0 -16
- package/dist/commands/remove.d.ts.map +0 -1
- package/dist/commands/remove.js +0 -73
- package/dist/commands/remove.js.map +0 -1
- package/dist/commands/scan.d.ts +0 -10
- package/dist/commands/scan.d.ts.map +0 -1
- package/dist/commands/scan.js +0 -60
- package/dist/commands/scan.js.map +0 -1
- package/dist/commands/update.d.ts +0 -11
- package/dist/commands/update.d.ts.map +0 -1
- package/dist/commands/update.js +0 -135
- package/dist/commands/update.js.map +0 -1
- package/dist/context.d.ts +0 -44
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js +0 -179
- package/dist/context.js.map +0 -1
- package/dist/ignore.d.ts +0 -21
- package/dist/ignore.d.ts.map +0 -1
- package/dist/ignore.js +0 -79
- package/dist/ignore.js.map +0 -1
- package/dist/install.d.ts +0 -10
- package/dist/install.d.ts.map +0 -1
- package/dist/install.js +0 -54
- package/dist/install.js.map +0 -1
- package/dist/learn.d.ts +0 -45
- package/dist/learn.d.ts.map +0 -1
- package/dist/learn.js +0 -146
- package/dist/learn.js.map +0 -1
- package/dist/registry.d.ts +0 -23
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js +0 -38
- package/dist/registry.js.map +0 -1
- package/dist/scan.d.ts +0 -3
- package/dist/scan.d.ts.map +0 -1
- package/dist/scan.js +0 -104
- package/dist/scan.js.map +0 -1
- package/dist/state.d.ts +0 -31
- package/dist/state.d.ts.map +0 -1
- package/dist/state.js +0 -39
- package/dist/state.js.map +0 -1
- package/dist/ui.d.ts +0 -17
- package/dist/ui.d.ts.map +0 -1
- package/dist/ui.js +0 -35
- package/dist/ui.js.map +0 -1
- package/node_modules/@skyl/core/dist/audit.d.ts +0 -48
- package/node_modules/@skyl/core/dist/audit.d.ts.map +0 -1
- package/node_modules/@skyl/core/dist/audit.js +0 -99
- package/node_modules/@skyl/core/dist/audit.js.map +0 -1
- package/node_modules/@skyl/core/dist/detect.d.ts +0 -15
- package/node_modules/@skyl/core/dist/detect.d.ts.map +0 -1
- package/node_modules/@skyl/core/dist/detect.js +0 -62
- package/node_modules/@skyl/core/dist/detect.js.map +0 -1
- package/node_modules/@skyl/core/dist/diff.d.ts +0 -32
- package/node_modules/@skyl/core/dist/diff.d.ts.map +0 -1
- package/node_modules/@skyl/core/dist/diff.js +0 -119
- package/node_modules/@skyl/core/dist/diff.js.map +0 -1
- package/node_modules/@skyl/core/dist/errors.d.ts +0 -21
- package/node_modules/@skyl/core/dist/errors.d.ts.map +0 -1
- package/node_modules/@skyl/core/dist/errors.js +0 -25
- package/node_modules/@skyl/core/dist/errors.js.map +0 -1
- package/node_modules/@skyl/core/dist/index.d.ts +0 -14
- package/node_modules/@skyl/core/dist/index.d.ts.map +0 -1
- package/node_modules/@skyl/core/dist/index.js +0 -14
- package/node_modules/@skyl/core/dist/index.js.map +0 -1
- package/node_modules/@skyl/core/dist/lint.d.ts +0 -28
- package/node_modules/@skyl/core/dist/lint.d.ts.map +0 -1
- package/node_modules/@skyl/core/dist/lint.js +0 -169
- package/node_modules/@skyl/core/dist/lint.js.map +0 -1
- package/node_modules/@skyl/core/dist/lockfile.d.ts +0 -37
- package/node_modules/@skyl/core/dist/lockfile.d.ts.map +0 -1
- package/node_modules/@skyl/core/dist/lockfile.js +0 -47
- package/node_modules/@skyl/core/dist/lockfile.js.map +0 -1
- package/node_modules/@skyl/core/dist/match.d.ts +0 -19
- package/node_modules/@skyl/core/dist/match.d.ts.map +0 -1
- package/node_modules/@skyl/core/dist/match.js +0 -72
- package/node_modules/@skyl/core/dist/match.js.map +0 -1
- package/node_modules/@skyl/core/dist/names.d.ts +0 -11
- package/node_modules/@skyl/core/dist/names.d.ts.map +0 -1
- package/node_modules/@skyl/core/dist/names.js +0 -31
- package/node_modules/@skyl/core/dist/names.js.map +0 -1
- package/node_modules/@skyl/core/dist/parse.d.ts +0 -22
- package/node_modules/@skyl/core/dist/parse.d.ts.map +0 -1
- package/node_modules/@skyl/core/dist/parse.js +0 -163
- package/node_modules/@skyl/core/dist/parse.js.map +0 -1
- package/node_modules/@skyl/core/dist/resolve.d.ts +0 -12
- package/node_modules/@skyl/core/dist/resolve.d.ts.map +0 -1
- package/node_modules/@skyl/core/dist/resolve.js +0 -40
- package/node_modules/@skyl/core/dist/resolve.js.map +0 -1
- package/node_modules/@skyl/core/dist/source.d.ts +0 -35
- package/node_modules/@skyl/core/dist/source.d.ts.map +0 -1
- package/node_modules/@skyl/core/dist/source.js +0 -85
- package/node_modules/@skyl/core/dist/source.js.map +0 -1
- package/node_modules/@skyl/core/dist/targets.d.ts +0 -20
- package/node_modules/@skyl/core/dist/targets.d.ts.map +0 -1
- package/node_modules/@skyl/core/dist/targets.js +0 -24
- package/node_modules/@skyl/core/dist/targets.js.map +0 -1
- package/node_modules/@skyl/core/dist/types.d.ts +0 -51
- package/node_modules/@skyl/core/dist/types.d.ts.map +0 -1
- package/node_modules/@skyl/core/dist/types.js +0 -2
- package/node_modules/@skyl/core/dist/types.js.map +0 -1
- package/node_modules/@skyl/core/package.json +0 -20
package/dist/learn.js
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { sections } from '@skyl/core';
|
|
2
|
-
import { renderContext } from "./context.js";
|
|
3
|
-
/**
|
|
4
|
-
* The generated file is a skill like any other, so an installed agent reads it the same
|
|
5
|
-
* way. What makes it different is that nobody can review it against a corpus: it is true
|
|
6
|
-
* of one repository and only the people working there can say whether it is right.
|
|
7
|
-
*/
|
|
8
|
-
export const LEARNED_NAME = 'project/core';
|
|
9
|
-
/** Never overwritten by a refresh. If a refresh can eat hand-written text even once, nobody runs it again. */
|
|
10
|
-
export const MANUAL_SECTION = 'Manual';
|
|
11
|
-
const INSTRUCTIONS = `You are writing a project knowledge skill for an AI coding agent that will work in this
|
|
12
|
-
repository. The context bundle below was selected mechanically, not by a model.
|
|
13
|
-
|
|
14
|
-
Write **product knowledge**, not code quality advice. What the product is, what its terms mean, what
|
|
15
|
-
its parts are called, where things live. A rule about Compose or coroutines belongs in a community
|
|
16
|
-
skill and must not appear here.
|
|
17
|
-
|
|
18
|
-
Include only what you can point at in the bundle:
|
|
19
|
-
|
|
20
|
-
- **Glossary.** Domain terms and what they mean, with where each is defined. Usually the most
|
|
21
|
-
valuable section, and the one nothing else can supply.
|
|
22
|
-
- **Features.** Modules and screens, and what each is called.
|
|
23
|
-
- **Entities.** The data model and how the pieces relate.
|
|
24
|
-
- **Integrations.** Third party services, and what each is used for.
|
|
25
|
-
- **Flows.** Named flows and their entry points, such as "withdrawal starts at WithdrawFragment and
|
|
26
|
-
hits /api/withdraw".
|
|
27
|
-
- **Placement.** Where a new screen, a new model, a new test goes.
|
|
28
|
-
- **Commands.** Build, test, lint.
|
|
29
|
-
|
|
30
|
-
Leave out:
|
|
31
|
-
|
|
32
|
-
- Explanations of how code works. The agent reads the code faster than it reads a summary.
|
|
33
|
-
- Architecture justification. One sentence for the choice, none for the argument.
|
|
34
|
-
- Anything the installed skills already cover.
|
|
35
|
-
- Secrets, credentials, environment structure. If you see one, say so and do not copy it.
|
|
36
|
-
|
|
37
|
-
**Ask rather than assert.** Anything you cannot observe in the bundle is a question, never a claim.
|
|
38
|
-
Collect the questions at the end of the file under \`## Questions\`, each as a line ending in
|
|
39
|
-
\`<!-- unanswered -->\`. A business rule you inferred from a status enum is a question. This is the
|
|
40
|
-
part that keeps the file from decaying: it improves each run instead of drifting.
|
|
41
|
-
|
|
42
|
-
Output one markdown file and nothing else. No preamble, no explanation of what you did. Start at the
|
|
43
|
-
frontmatter and use this shape:
|
|
44
|
-
|
|
45
|
-
\`\`\`
|
|
46
|
-
---
|
|
47
|
-
name: project/core
|
|
48
|
-
axis: topic
|
|
49
|
-
family: project
|
|
50
|
-
version: 1.0.0
|
|
51
|
-
agent_sections: [rules]
|
|
52
|
-
generated: <date>
|
|
53
|
-
---
|
|
54
|
-
|
|
55
|
-
## Rules
|
|
56
|
-
|
|
57
|
-
- **PROJ-1** \`must\`: <instruction>
|
|
58
|
-
*Why:* <the failure it prevents>
|
|
59
|
-
*Not when:* <the boundary>
|
|
60
|
-
|
|
61
|
-
## Glossary
|
|
62
|
-
...
|
|
63
|
-
## Questions
|
|
64
|
-
- Can a withdrawal be cancelled after PROCESSING? <!-- unanswered -->
|
|
65
|
-
\`\`\`
|
|
66
|
-
`;
|
|
67
|
-
export function learnPrompt(bundle, keep) {
|
|
68
|
-
const parts = [INSTRUCTIONS];
|
|
69
|
-
if (keep.manual) {
|
|
70
|
-
parts.push(`\n## Text to carry over unchanged\n\nThis was written by hand. Reproduce it verbatim as a \`## ${MANUAL_SECTION}\` section, and do not
|
|
71
|
-
edit, summarise, or reorder it.\n\n\`\`\`\n${keep.manual}\n\`\`\`\n`);
|
|
72
|
-
}
|
|
73
|
-
if (keep.questions) {
|
|
74
|
-
parts.push(`\n## Questions still open from the last run\n\nCarry any that are still unanswered. Drop one only if the bundle now answers it.\n\n\`\`\`\n${keep.questions}\n\`\`\`\n`);
|
|
75
|
-
}
|
|
76
|
-
parts.push('\n---\n');
|
|
77
|
-
parts.push(renderContext(bundle));
|
|
78
|
-
return parts.join('\n');
|
|
79
|
-
}
|
|
80
|
-
/** What a refresh has to preserve out of the file that is already there. */
|
|
81
|
-
export function preserved(existing) {
|
|
82
|
-
if (!existing)
|
|
83
|
-
return {};
|
|
84
|
-
const found = sections(existing);
|
|
85
|
-
const manual = found.get(MANUAL_SECTION);
|
|
86
|
-
const questions = found.get('Questions');
|
|
87
|
-
return {
|
|
88
|
-
...(manual ? { manual } : {}),
|
|
89
|
-
...(questions ? { questions: questions.split('\n').filter((l) => l.includes('<!-- unanswered -->')).join('\n') } : {}),
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Take the markdown back out of whatever the agent printed.
|
|
94
|
-
*
|
|
95
|
-
* Headless CLIs vary in how much they wrap the answer, and a fenced block around the
|
|
96
|
-
* whole file is the common case. Anything before the frontmatter is dropped.
|
|
97
|
-
*/
|
|
98
|
-
export function extractMarkdown(output) {
|
|
99
|
-
const fenced = /```(?:markdown|md)?\n([\s\S]*?)```/.exec(output);
|
|
100
|
-
const text = (fenced?.[1] ?? output).trim();
|
|
101
|
-
const start = text.indexOf('---');
|
|
102
|
-
if (start < 0)
|
|
103
|
-
return undefined;
|
|
104
|
-
return `${text.slice(start).trim()}\n`;
|
|
105
|
-
}
|
|
106
|
-
/** Put back what the model was told to carry, in case it did not. */
|
|
107
|
-
export function reattach(generated, keep) {
|
|
108
|
-
let out = generated;
|
|
109
|
-
const found = sections(out);
|
|
110
|
-
if (keep.manual && !found.has(MANUAL_SECTION)) {
|
|
111
|
-
out = `${out.trimEnd()}\n\n## ${MANUAL_SECTION}\n\n${keep.manual}\n`;
|
|
112
|
-
}
|
|
113
|
-
if (keep.questions) {
|
|
114
|
-
const already = found.get('Questions') ?? '';
|
|
115
|
-
const missing = keep.questions.split('\n').filter((q) => q.trim() !== '' && !already.includes(q.trim()));
|
|
116
|
-
if (missing.length > 0) {
|
|
117
|
-
out = found.has('Questions')
|
|
118
|
-
? out.replace(/^## Questions$/m, `## Questions\n\n${missing.join('\n')}`)
|
|
119
|
-
: `${out.trimEnd()}\n\n## Questions\n\n${missing.join('\n')}\n`;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return out;
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* A header that travels with the file into the repository.
|
|
126
|
-
*
|
|
127
|
-
* Docs nobody opens cannot carry this warning. The file itself can, and the agent reading
|
|
128
|
-
* it sees the date and can treat old content with the suspicion it deserves.
|
|
129
|
-
*/
|
|
130
|
-
export function caution(date, sha) {
|
|
131
|
-
return `<!--\nGenerated by \`skyl learn\` on ${date}${sha ? ` from commit ${sha}` : ''}.\nPartly inferred from the repository. Correct anything wrong.\nText under \`## ${MANUAL_SECTION}\` is written by hand and is preserved across refreshes.\n-->`;
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* The caution goes after the frontmatter, not before it.
|
|
135
|
-
*
|
|
136
|
-
* A skill file starts at `---` and a parser that finds anything else gives up, so putting
|
|
137
|
-
* the comment first would make the generated file the one skill nothing can read.
|
|
138
|
-
*/
|
|
139
|
-
export function withCaution(markdown, date, sha) {
|
|
140
|
-
const note = caution(date, sha);
|
|
141
|
-
const end = /^---\r?\n[\s\S]*?\r?\n---\r?\n/.exec(markdown);
|
|
142
|
-
if (!end)
|
|
143
|
-
return `${note}\n\n${markdown}`;
|
|
144
|
-
return `${markdown.slice(0, end[0].length)}\n${note}\n${markdown.slice(end[0].length)}`;
|
|
145
|
-
}
|
|
146
|
-
//# sourceMappingURL=learn.js.map
|
package/dist/learn.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"learn.js","sourceRoot":"","sources":["../src/learn.ts"],"names":[],"mappings":"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"}
|
package/dist/registry.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { type Skill, type Source } from '@skyl/core';
|
|
2
|
-
/**
|
|
3
|
-
* Sources in the order they are tried.
|
|
4
|
-
*
|
|
5
|
-
* A local directory first, so someone editing skills sees their edit immediately. Then
|
|
6
|
-
* the bundle shipped inside this package, which always works and is as old as the
|
|
7
|
-
* release. Then the network, which is current and may not be reachable.
|
|
8
|
-
*
|
|
9
|
-
* The bundle before the network means the common path never blocks on a request, and
|
|
10
|
-
* `--refresh` reverses the last two when currency matters more than speed.
|
|
11
|
-
*/
|
|
12
|
-
export declare function sources(opts: {
|
|
13
|
-
dir?: string | undefined;
|
|
14
|
-
refresh?: boolean | undefined;
|
|
15
|
-
}): Source[];
|
|
16
|
-
export declare function loadRegistry(opts: {
|
|
17
|
-
dir?: string | undefined;
|
|
18
|
-
refresh?: boolean | undefined;
|
|
19
|
-
}): Promise<{
|
|
20
|
-
skills: Skill[];
|
|
21
|
-
from: string;
|
|
22
|
-
}>;
|
|
23
|
-
//# sourceMappingURL=registry.d.ts.map
|
package/dist/registry.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAIA,OAAO,EAEQ,KAAK,KAAK,EAAE,KAAK,MAAM,EACrC,MAAM,YAAY,CAAC;AAOpB;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAAE,GAAG,MAAM,EAAE,CAgBnG;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAAE,GAChE,OAAO,CAAC;IAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAG5C"}
|
package/dist/registry.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
2
|
-
import { readFile } from 'node:fs/promises';
|
|
3
|
-
import { dirname, join, resolve as resolvePath } from 'node:path';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { bundleSource, directorySource, firstAvailable, httpBundleSource, } from '@skyl/core';
|
|
6
|
-
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
/** Where the registry is fetched from when nothing local is available. */
|
|
8
|
-
const REMOTE = 'https://skyl.dev/registry.json';
|
|
9
|
-
/**
|
|
10
|
-
* Sources in the order they are tried.
|
|
11
|
-
*
|
|
12
|
-
* A local directory first, so someone editing skills sees their edit immediately. Then
|
|
13
|
-
* the bundle shipped inside this package, which always works and is as old as the
|
|
14
|
-
* release. Then the network, which is current and may not be reachable.
|
|
15
|
-
*
|
|
16
|
-
* The bundle before the network means the common path never blocks on a request, and
|
|
17
|
-
* `--refresh` reverses the last two when currency matters more than speed.
|
|
18
|
-
*/
|
|
19
|
-
export function sources(opts) {
|
|
20
|
-
const list = [];
|
|
21
|
-
if (opts.dir)
|
|
22
|
-
list.push(directorySource(resolvePath(opts.dir), 'local'));
|
|
23
|
-
const bundlePath = join(HERE, '..', 'bundle.json');
|
|
24
|
-
const bundled = bundleSource(async () => JSON.parse(await readFile(bundlePath, 'utf8')), 'bundled');
|
|
25
|
-
const remote = httpBundleSource(REMOTE, 'skyl.dev');
|
|
26
|
-
if (opts.refresh)
|
|
27
|
-
list.push(remote, bundled);
|
|
28
|
-
else if (existsSync(bundlePath))
|
|
29
|
-
list.push(bundled, remote);
|
|
30
|
-
else
|
|
31
|
-
list.push(remote);
|
|
32
|
-
return list;
|
|
33
|
-
}
|
|
34
|
-
export async function loadRegistry(opts) {
|
|
35
|
-
const { skills, from } = await firstAvailable(sources(opts));
|
|
36
|
-
return { skills, from: from.name };
|
|
37
|
-
}
|
|
38
|
-
//# sourceMappingURL=registry.js.map
|
package/dist/registry.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,WAAW,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,GAEhE,MAAM,YAAY,CAAC;AAEpB,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAErD,0EAA0E;AAC1E,MAAM,MAAM,GAAG,gCAAgC,CAAC;AAEhD;;;;;;;;;GASG;AACH,MAAM,UAAU,OAAO,CAAC,IAAiE;IACvF,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,IAAI,CAAC,GAAG;QAAE,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IAEzE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,YAAY,CAC1B,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAW,EACpE,SAAS,CACV,CAAC;IACF,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAEpD,IAAI,IAAI,CAAC,OAAO;QAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;SACxC,IAAI,UAAU,CAAC,UAAU,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;;QACvD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEvB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAiE;IAEjE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7D,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;AACrC,CAAC"}
|
package/dist/scan.d.ts
DELETED
package/dist/scan.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AA2CjD,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAgDvE"}
|
package/dist/scan.js
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { readdir, readFile } from 'node:fs/promises';
|
|
2
|
-
import { join, relative, sep } from 'node:path';
|
|
3
|
-
/**
|
|
4
|
-
* Collect what a project declares, without building it.
|
|
5
|
-
*
|
|
6
|
-
* Reading build files as text rather than invoking Gradle is the whole point: it is
|
|
7
|
-
* instant, works on a project that does not currently compile, and needs no toolchain.
|
|
8
|
-
* The cost is that a dependency assembled at runtime from variables is missed, which is
|
|
9
|
-
* why `scan` proposes and never installs on its own.
|
|
10
|
-
*/
|
|
11
|
-
const SKIP = new Set(['node_modules', 'build', '.git', '.gradle', '.idea', 'dist', 'out', '.kotlin']);
|
|
12
|
-
const MAX_DEPTH = 6;
|
|
13
|
-
const BUILD_FILES = ['build.gradle.kts', 'build.gradle', 'settings.gradle.kts', 'settings.gradle'];
|
|
14
|
-
const CATALOGS = ['libs.versions.toml'];
|
|
15
|
-
async function walk(root, depth = 0, acc = []) {
|
|
16
|
-
if (depth > MAX_DEPTH)
|
|
17
|
-
return acc;
|
|
18
|
-
let entries;
|
|
19
|
-
try {
|
|
20
|
-
entries = await readdir(root, { withFileTypes: true });
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
return acc;
|
|
24
|
-
}
|
|
25
|
-
for (const e of entries) {
|
|
26
|
-
if (e.name.startsWith('.') && e.name !== '.claude') {
|
|
27
|
-
if (SKIP.has(e.name))
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
if (SKIP.has(e.name))
|
|
31
|
-
continue;
|
|
32
|
-
const full = join(root, e.name);
|
|
33
|
-
if (e.isDirectory())
|
|
34
|
-
await walk(full, depth + 1, acc);
|
|
35
|
-
else
|
|
36
|
-
acc.push(full);
|
|
37
|
-
}
|
|
38
|
-
return acc;
|
|
39
|
-
}
|
|
40
|
-
/** `implementation("group:artifact:1.2.3")` and the `libs.` alias form. */
|
|
41
|
-
const DEP = /["']([a-zA-Z][\w.-]*(?:\.[\w-]+)+:[\w.-]+)(?::[^"']*)?["']/g;
|
|
42
|
-
const PLUGIN_ID = /id\s*\(?\s*["']([\w.-]+)["']/g;
|
|
43
|
-
const PLUGIN_ALIAS = /^\s*([\w-]+)\s*=\s*\{[^}]*id\s*=\s*["']([\w.-]+)["']/gm;
|
|
44
|
-
const TOML_DEP = /^\s*[\w-]+\s*=\s*\{[^}]*module\s*=\s*["']([\w.:-]+)["']/gm;
|
|
45
|
-
const TOML_GROUP = /^\s*[\w-]+\s*=\s*\{[^}]*group\s*=\s*["']([\w.-]+)["'][^}]*name\s*=\s*["']([\w.-]+)["']/gm;
|
|
46
|
-
export async function scanProject(root) {
|
|
47
|
-
const files = await walk(root);
|
|
48
|
-
const rel = files.map((f) => relative(root, f).split(sep).join('/'));
|
|
49
|
-
const dependencies = new Set();
|
|
50
|
-
const plugins = new Set();
|
|
51
|
-
const manifestElements = new Set();
|
|
52
|
-
const manifestAttributes = new Set();
|
|
53
|
-
const properties = new Set();
|
|
54
|
-
for (const f of files) {
|
|
55
|
-
const name = f.split(sep).pop();
|
|
56
|
-
const isBuild = BUILD_FILES.includes(name);
|
|
57
|
-
const isCatalog = CATALOGS.includes(name);
|
|
58
|
-
const isManifest = name === 'AndroidManifest.xml';
|
|
59
|
-
const isProps = name === 'gradle.properties';
|
|
60
|
-
if (!isBuild && !isCatalog && !isManifest && !isProps)
|
|
61
|
-
continue;
|
|
62
|
-
let text;
|
|
63
|
-
try {
|
|
64
|
-
text = await readFile(f, 'utf8');
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
if (isBuild || isCatalog) {
|
|
70
|
-
for (const m of text.matchAll(DEP))
|
|
71
|
-
dependencies.add(m[1]);
|
|
72
|
-
for (const m of text.matchAll(TOML_DEP))
|
|
73
|
-
dependencies.add(m[1]);
|
|
74
|
-
for (const m of text.matchAll(TOML_GROUP))
|
|
75
|
-
dependencies.add(`${m[1]}:${m[2]}`);
|
|
76
|
-
for (const m of text.matchAll(PLUGIN_ID))
|
|
77
|
-
plugins.add(m[1]);
|
|
78
|
-
for (const m of text.matchAll(PLUGIN_ALIAS))
|
|
79
|
-
plugins.add(m[2]);
|
|
80
|
-
}
|
|
81
|
-
if (isManifest) {
|
|
82
|
-
for (const m of text.matchAll(/<([a-zA-Z-]+)[\s>]/g))
|
|
83
|
-
manifestElements.add(m[1]);
|
|
84
|
-
for (const m of text.matchAll(/\s(android:[\w]+)\s*=/g))
|
|
85
|
-
manifestAttributes.add(m[1]);
|
|
86
|
-
}
|
|
87
|
-
if (isProps) {
|
|
88
|
-
for (const line of text.split('\n')) {
|
|
89
|
-
const eq = line.indexOf('=');
|
|
90
|
-
if (eq > 0 && !line.trimStart().startsWith('#'))
|
|
91
|
-
properties.add(line.slice(0, eq).trim());
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return {
|
|
96
|
-
file: rel,
|
|
97
|
-
gradle_dependency: [...dependencies],
|
|
98
|
-
gradle_plugin: [...plugins],
|
|
99
|
-
manifest_element: [...manifestElements],
|
|
100
|
-
manifest_attribute: [...manifestAttributes],
|
|
101
|
-
gradle_property: [...properties],
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
//# sourceMappingURL=scan.js.map
|
package/dist/scan.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"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"}
|
package/dist/state.d.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { type DriftKind, type LockEntry, type Lockfile, type Skill, type Target } from '@skyl/core';
|
|
2
|
-
/**
|
|
3
|
-
* What is installed here, next to what upstream currently says.
|
|
4
|
-
*
|
|
5
|
-
* `list`, `diff` and `update` all need exactly this, and computing it in one place is
|
|
6
|
-
* what keeps them from disagreeing about whether something has moved.
|
|
7
|
-
*/
|
|
8
|
-
export interface Installed {
|
|
9
|
-
readonly name: string;
|
|
10
|
-
readonly entry: LockEntry;
|
|
11
|
-
readonly skill: Skill | undefined;
|
|
12
|
-
/** What is in the file now, if the file is still there. */
|
|
13
|
-
readonly onDisk: string | undefined;
|
|
14
|
-
/** What we would write today. */
|
|
15
|
-
readonly upstream: string | undefined;
|
|
16
|
-
readonly state: DriftKind;
|
|
17
|
-
}
|
|
18
|
-
export declare function installedState(root: string, lock: Lockfile, target: Target, opts: {
|
|
19
|
-
dir?: string | undefined;
|
|
20
|
-
refresh?: boolean | undefined;
|
|
21
|
-
}): Promise<{
|
|
22
|
-
items: Installed[];
|
|
23
|
-
from: string | undefined;
|
|
24
|
-
}>;
|
|
25
|
-
/**
|
|
26
|
-
* A skill that moved upstream can still be byte-identical here: a patch release that
|
|
27
|
-
* only touched `## Why` changes the version and not a word of what was installed.
|
|
28
|
-
* Saying "update available" for that is noise, so the two are told apart.
|
|
29
|
-
*/
|
|
30
|
-
export declare function changedOnDisk(item: Installed): boolean;
|
|
31
|
-
//# sourceMappingURL=state.d.ts.map
|
package/dist/state.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAE,KAAK,KAAK,EAAE,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAI3G;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IAClC,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,iCAAiC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;CAC3B;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAAE,GAChE,OAAO,CAAC;IAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC,CA0B3D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAEtD"}
|
package/dist/state.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { drift } from '@skyl/core';
|
|
2
|
-
import { readInstalled, renderFor } from "./install.js";
|
|
3
|
-
import { loadRegistry } from "./registry.js";
|
|
4
|
-
export async function installedState(root, lock, target, opts) {
|
|
5
|
-
let registry;
|
|
6
|
-
let from;
|
|
7
|
-
try {
|
|
8
|
-
const reg = await loadRegistry(opts);
|
|
9
|
-
registry = new Map(reg.skills.map((s) => [s.name, s]));
|
|
10
|
-
from = reg.from;
|
|
11
|
-
}
|
|
12
|
-
catch {
|
|
13
|
-
// offline: local state is still worth showing, drift just cannot be judged
|
|
14
|
-
}
|
|
15
|
-
const items = [];
|
|
16
|
-
for (const name of Object.keys(lock.skills).sort()) {
|
|
17
|
-
const entry = lock.skills[name];
|
|
18
|
-
const skill = registry?.get(name);
|
|
19
|
-
const onDisk = skill ? await readInstalled(root, target, skill) : undefined;
|
|
20
|
-
items.push({
|
|
21
|
-
name,
|
|
22
|
-
entry,
|
|
23
|
-
skill,
|
|
24
|
-
onDisk,
|
|
25
|
-
upstream: skill ? renderFor(target, skill) : undefined,
|
|
26
|
-
state: registry === undefined ? 'unchanged' : drift(entry, onDisk, skill),
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
return { items, from };
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* A skill that moved upstream can still be byte-identical here: a patch release that
|
|
33
|
-
* only touched `## Why` changes the version and not a word of what was installed.
|
|
34
|
-
* Saying "update available" for that is noise, so the two are told apart.
|
|
35
|
-
*/
|
|
36
|
-
export function changedOnDisk(item) {
|
|
37
|
-
return item.upstream !== undefined && item.onDisk !== item.upstream;
|
|
38
|
-
}
|
|
39
|
-
//# sourceMappingURL=state.js.map
|
package/dist/state.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAA0E,MAAM,YAAY,CAAC;AAC3G,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAmB7C,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAY,EACZ,IAAc,EACd,MAAc,EACd,IAAiE;IAEjE,IAAI,QAAwC,CAAC;IAC7C,IAAI,IAAwB,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QACrC,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACvD,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QACP,2EAA2E;IAC7E,CAAC;IAED,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACnD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAE,CAAC;QACjC,MAAM,KAAK,GAAG,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5E,KAAK,CAAC,IAAI,CAAC;YACT,IAAI;YACJ,KAAK;YACL,KAAK;YACL,MAAM;YACN,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS;YACtD,KAAK,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC;SAC1E,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAe;IAC3C,OAAO,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,QAAQ,CAAC;AACtE,CAAC"}
|
package/dist/ui.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export declare const bold: (s: string) => string;
|
|
2
|
-
export declare const dim: (s: string) => string;
|
|
3
|
-
export declare const green: (s: string) => string;
|
|
4
|
-
export declare const yellow: (s: string) => string;
|
|
5
|
-
export declare const red: (s: string) => string;
|
|
6
|
-
export declare const cyan: (s: string) => string;
|
|
7
|
-
export declare function out(line?: string): void;
|
|
8
|
-
export declare function err(line: string): void;
|
|
9
|
-
/**
|
|
10
|
-
* A token estimate, shown before anything is written.
|
|
11
|
-
*
|
|
12
|
-
* Deliberately approximate and labelled as such: the real count depends on the model's
|
|
13
|
-
* tokenizer, and a precise-looking number nobody can reproduce is worse than a rough one.
|
|
14
|
-
*/
|
|
15
|
-
export declare function tokens(words: number): string;
|
|
16
|
-
export declare function confirm(question: string, assumeYes: boolean): Promise<boolean>;
|
|
17
|
-
//# sourceMappingURL=ui.d.ts.map
|
package/dist/ui.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,IAAI,MAFkB,MAAM,WAEZ,CAAC;AAC9B,eAAO,MAAM,GAAG,MAHmB,MAAM,WAGb,CAAC;AAC7B,eAAO,MAAM,KAAK,MAJiB,MAAM,WAIV,CAAC;AAChC,eAAO,MAAM,MAAM,MALgB,MAAM,WAKT,CAAC;AACjC,eAAO,MAAM,GAAG,MANmB,MAAM,WAMZ,CAAC;AAC9B,eAAO,MAAM,IAAI,MAPkB,MAAM,WAOX,CAAC;AAE/B,wBAAgB,GAAG,CAAC,IAAI,SAAK,GAAG,IAAI,CAAuC;AAC3E,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAuC;AAE9E;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAWpF"}
|
package/dist/ui.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/** Terminal output. Colour only when a terminal is attached and NO_COLOR is unset. */
|
|
2
|
-
const on = process.stdout.isTTY === true && !process.env['NO_COLOR'];
|
|
3
|
-
const wrap = (code) => (s) => (on ? `\u001b[${code}m${s}\u001b[0m` : s);
|
|
4
|
-
export const bold = wrap('1');
|
|
5
|
-
export const dim = wrap('2');
|
|
6
|
-
export const green = wrap('32');
|
|
7
|
-
export const yellow = wrap('33');
|
|
8
|
-
export const red = wrap('31');
|
|
9
|
-
export const cyan = wrap('36');
|
|
10
|
-
export function out(line = '') { process.stdout.write(`${line}\n`); }
|
|
11
|
-
export function err(line) { process.stderr.write(`${line}\n`); }
|
|
12
|
-
/**
|
|
13
|
-
* A token estimate, shown before anything is written.
|
|
14
|
-
*
|
|
15
|
-
* Deliberately approximate and labelled as such: the real count depends on the model's
|
|
16
|
-
* tokenizer, and a precise-looking number nobody can reproduce is worse than a rough one.
|
|
17
|
-
*/
|
|
18
|
-
export function tokens(words) {
|
|
19
|
-
return `~${(Math.round((words * 4) / 300) * 100).toLocaleString()} tokens`;
|
|
20
|
-
}
|
|
21
|
-
export async function confirm(question, assumeYes) {
|
|
22
|
-
if (assumeYes)
|
|
23
|
-
return true;
|
|
24
|
-
if (!process.stdin.isTTY)
|
|
25
|
-
return false;
|
|
26
|
-
process.stdout.write(`${question} [y/N] `);
|
|
27
|
-
const answer = await new Promise((resolve) => {
|
|
28
|
-
process.stdin.setEncoding('utf8');
|
|
29
|
-
process.stdin.once('data', (d) => resolve(String(d)));
|
|
30
|
-
process.stdin.resume();
|
|
31
|
-
});
|
|
32
|
-
process.stdin.pause();
|
|
33
|
-
return /^y(es)?$/i.test(answer.trim());
|
|
34
|
-
}
|
|
35
|
-
//# sourceMappingURL=ui.js.map
|
package/dist/ui.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AACrE,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAExF,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;AAC9B,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7B,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;AAChC,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;AACjC,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9B,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;AAE/B,MAAM,UAAU,GAAG,CAAC,IAAI,GAAG,EAAE,IAAU,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3E,MAAM,UAAU,GAAG,CAAC,IAAY,IAAU,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,KAAa;IAClC,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,cAAc,EAAE,SAAS,CAAC;AAC7E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,QAAgB,EAAE,SAAkB;IAChE,IAAI,SAAS;QAAE,OAAO,IAAI,CAAC;IAC3B,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,SAAS,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;QACnD,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACtB,OAAO,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import type { Skill } from './types.ts';
|
|
2
|
-
/**
|
|
3
|
-
* What a hand-written context file contains, measured against the registry.
|
|
4
|
-
*
|
|
5
|
-
* Analysis only. There is no rewriting here and there should not be: prose passed
|
|
6
|
-
* through a model reliably comes back longer and more generic, and the file being
|
|
7
|
-
* audited is usually one someone tuned by hand over months.
|
|
8
|
-
*
|
|
9
|
-
* Everything reported is lexical. Overlap means the section and the skill talk about the
|
|
10
|
-
* same things in the same words, which is a reason for a human to look, not a finding on
|
|
11
|
-
* its own. The matched terms are always shown, because a claim of overlap that cannot be
|
|
12
|
-
* checked is worth nothing.
|
|
13
|
-
*/
|
|
14
|
-
export interface SectionReport {
|
|
15
|
-
readonly heading: string;
|
|
16
|
-
readonly words: number;
|
|
17
|
-
/** Registry skills whose distinctive vocabulary this section shares. */
|
|
18
|
-
readonly overlaps: readonly {
|
|
19
|
-
readonly skill: string;
|
|
20
|
-
readonly share: number;
|
|
21
|
-
readonly terms: readonly string[];
|
|
22
|
-
}[];
|
|
23
|
-
/** No imperative wording anywhere in the section. */
|
|
24
|
-
readonly noInstruction: boolean;
|
|
25
|
-
}
|
|
26
|
-
export interface AuditReport {
|
|
27
|
-
readonly words: number;
|
|
28
|
-
readonly sections: readonly SectionReport[];
|
|
29
|
-
/** Things a context file is expected to carry that are not here. */
|
|
30
|
-
readonly missing: readonly string[];
|
|
31
|
-
/** Lines that look like a credential. Reported first, and never quoted in full. */
|
|
32
|
-
readonly secrets: readonly {
|
|
33
|
-
readonly line: number;
|
|
34
|
-
readonly what: string;
|
|
35
|
-
}[];
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Lines that look like a credential.
|
|
39
|
-
*
|
|
40
|
-
* Shared with the context bundler, where a hit is a hard refusal rather than a warning:
|
|
41
|
-
* a file that reaches a model has left the machine, and there is no taking it back.
|
|
42
|
-
*/
|
|
43
|
-
export declare function scanSecrets(text: string): {
|
|
44
|
-
line: number;
|
|
45
|
-
what: string;
|
|
46
|
-
}[];
|
|
47
|
-
export declare function audit(text: string, skills: readonly Skill[]): AuditReport;
|
|
48
|
-
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,SAAS;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IACpH,qDAAqD;IACrD,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;IAC5C,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,mFAAmF;IACnF,QAAQ,CAAC,OAAO,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC/E;AAuDD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAQ1E;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,EAAE,GAAG,WAAW,CAoCzE"}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { sections } from "./parse.js";
|
|
2
|
-
const STOP = new Set([
|
|
3
|
-
'the', 'a', 'an', 'and', 'or', 'but', 'if', 'then', 'is', 'are', 'was', 'be', 'been', 'to', 'of',
|
|
4
|
-
'in', 'on', 'for', 'with', 'as', 'at', 'by', 'from', 'that', 'this', 'it', 'its', 'not', 'no',
|
|
5
|
-
'do', 'does', 'use', 'using', 'used', 'when', 'where', 'which', 'you', 'your', 'we', 'our', 'can',
|
|
6
|
-
'will', 'should', 'must', 'never', 'always', 'all', 'any', 'each', 'per', 'into', 'out', 'up',
|
|
7
|
-
'has', 'have', 'they', 'them', 'their', 'one', 'two', 'more', 'than', 'so', 'only', 'also',
|
|
8
|
-
]);
|
|
9
|
-
const words = (text) => text.toLowerCase().match(/[a-z][a-z0-9_.]{2,}/g)?.filter((w) => !STOP.has(w)) ?? [];
|
|
10
|
-
const IMPERATIVE = /\b(must|never|always|do not|don't|avoid|prefer|require[sd]?|should|use\b)/i;
|
|
11
|
-
/**
|
|
12
|
-
* Terms that identify a skill: ones that appear in it and in few others.
|
|
13
|
-
*
|
|
14
|
-
* Without the rarity weighting every section matches every Android skill on words like
|
|
15
|
-
* "android" and "compose", and the report says nothing.
|
|
16
|
-
*/
|
|
17
|
-
function distinctive(skills) {
|
|
18
|
-
const perSkill = new Map();
|
|
19
|
-
const documents = new Map();
|
|
20
|
-
for (const skill of skills) {
|
|
21
|
-
const set = new Set(words(skill.installable));
|
|
22
|
-
perSkill.set(skill.name, set);
|
|
23
|
-
for (const term of set)
|
|
24
|
-
documents.set(term, (documents.get(term) ?? 0) + 1);
|
|
25
|
-
}
|
|
26
|
-
const limit = Math.max(1, Math.floor(skills.length / 4));
|
|
27
|
-
const out = new Map();
|
|
28
|
-
for (const [name, set] of perSkill) {
|
|
29
|
-
out.set(name, new Set([...set].filter((t) => (documents.get(t) ?? 0) <= limit)));
|
|
30
|
-
}
|
|
31
|
-
return out;
|
|
32
|
-
}
|
|
33
|
-
const SECRET = [
|
|
34
|
-
{ what: 'private key', re: /-----BEGIN [A-Z ]*PRIVATE KEY-----/ },
|
|
35
|
-
{ what: 'AWS access key', re: /\bAKIA[0-9A-Z]{16}\b/ },
|
|
36
|
-
{ what: 'Google API key', re: /\bAIza[0-9A-Za-z_-]{35}\b/ },
|
|
37
|
-
{ what: 'GitHub token', re: /\bgh[pousr]_[0-9A-Za-z]{36,}\b/ },
|
|
38
|
-
{ what: 'Slack token', re: /\bxox[abprs]-[0-9A-Za-z-]{10,}\b/ },
|
|
39
|
-
{ what: 'bearer token', re: /\b(?:bearer|authorization)\s*[:=]\s*["']?[A-Za-z0-9._-]{20,}/i },
|
|
40
|
-
{ what: 'assignment that looks like a secret', re: /\b(?:api[_-]?key|secret|password|passwd|token|credential)s?\s*[:=]\s*["'][^"'\s]{8,}["']/i },
|
|
41
|
-
];
|
|
42
|
-
const EXPECTS = [
|
|
43
|
-
{ what: 'placement, where new code goes', re: /\b(place|placement|goes in|belongs in|live[s]? in|directory structure|module layout)\b/i },
|
|
44
|
-
{ what: 'build, test or lint commands', re: /\b(\.\/gradlew|npm run|pnpm |yarn |make |pytest|cargo )/ },
|
|
45
|
-
{ what: 'entry points or flow names', re: /\b(entry point|starts (at|in)|flow|screen|endpoint)\b/i },
|
|
46
|
-
];
|
|
47
|
-
/**
|
|
48
|
-
* Lines that look like a credential.
|
|
49
|
-
*
|
|
50
|
-
* Shared with the context bundler, where a hit is a hard refusal rather than a warning:
|
|
51
|
-
* a file that reaches a model has left the machine, and there is no taking it back.
|
|
52
|
-
*/
|
|
53
|
-
export function scanSecrets(text) {
|
|
54
|
-
const out = [];
|
|
55
|
-
text.split('\n').forEach((line, i) => {
|
|
56
|
-
for (const s of SECRET) {
|
|
57
|
-
if (s.re.test(line)) {
|
|
58
|
-
out.push({ line: i + 1, what: s.what });
|
|
59
|
-
break;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
return out;
|
|
64
|
-
}
|
|
65
|
-
export function audit(text, skills) {
|
|
66
|
-
const secrets = scanSecrets(text);
|
|
67
|
-
const vocab = distinctive(skills);
|
|
68
|
-
const found = sections(text);
|
|
69
|
-
// a file with no headings is still worth auditing, as one section
|
|
70
|
-
const parts = found.size > 0 ? [...found] : [['(whole file)', text]];
|
|
71
|
-
const reports = parts.map(([heading, content]) => {
|
|
72
|
-
const terms = words(content);
|
|
73
|
-
const unique = new Set(terms);
|
|
74
|
-
const overlaps = [];
|
|
75
|
-
for (const [name, set] of vocab) {
|
|
76
|
-
const hit = [...unique].filter((t) => set.has(t));
|
|
77
|
-
if (hit.length < 4)
|
|
78
|
-
continue;
|
|
79
|
-
const share = hit.length / Math.max(unique.size, 1);
|
|
80
|
-
if (share < 0.04)
|
|
81
|
-
continue;
|
|
82
|
-
overlaps.push({ skill: name, share, terms: hit.slice(0, 8) });
|
|
83
|
-
}
|
|
84
|
-
overlaps.sort((a, b) => b.share - a.share);
|
|
85
|
-
return {
|
|
86
|
-
heading,
|
|
87
|
-
words: content.split(/\s+/).filter(Boolean).length,
|
|
88
|
-
overlaps: overlaps.slice(0, 3),
|
|
89
|
-
noInstruction: !IMPERATIVE.test(content),
|
|
90
|
-
};
|
|
91
|
-
});
|
|
92
|
-
return {
|
|
93
|
-
words: text.split(/\s+/).filter(Boolean).length,
|
|
94
|
-
sections: reports,
|
|
95
|
-
missing: EXPECTS.filter((e) => !e.re.test(text)).map((e) => e.what),
|
|
96
|
-
secrets,
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
//# sourceMappingURL=audit.js.map
|