@jaimevalasek/aioson 1.9.0 → 1.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jaimevalasek/aioson",
3
- "version": "1.9.0",
3
+ "version": "1.9.1",
4
4
  "description": "AI operating framework for hyper-personalized software.",
5
5
  "keywords": [
6
6
  "ai",
package/src/cli.js CHANGED
@@ -583,6 +583,8 @@ const JSON_SUPPORTED_COMMANDS = new Set([
583
583
  'pulse-update',
584
584
  'state:save',
585
585
  'state-save',
586
+ 'dev:state:write',
587
+ 'dev-state-write',
586
588
  'feature:close',
587
589
  'feature-close',
588
590
  'feature:archive',
@@ -1315,7 +1317,12 @@ async function main() {
1315
1317
  result = await runDetectTestRunner({ args, options, logger: commandLogger });
1316
1318
  } else if (command === 'pulse:update' || command === 'pulse-update') {
1317
1319
  result = await runPulseUpdate({ args, options, logger: commandLogger });
1318
- } else if (command === 'state:save' || command === 'state-save') {
1320
+ } else if (
1321
+ command === 'state:save' ||
1322
+ command === 'state-save' ||
1323
+ command === 'dev:state:write' ||
1324
+ command === 'dev-state-write'
1325
+ ) {
1319
1326
  result = await runStateSave({ args, options, logger: commandLogger });
1320
1327
  } else if (command === 'feature:close' || command === 'feature-close') {
1321
1328
  result = await runFeatureClose({ args, options, logger: commandLogger });
@@ -35,7 +35,7 @@ const {
35
35
  inferProjectTypeFromFramework,
36
36
  inferWeb3NetworkFromFramework,
37
37
  buildDeveloperProfile,
38
- recommendBeginnerProfile,
38
+ recommendCreatorProfile,
39
39
  buildTeamProfile
40
40
  } = require('../onboarding');
41
41
 
@@ -286,7 +286,7 @@ function buildDeveloperProfileFromOptions(options, defaults, t) {
286
286
  }
287
287
 
288
288
  function buildBeginnerProfileFromOptions(options, t) {
289
- const profile = recommendBeginnerProfile({
289
+ const profile = recommendCreatorProfile({
290
290
  projectSummary: resolveOption(options, 'project-summary', ''),
291
291
  expectedUsers: resolveOption(options, 'expected-users', ''),
292
292
  mobileRequirement: resolveOption(options, 'mobile-requirement', ''),
@@ -408,7 +408,7 @@ async function askBeginnerProfile(rl, data, logger, t) {
408
408
  const mobileRequirement = await ask(rl, t('setup_context.q_beginner_mobile'), '2');
409
409
  const hostingPreference = await ask(rl, t('setup_context.q_beginner_hosting'), '1');
410
410
 
411
- const recommendation = recommendBeginnerProfile({
411
+ const recommendation = recommendCreatorProfile({
412
412
  projectSummary,
413
413
  expectedUsers,
414
414
  mobileRequirement,
@@ -443,7 +443,7 @@ async function askBeginnerProfile(rl, data, logger, t) {
443
443
 
444
444
  return {
445
445
  ...custom,
446
- profile: 'beginner',
446
+ profile: 'creator',
447
447
  notes: uniqueStrings([
448
448
  ...localizeProfileNotes(recommendation, t).notes,
449
449
  t('setup_context.note_beginner_declined')
@@ -560,7 +560,7 @@ async function runSetupContext({ args, options, logger, t }) {
560
560
  let profileData = null;
561
561
  if (data.profile === 'developer') {
562
562
  profileData = await askDeveloperProfile(rl, data, t);
563
- } else if (data.profile === 'beginner') {
563
+ } else if (data.profile === 'creator') {
564
564
  profileData = await askBeginnerProfile(rl, data, logger, t);
565
565
  } else {
566
566
  profileData = await askTeamProfile(rl, data, t);
@@ -601,7 +601,7 @@ async function runSetupContext({ args, options, logger, t }) {
601
601
  let profileData = null;
602
602
  if (profile === 'developer') {
603
603
  profileData = buildDeveloperProfileFromOptions(options, data, t);
604
- } else if (profile === 'beginner') {
604
+ } else if (profile === 'creator') {
605
605
  profileData = buildBeginnerProfileFromOptions(options, t);
606
606
  } else {
607
607
  profileData = localizeProfileNotes(buildTeamProfileFromOptions(options, data), t);
@@ -1,25 +1,73 @@
1
1
  'use strict';
2
2
 
3
3
  /**
4
- * aioson state:save — create/update dev-state.md for @dev session resumption.
4
+ * aioson state:save (alias: dev:state:write) — create/update dev-state.md
5
+ * for @dev session resumption.
5
6
  *
6
- * Replaces the manual dev-state.md update block. Stores active feature,
7
- * phase, next step, spec version, and context package.
7
+ * Stores active feature, phase, next step, spec version, and context package.
8
+ * Invoked by upstream agents (@analyst, @product, @sheldon, @architect) at
9
+ * session end so the next @dev activation auto-resumes on `next_step` instead
10
+ * of cold-starting.
8
11
  *
9
12
  * Usage:
10
- * aioson state:save . --feature=checkout --phase=3 --next="Implement notification listeners" \
11
- * --spec-version=3 --status=in_progress
12
- * aioson state:save . --feature=checkout --next="Continue payment webhook" --status=in_progress
13
+ * aioson dev:state:write . --feature=checkout --phase=3 \
14
+ * --next="Implement notification listeners" --context=spec,requirements,impl-plan
15
+ * aioson state:save . --feature=checkout --next="Continue payment webhook"
16
+ *
17
+ * --context (optional): comma-separated canonical type tokens. Each token
18
+ * resolves to a feature-scoped path. Max 4 entries total (including the
19
+ * always-included project.context.md anchor). Unknown tokens or missing
20
+ * files emit a warning and are skipped — never fail the command.
21
+ *
22
+ * Canonical context tokens:
23
+ * prd → prd-{slug}.md
24
+ * requirements → requirements-{slug}.md
25
+ * spec → spec-{slug}.md
26
+ * architecture → architecture.md
27
+ * impl-plan → implementation-plan-{slug}.md
28
+ * sheldon → sheldon-enrichment-{slug}.md
29
+ * design-doc → design-doc-{slug}.md (falls back to design-doc.md)
30
+ * dossier → features/{slug}/dossier.md
31
+ *
32
+ * When --context is omitted, auto-detect kicks in (legacy behavior): include
33
+ * project.context.md + spec-{slug}.md + plan if present.
13
34
  */
14
35
 
15
36
  const fs = require('node:fs/promises');
16
37
  const path = require('node:path');
17
38
  const { contextDir, readFileSafe, parseFrontmatter, scanArtifacts } = require('../preflight-engine');
18
39
 
40
+ const MAX_CONTEXT = 4;
41
+
42
+ const CONTEXT_TYPE_MAP = {
43
+ prd: { rel: (slug) => `prd-${slug}.md` },
44
+ requirements: { rel: (slug) => `requirements-${slug}.md` },
45
+ spec: { rel: (slug) => `spec-${slug}.md` },
46
+ architecture: { rel: () => 'architecture.md' },
47
+ 'impl-plan': { rel: (slug) => `implementation-plan-${slug}.md` },
48
+ sheldon: { rel: (slug) => `sheldon-enrichment-${slug}.md` },
49
+ 'design-doc': { rel: (slug) => `design-doc-${slug}.md`, fallback: () => 'design-doc.md' },
50
+ dossier: { rel: (slug) => `features/${slug}/dossier.md` }
51
+ };
52
+
19
53
  function nowDate() {
20
54
  return new Date().toISOString().slice(0, 10);
21
55
  }
22
56
 
57
+ function parseContextFlag(value) {
58
+ if (value === undefined || value === null || value === '') return null;
59
+ return String(value).split(',').map((s) => s.trim()).filter(Boolean);
60
+ }
61
+
62
+ async function fileExistsRel(targetDir, rel) {
63
+ try {
64
+ await fs.access(path.join(contextDir(targetDir), rel));
65
+ return true;
66
+ } catch {
67
+ return false;
68
+ }
69
+ }
70
+
23
71
  async function runStateSave({ args, options = {}, logger }) {
24
72
  const targetDir = path.resolve(process.cwd(), args[0] || '.');
25
73
  const slug = options.feature ? String(options.feature) : null;
@@ -28,6 +76,7 @@ async function runStateSave({ args, options = {}, logger }) {
28
76
  const specVersion = options['spec-version'] ? String(options['spec-version']) : null;
29
77
  const status = options.status ? String(options.status) : 'in_progress';
30
78
  const plan = options.plan ? String(options.plan) : null;
79
+ const contextTokens = parseContextFlag(options.context);
31
80
 
32
81
  if (!slug) {
33
82
  if (options.json) return { ok: false, reason: 'missing_feature' };
@@ -41,13 +90,49 @@ async function runStateSave({ args, options = {}, logger }) {
41
90
  return { ok: false };
42
91
  }
43
92
 
44
- // Build context package based on what exists
93
+ // Build context package
45
94
  const artifacts = await scanArtifacts(targetDir, slug);
46
95
  const contextPackage = [];
47
- if (artifacts.project_context.exists) contextPackage.push('project.context.md');
48
- if (artifacts.spec.exists) contextPackage.push(`spec-${slug}.md`);
49
- if (plan) contextPackage.push(plan);
50
- else if (artifacts.implementation_plan.exists) contextPackage.push(`implementation-plan-${slug}.md`);
96
+ const warnings = [];
97
+
98
+ if (contextTokens) {
99
+ // Explicit mode: agent declares the canonical types to include.
100
+ // Always anchor with project.context.md (counts toward the 4-entry cap).
101
+ if (artifacts.project_context.exists) contextPackage.push('project.context.md');
102
+
103
+ for (const rawToken of contextTokens) {
104
+ const token = rawToken.toLowerCase();
105
+ if (contextPackage.length >= MAX_CONTEXT) {
106
+ warnings.push(`context cap reached (${MAX_CONTEXT}); skipped "${token}" and remaining`);
107
+ break;
108
+ }
109
+ const def = CONTEXT_TYPE_MAP[token];
110
+ if (!def) {
111
+ warnings.push(`unknown context type "${token}" (valid: ${Object.keys(CONTEXT_TYPE_MAP).join(', ')})`);
112
+ continue;
113
+ }
114
+ const relPath = def.rel(slug);
115
+ if (await fileExistsRel(targetDir, relPath)) {
116
+ if (!contextPackage.includes(relPath)) contextPackage.push(relPath);
117
+ } else if (def.fallback) {
118
+ const fb = def.fallback();
119
+ if (await fileExistsRel(targetDir, fb)) {
120
+ if (!contextPackage.includes(fb)) contextPackage.push(fb);
121
+ } else {
122
+ warnings.push(`"${token}" file missing (${relPath}); skipped`);
123
+ }
124
+ } else {
125
+ warnings.push(`"${token}" file missing (${relPath}); skipped`);
126
+ }
127
+ }
128
+ } else {
129
+ // Auto-detect (legacy behavior): keep backward compatibility for callers
130
+ // that haven't migrated to --context yet.
131
+ if (artifacts.project_context.exists) contextPackage.push('project.context.md');
132
+ if (artifacts.spec.exists) contextPackage.push(`spec-${slug}.md`);
133
+ if (plan) contextPackage.push(plan);
134
+ else if (artifacts.implementation_plan.exists) contextPackage.push(`implementation-plan-${slug}.md`);
135
+ }
51
136
 
52
137
  const today = nowDate();
53
138
  const statePath = path.join(contextDir(targetDir), 'dev-state.md');
@@ -104,7 +189,8 @@ async function runStateSave({ args, options = {}, logger }) {
104
189
  active_phase: phase,
105
190
  next_step: next,
106
191
  last_spec_version: specVersion,
107
- context_package: contextPackage
192
+ context_package: contextPackage,
193
+ warnings
108
194
  };
109
195
 
110
196
  if (options.json) return result;
@@ -115,8 +201,20 @@ async function runStateSave({ args, options = {}, logger }) {
115
201
  logger.log(` next_step: "${next}"`);
116
202
  if (specVersion) logger.log(` last_spec_version: ${specVersion}`);
117
203
  logger.log(` context_package: [${contextPackage.join(', ')}]`);
204
+ for (const w of warnings) logger.log(` warn: ${w}`);
205
+ if (warnings.length === 0 && contextTokens) {
206
+ // Visible confirmation banner — agent kernels can rely on this to know
207
+ // they fulfilled the dev-state.md producer contract for @dev cold-resume.
208
+ const preview = next.length > 80 ? `${next.slice(0, 77)}...` : next;
209
+ logger.log(` ✓ @dev will auto-resume on cold start: next_step="${preview}"`);
210
+ }
118
211
 
119
212
  return result;
120
213
  }
121
214
 
122
- module.exports = { runStateSave };
215
+ module.exports = {
216
+ runStateSave,
217
+ CONTEXT_TYPE_MAP,
218
+ MAX_CONTEXT,
219
+ parseContextFlag
220
+ };
@@ -40,6 +40,10 @@ async function runUpdate({ args, options, logger, t }) {
40
40
  logger.log(t('update.done_at', { targetDir }));
41
41
  logger.log(t('update.files_updated', { count: result.copied.length }));
42
42
  logger.log(t('update.backups_created', { count: result.backedUp.length }));
43
+ if (result.migrations && result.migrations.profileRename && result.migrations.profileRename.changed) {
44
+ logger.log('');
45
+ logger.log(t('update.profile_renamed'));
46
+ }
43
47
  if (!dryRun) {
44
48
  logger.log('');
45
49
  logger.log(t('update.reconfigure_hint'));
package/src/constants.js CHANGED
@@ -60,6 +60,7 @@ const MANAGED_FILES = [
60
60
  '.aioson/docs/deyvin/pair-execution.md',
61
61
  '.aioson/docs/deyvin/runtime-handoffs.md',
62
62
  '.aioson/docs/deyvin/debugging-escalation.md',
63
+ '.aioson/docs/handoff-persistence.md',
63
64
  '.aioson/docs/sheldon/research-loop.md',
64
65
  '.aioson/docs/sheldon/web-intelligence.md',
65
66
  '.aioson/docs/sheldon/quality-lens.md',
@@ -67,6 +68,9 @@ const MANAGED_FILES = [
67
68
  '.aioson/docs/sheldon/harness-contract.md',
68
69
  '.aioson/docs/dev/stack-conventions.md',
69
70
  '.aioson/docs/dev/execution-discipline.md',
71
+ '.aioson/skills/process/decision-presentation/SKILL.md',
72
+ '.aioson/skills/process/decision-presentation/references/jargon-map.en.yaml',
73
+ '.aioson/skills/process/decision-presentation/references/jargon-map.pt-BR.yaml',
70
74
  '.aioson/skills/static/laravel-conventions.md',
71
75
  '.aioson/skills/static/tall-stack-patterns.md',
72
76
  '.aioson/skills/static/jetstream-setup.md',
@@ -180,7 +184,7 @@ const CONTEXT_REQUIRED_FIELDS = [
180
184
 
181
185
  const CONTEXT_ALLOWED_CLASSIFICATIONS = ['MICRO', 'SMALL', 'MEDIUM'];
182
186
  const CONTEXT_ALLOWED_PROJECT_TYPES = ['web_app', 'api', 'site', 'script', 'dapp', 'desktop_app'];
183
- const CONTEXT_ALLOWED_PROFILES = ['developer', 'beginner', 'team'];
187
+ const CONTEXT_ALLOWED_PROFILES = ['developer', 'creator', 'team'];
184
188
 
185
189
  const AGENT_DEFINITIONS = [
186
190
  {
package/src/doctor.js CHANGED
@@ -18,6 +18,7 @@ const {
18
18
  assessLearningOrphans,
19
19
  assessDistillationLag
20
20
  } = require('./learning-loop-doctor');
21
+ const { assessJargonLeak } = require('./jargon-leak-doctor');
21
22
  const { openRuntimeDb } = require('./runtime-store');
22
23
 
23
24
  const BOOTSTRAP_REQUIRED = ['what-is.md', 'how-it-works.md', 'what-it-does.md', 'current-state.md'];
@@ -436,6 +437,57 @@ async function runDoctor(targetDir) {
436
437
  }
437
438
  }
438
439
 
440
+ // 8. lay-user-agent-mode — jargon_leak_detection (Phase 3)
441
+ // Independent of classification (the skip rule is profile-based, not
442
+ // size-based). Opens its own DB handle so it works for MICRO projects.
443
+ let jargonDb = null;
444
+ try {
445
+ try {
446
+ const handle = await openRuntimeDb(targetDir);
447
+ jargonDb = handle.db;
448
+ } catch {
449
+ jargonDb = null; // greenfield (EC-LUM-05)
450
+ }
451
+ const jargonAssessment = await assessJargonLeak({ db: jargonDb, targetDir });
452
+ if (jargonAssessment.skipped) {
453
+ checks.push({
454
+ id: 'jargon_leak_detection',
455
+ severity: 'warning',
456
+ key: 'doctor.jargon_leak_detection.skipped_dev',
457
+ params: { profile: jargonAssessment.profile },
458
+ ok: true
459
+ });
460
+ } else {
461
+ const params = {
462
+ count: jargonAssessment.count,
463
+ events: jargonAssessment.eventsScanned || 0,
464
+ profile: jargonAssessment.profile
465
+ };
466
+ checks.push({
467
+ id: 'jargon_leak_detection',
468
+ severity: 'warning',
469
+ key: jargonAssessment.ok
470
+ ? 'doctor.jargon_leak_detection.ok'
471
+ : 'doctor.jargon_leak_detection.fail',
472
+ params,
473
+ ok: jargonAssessment.ok,
474
+ hintKey: jargonAssessment.ok ? undefined : 'doctor.jargon_leak_detection.hint',
475
+ hintParams: jargonAssessment.ok
476
+ ? undefined
477
+ : {
478
+ samples: jargonAssessment.samples
479
+ .slice(0, 5)
480
+ .map((s) => `${s.agent}/${(s.terms || []).join('+')}`)
481
+ .join(', ') || '(none)'
482
+ }
483
+ });
484
+ }
485
+ } finally {
486
+ if (jargonDb) {
487
+ try { jargonDb.close(); } catch { /* swallow */ }
488
+ }
489
+ }
490
+
439
491
  // 5. permissions_in_sync
440
492
  const permsAssessment = await assessPermissionsSync(targetDir);
441
493
  const permsOk = !permsAssessment.protocolMissing
@@ -0,0 +1,101 @@
1
+ 'use strict';
2
+
3
+ // Gateway pointer merge — keeps the AIOSON instructions inside CLAUDE.md,
4
+ // AGENTS.md, OPENCODE.md, and .gemini/GEMINI.md without clobbering any
5
+ // project-authored content above the managed block. When the destination
6
+ // file already exists, the prior copy path skipped it entirely, leaving
7
+ // existing projects without the framework instructions. This module wraps
8
+ // the template body in <!-- AIOSON:BEGIN --> ... <!-- AIOSON:END --> markers
9
+ // and either appends or replaces that block in place.
10
+
11
+ const fs = require('node:fs/promises');
12
+ const path = require('node:path');
13
+ const { exists, copyFileWithDir, toRelativeSafe } = require('./utils');
14
+
15
+ const MARKER_BEGIN = '<!-- AIOSON:BEGIN -->';
16
+ const MARKER_END = '<!-- AIOSON:END -->';
17
+
18
+ const GATEWAY_POINTER_FILES = new Set([
19
+ 'CLAUDE.md',
20
+ 'AGENTS.md',
21
+ 'OPENCODE.md',
22
+ '.gemini/GEMINI.md'
23
+ ]);
24
+
25
+ function isGatewayPointerPath(rel) {
26
+ return GATEWAY_POINTER_FILES.has(rel);
27
+ }
28
+
29
+ function buildBlock(templateContent) {
30
+ const body = templateContent.endsWith('\n') ? templateContent : `${templateContent}\n`;
31
+ return `${MARKER_BEGIN}\n${body}${MARKER_END}\n`;
32
+ }
33
+
34
+ function findBlockRange(content) {
35
+ const start = content.indexOf(MARKER_BEGIN);
36
+ if (start === -1) return null;
37
+ const endIdx = content.indexOf(MARKER_END, start + MARKER_BEGIN.length);
38
+ if (endIdx === -1) return null;
39
+ let end = endIdx + MARKER_END.length;
40
+ if (content[end] === '\n') end += 1;
41
+ return { start, end };
42
+ }
43
+
44
+ async function mergeGatewayPointer({ templatePath, targetPath, backupRoot, targetDir, dryRun = false }) {
45
+ const templateContent = await fs.readFile(templatePath, 'utf8');
46
+ const block = buildBlock(templateContent);
47
+
48
+ if (!(await exists(targetPath))) {
49
+ if (!dryRun) await fs.writeFile(targetPath, block, 'utf8');
50
+ return { action: 'created' };
51
+ }
52
+
53
+ const existing = await fs.readFile(targetPath, 'utf8');
54
+ const range = findBlockRange(existing);
55
+
56
+ let next;
57
+ let action;
58
+ if (range) {
59
+ const before = existing.slice(0, range.start);
60
+ const after = existing.slice(range.end);
61
+ const cleanBefore = before.length === 0 || before.endsWith('\n') ? before : `${before}\n`;
62
+ next = `${cleanBefore}${block}${after}`;
63
+ action = 'block_updated';
64
+ } else {
65
+ const separator = existing.length === 0 ? '' : existing.endsWith('\n\n') ? '' : existing.endsWith('\n') ? '\n' : '\n\n';
66
+ next = `${existing}${separator}${block}`;
67
+ action = 'block_appended';
68
+ }
69
+
70
+ if (next === existing) return { action: 'unchanged' };
71
+
72
+ let backupPath = null;
73
+ let backupError = null;
74
+ if (backupRoot && targetDir) {
75
+ const rel = toRelativeSafe(targetDir, targetPath);
76
+ const dest = path.join(backupRoot, rel);
77
+ if (!dryRun) {
78
+ try {
79
+ await copyFileWithDir(targetPath, dest);
80
+ backupPath = dest;
81
+ } catch (err) {
82
+ backupError = err && err.message ? err.message : String(err);
83
+ }
84
+ } else {
85
+ backupPath = dest;
86
+ }
87
+ }
88
+
89
+ if (!dryRun) await fs.writeFile(targetPath, next, 'utf8');
90
+ return { action, backupPath, backupError };
91
+ }
92
+
93
+ module.exports = {
94
+ MARKER_BEGIN,
95
+ MARKER_END,
96
+ GATEWAY_POINTER_FILES,
97
+ isGatewayPointerPath,
98
+ buildBlock,
99
+ findBlockRange,
100
+ mergeGatewayPointer
101
+ };
@@ -343,6 +343,7 @@ module.exports = {
343
343
  done_at: 'Update completed at: {targetDir}',
344
344
  files_updated: 'Files updated: {count}',
345
345
  backups_created: 'Backups created: {count}',
346
+ profile_renamed: 'i Profile `beginner` renamed to `creator` in project.context.md to better describe the user. Behavior unchanged. Edit the file to switch to `developer` if desired.',
346
347
  reconfigure_hint: 'New options may be available. Run: aioson install --reconfigure'
347
348
  },
348
349
  info: {
@@ -381,7 +382,7 @@ module.exports = {
381
382
  context_project_type_value: '`project_type` must be one of {expected}',
382
383
  context_project_type_value_hint: 'Use web_app, api, site, script, dapp, or desktop_app exactly.',
383
384
  context_profile_value: '`profile` must be one of {expected}',
384
- context_profile_value_hint: 'Use developer, beginner, or team exactly.',
385
+ context_profile_value_hint: 'Use developer, creator, or team exactly.',
385
386
  context_interaction_language_format: '`interaction_language` is not a valid BCP-47 tag',
386
387
  context_interaction_language_format_hint: 'Use values like en, en-US, pt-BR.',
387
388
  context_conversation_language_format: '`conversation_language` is not a valid BCP-47 tag',
@@ -452,6 +453,12 @@ module.exports = {
452
453
  distillation_lag: 'Distillation lag: {closed} closed features but only {distillations} have an auto_distillation event (threshold {threshold})',
453
454
  distillation_lag_hint: 'Features missing distillation (first 5): {missing_slugs}. Check Phase 5 hook health.',
454
455
  distillation_lag_skipped_micro: 'Distillation lag check skipped: project classification is MICRO (BR-ALL-11)'
456
+ },
457
+ jargon_leak_detection: {
458
+ ok: 'No jargon leaks in user-facing agent events ({events} events scanned, profile={profile})',
459
+ fail: 'Jargon leaks: {count} occurrences across {events} events from MVP agents (profile={profile})',
460
+ hint: 'Affected events (first 5): {samples}. Translate the term via jargon-map.{en,pt-BR}.yaml or update the dictionary if the term is intentional.',
461
+ skipped_dev: 'Jargon leak check skipped: project profile is `{profile}` (jargon permitted in this mode)'
455
462
  }
456
463
  },
457
464
  i18n_add: {
@@ -533,7 +540,7 @@ module.exports = {
533
540
  detected: 'Detected framework: {framework} (installed={installed})',
534
541
  q_project_name: 'Project name',
535
542
  q_project_type: 'Project type (web_app|api|site|script|dapp|desktop_app)',
536
- q_profile: 'Profile: [1] developer [2] beginner [3] team',
543
+ q_profile: 'Profile: [1] developer [2] creator [3] team',
537
544
  q_use_detected_framework: 'Use detected framework? (true/false)',
538
545
  q_framework: 'Framework',
539
546
  q_framework_installed: 'Framework installed? (true/false)',
@@ -217,6 +217,7 @@ module.exports = {
217
217
  done_at: 'Actualizacion completada en: {targetDir}',
218
218
  files_updated: 'Archivos actualizados: {count}',
219
219
  backups_created: 'Backups creados: {count}',
220
+ profile_renamed: 'i Perfil `beginner` renombrado a `creator` en project.context.md para describir mejor al usuario. Comportamiento sin cambios. Edita el archivo para cambiar a `developer` si lo prefieres.',
220
221
  reconfigure_hint: 'Nuevas opciones pueden estar disponibles. Ejecuta: aioson install --reconfigure'
221
222
  },
222
223
  info: {
@@ -259,7 +260,7 @@ module.exports = {
259
260
  context_project_type_value: '`project_type` debe ser uno de {expected}',
260
261
  context_project_type_value_hint: 'Usa web_app, api, site, script, dapp o desktop_app exactamente.',
261
262
  context_profile_value: '`profile` debe ser uno de {expected}',
262
- context_profile_value_hint: 'Usa developer, beginner o team exactamente.',
263
+ context_profile_value_hint: 'Usa developer, creator o team exactamente.',
263
264
  context_interaction_language_format:
264
265
  '`interaction_language` no es una etiqueta BCP-47 valida',
265
266
  context_interaction_language_format_hint: 'Usa valores como en, en-US, pt-BR.',
@@ -330,6 +331,12 @@ module.exports = {
330
331
  distillation_lag: 'Retraso de distillation: {closed} features cerradas pero solo {distillations} tienen evento auto_distillation (umbral {threshold})',
331
332
  distillation_lag_hint: 'Features sin distillation (primeras 5): {missing_slugs}. Verifique el hook de la Phase 5.',
332
333
  distillation_lag_skipped_micro: 'Verificación de distillation_lag omitida: clasificación del proyecto es MICRO (BR-ALL-11)'
334
+ },
335
+ jargon_leak_detection: {
336
+ ok: 'Sin fugas de jerga en eventos de agentes user-facing ({events} eventos analizados, profile={profile})',
337
+ fail: 'Fugas de jerga: {count} ocurrencias en {events} eventos de agentes del MVP (profile={profile})',
338
+ hint: 'Eventos afectados (primeros 5): {samples}. Traduce el término vía jargon-map.{en,pt-BR}.yaml o actualiza el diccionario si el término es intencional.',
339
+ skipped_dev: 'Verificación de jargon_leak_detection omitida: profile del proyecto es `{profile}` (jerga permitida en este modo)'
333
340
  }
334
341
  },
335
342
  i18n_add: {
@@ -411,7 +418,7 @@ module.exports = {
411
418
  detected: 'Framework detectado: {framework} (installed={installed})',
412
419
  q_project_name: 'Nombre del proyecto',
413
420
  q_project_type: 'Tipo de proyecto (web_app|api|site|script|dapp|desktop_app)',
414
- q_profile: 'Perfil: [1] developer [2] beginner [3] team',
421
+ q_profile: 'Perfil: [1] developer [2] creator [3] team',
415
422
  q_use_detected_framework: 'Usar framework detectado? (true/false)',
416
423
  q_framework: 'Framework',
417
424
  q_framework_installed: 'Framework instalado? (true/false)',
@@ -216,6 +216,7 @@ module.exports = {
216
216
  done_at: 'Mise a jour terminee dans : {targetDir}',
217
217
  files_updated: 'Fichiers mis a jour : {count}',
218
218
  backups_created: 'Sauvegardes creees : {count}',
219
+ profile_renamed: 'i Profil `beginner` renomme en `creator` dans project.context.md pour mieux decrire l utilisateur. Comportement inchange. Modifiez le fichier pour passer a `developer` si vous le souhaitez.',
219
220
  reconfigure_hint: 'De nouvelles options peuvent etre disponibles. Lancez : aioson install --reconfigure'
220
221
  },
221
222
  info: {
@@ -258,7 +259,7 @@ module.exports = {
258
259
  context_project_type_value: '`project_type` doit etre une des valeurs {expected}',
259
260
  context_project_type_value_hint: 'Utilisez web_app, api, site, script, dapp ou desktop_app exactement.',
260
261
  context_profile_value: '`profile` doit etre une des valeurs {expected}',
261
- context_profile_value_hint: 'Utilisez developer, beginner ou team exactement.',
262
+ context_profile_value_hint: 'Utilisez developer, creator ou team exactement.',
262
263
  context_interaction_language_format:
263
264
  '`interaction_language` n est pas une balise BCP-47 valide',
264
265
  context_interaction_language_format_hint: 'Utilisez des valeurs comme en, en-US, pt-BR.',
@@ -329,6 +330,12 @@ module.exports = {
329
330
  distillation_lag: 'Retard distillation : {closed} features fermées mais seulement {distillations} ont un évènement auto_distillation (seuil {threshold})',
330
331
  distillation_lag_hint: 'Features sans distillation (5 premières) : {missing_slugs}. Vérifiez le hook de la Phase 5.',
331
332
  distillation_lag_skipped_micro: 'Vérification distillation_lag ignorée : classification du projet est MICRO (BR-ALL-11)'
333
+ },
334
+ jargon_leak_detection: {
335
+ ok: 'Aucune fuite de jargon dans les évènements des agents user-facing ({events} évènements analysés, profile={profile})',
336
+ fail: 'Fuites de jargon : {count} occurrences dans {events} évènements des agents du MVP (profile={profile})',
337
+ hint: 'Évènements affectés (5 premiers) : {samples}. Traduisez le terme via jargon-map.{en,pt-BR}.yaml ou mettez à jour le dictionnaire si le terme est intentionnel.',
338
+ skipped_dev: 'Vérification jargon_leak_detection ignorée : profile du projet est `{profile}` (jargon autorisé dans ce mode)'
332
339
  }
333
340
  },
334
341
  i18n_add: {
@@ -410,7 +417,7 @@ module.exports = {
410
417
  detected: 'Framework detecte : {framework} (installed={installed})',
411
418
  q_project_name: 'Nom du projet',
412
419
  q_project_type: 'Type de projet (web_app|api|site|script|dapp|desktop_app)',
413
- q_profile: 'Profil : [1] developer [2] beginner [3] team',
420
+ q_profile: 'Profil : [1] developer [2] creator [3] team',
414
421
  q_use_detected_framework: 'Utiliser le framework detecte ? (true/false)',
415
422
  q_framework: 'Framework',
416
423
  q_framework_installed: 'Framework installe ? (true/false)',
@@ -310,6 +310,7 @@ module.exports = {
310
310
  done_at: 'Atualizacao concluida em: {targetDir}',
311
311
  files_updated: 'Arquivos atualizados: {count}',
312
312
  backups_created: 'Backups criados: {count}',
313
+ profile_renamed: 'i Perfil `beginner` renomeado para `creator` em project.context.md para descrever melhor o usuario. Comportamento inalterado. Edite o arquivo para mudar para `developer` se preferir.',
313
314
  reconfigure_hint: 'Novas opcoes podem estar disponiveis. Execute: aioson install --reconfigure'
314
315
  },
315
316
  info: {
@@ -352,7 +353,7 @@ module.exports = {
352
353
  context_project_type_value: '`project_type` deve ser um de {expected}',
353
354
  context_project_type_value_hint: 'Use web_app, api, site, script, dapp ou desktop_app exatamente.',
354
355
  context_profile_value: '`profile` deve ser um de {expected}',
355
- context_profile_value_hint: 'Use developer, beginner ou team exatamente.',
356
+ context_profile_value_hint: 'Use developer, creator ou team exatamente.',
356
357
  context_interaction_language_format:
357
358
  '`interaction_language` nao e uma tag BCP-47 valida',
358
359
  context_interaction_language_format_hint: 'Use valores como en, en-US, pt-BR.',
@@ -424,6 +425,12 @@ module.exports = {
424
425
  distillation_lag: 'Lag de distillation: {closed} features fechadas mas apenas {distillations} têm evento auto_distillation (limite {threshold})',
425
426
  distillation_lag_hint: 'Features sem distillation (primeiras 5): {missing_slugs}. Verifique o hook da Phase 5.',
426
427
  distillation_lag_skipped_micro: 'Check de distillation_lag ignorado: classificação do projeto é MICRO (BR-ALL-11)'
428
+ },
429
+ jargon_leak_detection: {
430
+ ok: 'Sem vazamento de jargão nos eventos dos agentes user-facing ({events} eventos analisados, profile={profile})',
431
+ fail: 'Vazamento de jargão: {count} ocorrências em {events} eventos dos agentes do MVP (profile={profile})',
432
+ hint: 'Eventos afetados (primeiros 5): {samples}. Traduza o termo via jargon-map.{en,pt-BR}.yaml ou atualize o dicionário se o termo for intencional.',
433
+ skipped_dev: 'Check de jargon_leak_detection ignorado: profile do projeto é `{profile}` (jargão permitido nesse modo)'
427
434
  }
428
435
  },
429
436
  i18n_add: {
@@ -505,7 +512,7 @@ module.exports = {
505
512
  detected: 'Framework detectado: {framework} (installed={installed})',
506
513
  q_project_name: 'Nome do projeto',
507
514
  q_project_type: 'Tipo do projeto (web_app|api|site|script|dapp|desktop_app)',
508
- q_profile: 'Perfil: [1] developer [2] beginner [3] team',
515
+ q_profile: 'Perfil: [1] developer [2] creator [3] team',
509
516
  q_use_detected_framework: 'Usar framework detectado? (true/false)',
510
517
  q_framework: 'Framework',
511
518
  q_framework_installed: 'Framework instalado? (true/false)',