proteum 2.5.6 → 2.5.7
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/agents/project/AGENTS.md
CHANGED
|
@@ -81,7 +81,6 @@ Managed compact root routers must use trigger -> canonical instruction file refe
|
|
|
81
81
|
- Before finishing, re-check touched files against root-level `CODING_STYLE.md` and any narrower area `AGENTS.md` that applied to the edit. Re-check against root-level `optimizations.md` only for touched client-side files. Re-check against root-level `diagnostics.md` only if the task involved an issue, diagnosis, runtime reproduction, or verification failure.
|
|
82
82
|
- Before finishing a production code change, re-check root-level `DOCUMENTATION.md` update rules. If behavior changed, a bug was fixed, a decision changed, or an important route, auth/OAuth, or integration issue was addressed, update the relevant docs before committing or explicitly explain why no docs update was needed.
|
|
83
83
|
- Run targeted tests and checks that match the changed surface before finishing each feature or change. When the repository defines `proteum.verify.config.ts`, use `npx proteum verify changed` as the first post-change verification pass and expand only when the selected plan is insufficient. Continue running tests after changes, but do not run coverage by default. Downstream app commit workflows run only `proteum refresh`, then targeted lint, typecheck, and test commands in parallel; framework-repo commit workflows skip this downstream app verification. Reserve the full `npm run check` gate for push workflows, explicit user requests, or when project-local instructions require the full gate. After implementing a new feature or changing existing feature behavior, update the relevant end-to-end coverage and run the cheapest trustworthy Playwright or browser verification for that behavior before finishing. For docs-only, wording-only, type-only, generated-output cleanup, or clearly local non-runtime refactors, skip Playwright unless the user explicitly asks for it or verification reveals a real issue.
|
|
84
|
-
- Before finishing a task, stop every `proteum dev` session started during the task and confirm cleanup with `npx proteum dev list --json` or an explicit `npx proteum dev stop --session-file <path>`.
|
|
85
84
|
- When you have finished your work, ask the user whether they want a commit message. After providing a commit message or after creating a commit, immediately follow it with this exact prompt and obey it:
|
|
86
85
|
`Explain in short minimalistic and few bullet points what we changed in this thread, like you would do to your grandma. Start with a verb in the past.`
|
|
87
86
|
|
|
@@ -67,7 +67,6 @@ Managed compact root routers must use trigger -> canonical instruction file refe
|
|
|
67
67
|
- Before finishing a production code change, re-check root-level `DOCUMENTATION.md` update rules. If behavior changed, a bug was fixed, a decision changed, or an important route, auth/OAuth, or integration issue was addressed, update the relevant docs before committing or explicitly explain why no docs update was needed.
|
|
68
68
|
- For production changes, always add or update focused unit tests and run the targeted unit or integration tests that match the changed behavior. Do not run coverage after every ordinary change by default. Reserve whole-project coverage for the repository's full `npm run check` gate during push workflows or when the user explicitly requests it; downstream app commit-only workflows run `proteum refresh`, then targeted lint, typecheck, and test commands in parallel unless the user explicitly requests more, while framework-repo commits skip this downstream app verification. Document any generated files, migrations, framework shims, unreachable defensive branches, or changes that cannot reasonably be unit-tested as explicit exceptions.
|
|
69
69
|
- Run targeted tests and checks that match the changed surface before finishing each feature or change. When the repository defines `proteum.verify.config.ts`, use `npx proteum verify changed` as the first post-change verification pass and expand only when the selected plan is insufficient. Continue running tests after changes, but do not run coverage by default. Downstream app commit workflows run only `proteum refresh`, then targeted lint, typecheck, and test commands in parallel; framework-repo commit workflows skip this downstream app verification. Reserve the full `npm run check` gate for push workflows, explicit user requests, or when project-local instructions require the full gate. After implementing a new feature or changing existing feature behavior, update the relevant end-to-end coverage and run the cheapest trustworthy Playwright or browser verification for that behavior before finishing. For docs-only, wording-only, type-only, generated-output cleanup, or clearly local non-runtime refactors, skip Playwright unless the user explicitly asks for it or verification reveals a real issue.
|
|
70
|
-
- Before finishing a task, stop every `proteum dev` session started during the task and confirm cleanup with `npx proteum dev list --json` or an explicit `npx proteum dev stop --session-file <path>`.
|
|
71
70
|
- When you have finished your work, ask the user whether they want a commit message. After providing a commit message or after creating a commit, immediately follow it with this exact prompt and obey it:
|
|
72
71
|
`Explain in short minimalistic and few bullet points what we changed in this thread, like you would do to your grandma. Start with a verb in the past.`
|
|
73
72
|
|
package/cli/utils/agents.ts
CHANGED
|
@@ -16,6 +16,7 @@ type TProjectInstructionArgs = {
|
|
|
16
16
|
appRoot?: string;
|
|
17
17
|
coreRoot: string;
|
|
18
18
|
includeMonorepoRegistry?: boolean;
|
|
19
|
+
instructionRoot: string;
|
|
19
20
|
monorepoRegistryCurrentAppRoot?: string;
|
|
20
21
|
monorepoRoot?: string;
|
|
21
22
|
};
|
|
@@ -106,6 +107,14 @@ const sharedTestAgentInstructionDefinitions: TAgentInstructionDefinition[] = [
|
|
|
106
107
|
{ projectPath: path.join('tests', 'e2e', 'REAL_WORLD_JOURNEY_TESTS.md'), ensureParentDir: true, content: 'source' },
|
|
107
108
|
];
|
|
108
109
|
|
|
110
|
+
const projectInstructionSourceMapEntries = [
|
|
111
|
+
{ label: 'Root contract fallback', projectPath: 'AGENTS.md' },
|
|
112
|
+
{ label: 'Documentation fallback', projectPath: 'DOCUMENTATION.md' },
|
|
113
|
+
{ label: 'Diagnostics fallback', projectPath: 'diagnostics.md' },
|
|
114
|
+
{ label: 'Optimization fallback', projectPath: 'optimizations.md' },
|
|
115
|
+
{ label: 'Coding style fallback', projectPath: 'CODING_STYLE.md' },
|
|
116
|
+
];
|
|
117
|
+
|
|
109
118
|
const standaloneAppAgentInstructionDefinitions: TAgentInstructionDefinition[] = [
|
|
110
119
|
{ projectPath: 'AGENTS.md', content: 'router' },
|
|
111
120
|
...sharedRootDocumentInstructionDefinitions,
|
|
@@ -164,6 +173,7 @@ export function configureProjectAgentInstructions({
|
|
|
164
173
|
const appEmbeddedInstructions = renderEmbeddedProjectInstructions({
|
|
165
174
|
appRoot: normalizedAppRoot,
|
|
166
175
|
coreRoot,
|
|
176
|
+
instructionRoot: normalizedAppRoot,
|
|
167
177
|
monorepoRoot: normalizedMonorepoRoot,
|
|
168
178
|
});
|
|
169
179
|
const rootEmbeddedInstructions =
|
|
@@ -172,6 +182,7 @@ export function configureProjectAgentInstructions({
|
|
|
172
182
|
appRoot: normalizedAppRoot,
|
|
173
183
|
coreRoot,
|
|
174
184
|
includeMonorepoRegistry: true,
|
|
185
|
+
instructionRoot: normalizedMonorepoRoot,
|
|
175
186
|
monorepoRegistryCurrentAppRoot: markCurrentAppInMonorepoRegistry ? normalizedAppRoot : undefined,
|
|
176
187
|
monorepoRoot: normalizedMonorepoRoot,
|
|
177
188
|
})
|
|
@@ -973,6 +984,7 @@ function renderEmbeddedProjectInstructions({
|
|
|
973
984
|
appRoot,
|
|
974
985
|
coreRoot,
|
|
975
986
|
includeMonorepoRegistry = false,
|
|
987
|
+
instructionRoot,
|
|
976
988
|
monorepoRegistryCurrentAppRoot,
|
|
977
989
|
monorepoRoot,
|
|
978
990
|
}: TProjectInstructionArgs) {
|
|
@@ -1063,11 +1075,14 @@ function renderEmbeddedProjectInstructions({
|
|
|
1063
1075
|
'',
|
|
1064
1076
|
'## Canonical Source Map',
|
|
1065
1077
|
'',
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1078
|
+
...projectInstructionSourceMapEntries.map(
|
|
1079
|
+
({ label, projectPath }) =>
|
|
1080
|
+
`- ${label}: ${formatProjectInstructionSourceMapPath({
|
|
1081
|
+
coreRoot,
|
|
1082
|
+
instructionRoot,
|
|
1083
|
+
projectPath,
|
|
1084
|
+
})}`,
|
|
1085
|
+
),
|
|
1071
1086
|
'',
|
|
1072
1087
|
];
|
|
1073
1088
|
|
|
@@ -1209,6 +1224,41 @@ function formatResultPath(rootDir: string, relativePath: string) {
|
|
|
1209
1224
|
return normalizeProjectPathForGitignore(path.join(rootDir, relativePath));
|
|
1210
1225
|
}
|
|
1211
1226
|
|
|
1227
|
+
function formatProjectInstructionSourceMapPath({
|
|
1228
|
+
coreRoot,
|
|
1229
|
+
instructionRoot,
|
|
1230
|
+
projectPath,
|
|
1231
|
+
}: {
|
|
1232
|
+
coreRoot: string;
|
|
1233
|
+
instructionRoot: string;
|
|
1234
|
+
projectPath: string;
|
|
1235
|
+
}) {
|
|
1236
|
+
const sourceRoot = resolveProjectInstructionSourceMapRoot({ coreRoot, instructionRoot });
|
|
1237
|
+
const sourcePath = path.resolve(sourceRoot, 'agents', 'project', projectPath);
|
|
1238
|
+
const relativePath = path.relative(path.resolve(instructionRoot), sourcePath);
|
|
1239
|
+
|
|
1240
|
+
return normalizeProjectPathForGitignore(relativePath);
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
function resolveProjectInstructionSourceMapRoot({ coreRoot, instructionRoot }: { coreRoot: string; instructionRoot: string }) {
|
|
1244
|
+
const visibleInstallRoot = findVisibleProteumInstructionRoot(instructionRoot);
|
|
1245
|
+
|
|
1246
|
+
return visibleInstallRoot || coreRoot;
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
function findVisibleProteumInstructionRoot(startRoot: string) {
|
|
1250
|
+
let currentPath = path.resolve(startRoot);
|
|
1251
|
+
|
|
1252
|
+
while (true) {
|
|
1253
|
+
const candidate = path.join(currentPath, 'node_modules', 'proteum');
|
|
1254
|
+
if (fs.existsSync(path.join(candidate, 'agents', 'project'))) return candidate;
|
|
1255
|
+
|
|
1256
|
+
const parentPath = path.dirname(currentPath);
|
|
1257
|
+
if (parentPath === currentPath) return undefined;
|
|
1258
|
+
currentPath = parentPath;
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1212
1262
|
export function resolveCanonicalPath(inputPath: string) {
|
|
1213
1263
|
const resolvedPath = path.resolve(inputPath);
|
|
1214
1264
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "proteum",
|
|
3
3
|
"description": "LLM-first Opinionated Typescript Framework for web applications.",
|
|
4
|
-
"version": "2.5.
|
|
4
|
+
"version": "2.5.7",
|
|
5
5
|
"author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
|
|
6
6
|
"repository": "git://github.com/gaetanlegac/proteum.git",
|
|
7
7
|
"license": "MIT",
|
|
@@ -38,8 +38,9 @@ const pathEntryExists = (filepath) => {
|
|
|
38
38
|
|
|
39
39
|
const makeTempRoot = () => fs.mkdtempSync(path.join(os.tmpdir(), 'proteum-agents-'));
|
|
40
40
|
|
|
41
|
-
const
|
|
42
|
-
|
|
41
|
+
const normalizePath = (value) => value.replace(/\\/g, '/');
|
|
42
|
+
|
|
43
|
+
const createCoreFixture = (root = makeTempRoot()) => {
|
|
43
44
|
const agentsRoot = path.join(root, 'agents', 'project');
|
|
44
45
|
|
|
45
46
|
writeFile(path.join(agentsRoot, 'AGENTS.md'), '# Root Contract\n\n- Root rule\n');
|
|
@@ -61,6 +62,20 @@ const createCoreFixture = () => {
|
|
|
61
62
|
return root;
|
|
62
63
|
};
|
|
63
64
|
|
|
65
|
+
const expectedSourceMapPath = ({ coreRoot, instructionRoot, projectPath }) =>
|
|
66
|
+
normalizePath(path.relative(instructionRoot, path.join(coreRoot, 'agents', 'project', projectPath)));
|
|
67
|
+
|
|
68
|
+
const assertSourceMapPath = ({ content, coreRoot, instructionRoot, label, projectPath }) => {
|
|
69
|
+
assert.equal(
|
|
70
|
+
content.includes(`- ${label}: ${expectedSourceMapPath({ coreRoot, instructionRoot, projectPath })}`),
|
|
71
|
+
true,
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const assertNoAbsoluteCoreSourceMapPath = ({ content, coreRoot }) => {
|
|
76
|
+
assert.equal(content.includes(normalizePath(path.join(coreRoot, 'agents', 'project'))), false);
|
|
77
|
+
};
|
|
78
|
+
|
|
64
79
|
const createAppFixture = () => {
|
|
65
80
|
const appRoot = makeTempRoot();
|
|
66
81
|
|
|
@@ -173,6 +188,53 @@ test('standalone configure creates tracked instruction files with routing contra
|
|
|
173
188
|
assert.doesNotMatch(gitignoreContent, /^\/DOCUMENTATION\.md$/m);
|
|
174
189
|
});
|
|
175
190
|
|
|
191
|
+
test('standalone configure writes install-relative source map fallbacks', () => {
|
|
192
|
+
const appRoot = createAppFixture();
|
|
193
|
+
const coreRoot = createCoreFixture(path.join(appRoot, 'node_modules', 'proteum'));
|
|
194
|
+
const result = configureProjectAgentInstructions({ appRoot, coreRoot });
|
|
195
|
+
const agentsContent = fs.readFileSync(path.join(appRoot, 'AGENTS.md'), 'utf8');
|
|
196
|
+
|
|
197
|
+
assert.equal(result.blocked.length, 0);
|
|
198
|
+
assertSourceMapPath({
|
|
199
|
+
content: agentsContent,
|
|
200
|
+
coreRoot,
|
|
201
|
+
instructionRoot: appRoot,
|
|
202
|
+
label: 'Root contract fallback',
|
|
203
|
+
projectPath: 'AGENTS.md',
|
|
204
|
+
});
|
|
205
|
+
assertSourceMapPath({
|
|
206
|
+
content: agentsContent,
|
|
207
|
+
coreRoot,
|
|
208
|
+
instructionRoot: appRoot,
|
|
209
|
+
label: 'Documentation fallback',
|
|
210
|
+
projectPath: 'DOCUMENTATION.md',
|
|
211
|
+
});
|
|
212
|
+
assertNoAbsoluteCoreSourceMapPath({ content: agentsContent, coreRoot });
|
|
213
|
+
assert.match(agentsContent, /Root contract fallback: node_modules\/proteum\/agents\/project\/AGENTS\.md/);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
test('standalone configure source map prefers project install over active external core', () => {
|
|
217
|
+
const activeCoreRoot = createCoreFixture();
|
|
218
|
+
const appRoot = createAppFixture();
|
|
219
|
+
createCoreFixture(path.join(appRoot, 'node_modules', 'proteum'));
|
|
220
|
+
|
|
221
|
+
configureProjectAgentInstructions({ appRoot, coreRoot: activeCoreRoot });
|
|
222
|
+
|
|
223
|
+
const agentsContent = fs.readFileSync(path.join(appRoot, 'AGENTS.md'), 'utf8');
|
|
224
|
+
assert.match(agentsContent, /Root contract fallback: node_modules\/proteum\/agents\/project\/AGENTS\.md/);
|
|
225
|
+
assert.equal(
|
|
226
|
+
agentsContent.includes(
|
|
227
|
+
`Root contract fallback: ${expectedSourceMapPath({
|
|
228
|
+
coreRoot: activeCoreRoot,
|
|
229
|
+
instructionRoot: appRoot,
|
|
230
|
+
projectPath: 'AGENTS.md',
|
|
231
|
+
})}`,
|
|
232
|
+
),
|
|
233
|
+
false,
|
|
234
|
+
);
|
|
235
|
+
assertNoAbsoluteCoreSourceMapPath({ content: agentsContent, coreRoot: activeCoreRoot });
|
|
236
|
+
});
|
|
237
|
+
|
|
176
238
|
test('configure preserves project content outside the managed section', () => {
|
|
177
239
|
const coreRoot = createCoreFixture();
|
|
178
240
|
const appRoot = createAppFixture();
|
|
@@ -296,6 +358,22 @@ test('monorepo configure writes root and app instruction files', () => {
|
|
|
296
358
|
assert.match(appAgentsContent, /## Agent Routing Contract/);
|
|
297
359
|
assert.doesNotMatch(appAgentsContent, /## Known Proteum Apps/);
|
|
298
360
|
assert.doesNotMatch(appAgentsContent, /Eligible Proteum commands run across the apps below/);
|
|
361
|
+
assertSourceMapPath({
|
|
362
|
+
content: fs.readFileSync(path.join(monorepoRoot, 'AGENTS.md'), 'utf8'),
|
|
363
|
+
coreRoot,
|
|
364
|
+
instructionRoot: monorepoRoot,
|
|
365
|
+
label: 'Root contract fallback',
|
|
366
|
+
projectPath: 'AGENTS.md',
|
|
367
|
+
});
|
|
368
|
+
assertSourceMapPath({
|
|
369
|
+
content: appAgentsContent,
|
|
370
|
+
coreRoot,
|
|
371
|
+
instructionRoot: appRoot,
|
|
372
|
+
label: 'Root contract fallback',
|
|
373
|
+
projectPath: 'AGENTS.md',
|
|
374
|
+
});
|
|
375
|
+
assertNoAbsoluteCoreSourceMapPath({ content: fs.readFileSync(path.join(monorepoRoot, 'AGENTS.md'), 'utf8'), coreRoot });
|
|
376
|
+
assertNoAbsoluteCoreSourceMapPath({ content: appAgentsContent, coreRoot });
|
|
299
377
|
assert.match(fs.readFileSync(path.join(appRoot, 'client', 'AGENTS.md'), 'utf8'), /## Source: client\/AGENTS\.md/);
|
|
300
378
|
assertClaudeSymlink(appRoot);
|
|
301
379
|
assertClaudeSymlink(appRoot, 'client');
|
|
@@ -306,6 +384,28 @@ test('monorepo configure writes root and app instruction files', () => {
|
|
|
306
384
|
assert.equal(result.removed.some((entry) => entry.endsWith('/apps/product/CODING_STYLE.md')), true);
|
|
307
385
|
});
|
|
308
386
|
|
|
387
|
+
test('monorepo configure source map uses workspace install from root and nested apps', () => {
|
|
388
|
+
const activeCoreRoot = createCoreFixture();
|
|
389
|
+
const monorepoRoot = makeTempRoot();
|
|
390
|
+
const appRoot = path.join(monorepoRoot, 'apps', 'product');
|
|
391
|
+
|
|
392
|
+
createCoreFixture(path.join(monorepoRoot, 'node_modules', 'proteum'));
|
|
393
|
+
fs.mkdirSync(path.join(monorepoRoot, '.git'));
|
|
394
|
+
fs.mkdirSync(path.join(appRoot, 'client'), { recursive: true });
|
|
395
|
+
writeFile(path.join(appRoot, 'package.json'), '{"name":"product"}\n');
|
|
396
|
+
writeFile(path.join(appRoot, 'identity.config.ts'), 'export default {};\n');
|
|
397
|
+
writeFile(path.join(appRoot, 'proteum.config.ts'), 'export default {};\n');
|
|
398
|
+
|
|
399
|
+
configureProjectAgentInstructions({ appRoot, coreRoot: activeCoreRoot, monorepoRoot });
|
|
400
|
+
|
|
401
|
+
const rootAgentsContent = fs.readFileSync(path.join(monorepoRoot, 'AGENTS.md'), 'utf8');
|
|
402
|
+
const appAgentsContent = fs.readFileSync(path.join(appRoot, 'AGENTS.md'), 'utf8');
|
|
403
|
+
assert.match(rootAgentsContent, /Root contract fallback: node_modules\/proteum\/agents\/project\/AGENTS\.md/);
|
|
404
|
+
assert.match(appAgentsContent, /Root contract fallback: \.\.\/\.\.\/node_modules\/proteum\/agents\/project\/AGENTS\.md/);
|
|
405
|
+
assertNoAbsoluteCoreSourceMapPath({ content: rootAgentsContent, coreRoot: activeCoreRoot });
|
|
406
|
+
assertNoAbsoluteCoreSourceMapPath({ content: appAgentsContent, coreRoot: activeCoreRoot });
|
|
407
|
+
});
|
|
408
|
+
|
|
309
409
|
test('monorepo-wide configure writes shared root once and all app instruction files', () => {
|
|
310
410
|
const coreRoot = createCoreFixture();
|
|
311
411
|
const monorepoRoot = makeTempRoot();
|