@event4u/agent-config 14.17.0 → 14.19.0
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/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +207 -77
- package/README.md +72 -150
- package/dist/agent-src/README.md +1 -1
- package/dist/agent-src/commands/agent-handoff.md +2 -2
- package/dist/agent-src/commands/pr/merge.md +35 -44
- package/dist/agent-src/commands/review/changes.md +19 -19
- package/dist/agent-src/commands/review.md +2 -2
- package/dist/agent-src/contexts/execution/host-capability-manifest.md +30 -3
- package/dist/agent-src/rules/autonomous-execution.md +1 -1
- package/dist/agent-src/rules/git-history-discipline.md +2 -2
- package/dist/agent-src/rules/guidelines.md +1 -1
- package/dist/agent-src/rules/session-canary.md +2 -2
- package/dist/agent-src/rules/token-efficiency.md +1 -1
- package/dist/agent-src/skills/accessibility-auditor/SKILL.md +2 -0
- package/dist/agent-src/skills/adversarial-review/SKILL.md +0 -8
- package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +27 -1
- package/dist/agent-src/skills/canvas-design/SKILL.md +1 -1
- package/dist/agent-src/skills/code-intelligence/SKILL.md +60 -12
- package/dist/agent-src/skills/complexity-first-planning/SKILL.md +27 -0
- package/dist/agent-src/skills/design-intelligence/SKILL.md +1 -1
- package/dist/agent-src/skills/design-intelligence/data/app-interface.csv +1 -1
- package/dist/agent-src/skills/design-intelligence/data/motion.csv +17 -17
- package/dist/agent-src/skills/design-intelligence/data/ux-guidelines.csv +2 -2
- package/dist/agent-src/skills/design-intelligence/references/context-and-registers.md +17 -0
- package/dist/agent-src/skills/design-intelligence/references/design-rules-checklist.md +4 -4
- package/dist/agent-src/skills/design-review/SKILL.md +3 -1
- package/dist/agent-src/skills/design-variations/SKILL.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +1 -1
- package/dist/agent-src/skills/fe-design/SKILL.md +32 -5
- package/dist/agent-src/skills/fe-design/references/craft-floor.md +7 -0
- package/dist/agent-src/skills/fe-design/references/design-patterns.md +47 -2
- package/dist/agent-src/skills/feature-planning/SKILL.md +34 -0
- package/dist/agent-src/skills/git-workflow/SKILL.md +37 -12
- package/dist/agent-src/skills/git-workflow/references/push-closes-its-loop.md +176 -0
- package/dist/agent-src/skills/laravel-mail/SKILL.md +44 -0
- package/dist/agent-src/skills/laravel-scheduling/SKILL.md +3 -1
- package/dist/agent-src/skills/project-analyzer/SKILL.md +0 -6
- package/dist/agent-src/skills/react-native-setup/SKILL.md +3 -3
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
- package/dist/agent-src/skills/sequential-thinking/SKILL.md +18 -8
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +40 -0
- package/dist/agent-src/skills/ui-apply-generic/SKILL.md +1 -1
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +1 -1
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +29 -2
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +53 -8
- package/dist/agent-src/skills/worktree-lifecycle/SKILL.md +3 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli/commands/recordTriggerEval.js +2 -2
- package/dist/cli/main.js +1 -1
- package/dist/cli-delegate/{chunk-AKJGUQNO.js → chunk-GZTMRYCN.js} +405 -341
- package/dist/cli-delegate/{chunk-7RXIKF62.js → chunk-IDHUQIXP.js} +283 -132
- package/dist/cli-delegate/cmd_adr_effective.js +318 -81
- package/dist/cli-delegate/cmd_conformance.js +749 -669
- package/dist/cli-delegate/cmd_doctor.js +1 -1
- package/dist/cli-delegate/cmd_export.js +1 -1
- package/dist/cli-delegate/cmd_handoff.js +1 -1
- package/dist/cli-delegate/cmd_prune.js +1 -1
- package/dist/cli-delegate/cmd_route_audit.js +1 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +1 -1
- package/dist/cli-delegate/cmd_uninstall.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +39 -38
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +2764 -2439
- package/dist/install/install.mjs +588 -527
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1381 -1138
- package/dist/scripts/_lib/model_tier.js +1 -1
- package/dist/shared/settingsConsent.js +1 -1
- package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +1 -1
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
- package/docs/guidelines/design-antipatterns.md +87 -64
- package/package.json +1 -1
- package/src/agent-src/README.md +1 -1
- package/src/config/ci-local-parity.yml +6 -0
- package/src/config/conformance-claim-baseline.json +9 -0
- package/src/config/gate-coverage.yml +170 -0
- package/src/config/gate-violation-baselines.json +4 -4
- package/src/config/release-gate-locality.yml +141 -0
- package/src/scripts/_cli/cmd_doctor.ts +2 -2
- package/src/scripts/_cli/cmd_handoff.ts +1 -1
- package/src/scripts/_cli/cmd_update.ts +1 -1
- package/src/scripts/_cli/cmd_versions.ts +1 -1
- package/src/scripts/_lib/adr_frontmatter.ts +44 -0
- package/src/scripts/_lib/consequence_objects.ts +152 -0
- package/src/scripts/_lib/exec_evidence.ts +7 -0
- package/src/scripts/_lib/global_deploy_inventory.ts +2 -2
- package/src/scripts/_lib/host_permission_checks.ts +251 -0
- package/src/scripts/_lib/model_tier.ts +1 -1
- package/src/scripts/_lib/obligation_frequency.ts +2 -2
- package/src/scripts/_lib/release_highlights.ts +265 -1
- package/src/scripts/_lib/release_material.ts +129 -0
- package/src/scripts/_lib/repeated_run.ts +77 -0
- package/src/scripts/_lib/runtime_journal.ts +26 -3
- package/src/scripts/_lib/runtime_wiring_checks.ts +12 -1
- package/src/scripts/_lib/session_register.ts +11 -6
- package/src/scripts/_lib/sqlite_schema.ts +22 -0
- package/src/scripts/_lib/surface.ts +86 -0
- package/src/scripts/_lib/tamper_vocabulary.ts +242 -0
- package/src/scripts/_lib/ui_authority.ts +116 -0
- package/src/scripts/_lib/unified_diff.ts +121 -0
- package/src/scripts/adr/regenerate_index.ts +54 -1
- package/src/scripts/adr_cite_check.ts +71 -15
- package/src/scripts/ai_council/clients.ts +1 -1
- package/src/scripts/autonomy_friction_corpus.ts +229 -0
- package/src/scripts/build_proof.ts +15 -2
- package/src/scripts/check_beta_review_markers.ts +141 -17
- package/src/scripts/check_enforcement_coverage.ts +1 -1
- package/src/scripts/check_enforcement_denominator.ts +121 -11
- package/src/scripts/check_finding_dispositions.ts +239 -6
- package/src/scripts/check_gate_coverage.ts +96 -0
- package/src/scripts/check_installed_hooks_fresh.ts +381 -0
- package/src/scripts/check_release_highlights.ts +99 -14
- package/src/scripts/check_skill_activation_claim.ts +179 -0
- package/src/scripts/check_suppression_hygiene.ts +11 -0
- package/src/scripts/check_trigger_evals.ts +1 -1
- package/src/scripts/code_graph/build.ts +230 -33
- package/src/scripts/code_graph/extract.ts +168 -33
- package/src/scripts/code_graph/types.ts +37 -2
- package/src/scripts/code_graph/validate.ts +12 -1
- package/src/scripts/conformance_scan.ts +45 -4
- package/src/scripts/detect_silent_catch.ts +403 -0
- package/src/scripts/detect_verification_tampering.ts +538 -0
- package/src/scripts/explain_run.ts +1 -1
- package/src/scripts/generate_capability_matrix.ts +1 -1
- package/src/scripts/git_authorization_hook.ts +228 -18
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +47 -30
- package/src/scripts/hooks/augment-dispatcher.sh +1 -1
- package/src/scripts/hooks/block_no_verify.ts +3 -3
- package/src/scripts/hooks/category_a.ts +291 -0
- package/src/scripts/hooks/cline-dispatcher.sh +1 -1
- package/src/scripts/hooks/concern_registry.ts +2 -2
- package/src/scripts/hooks/cursor-dispatcher.sh +11 -5
- package/src/scripts/hooks/dispatch_hook.ts +17 -22
- package/src/scripts/hooks/evidence_independence.ts +21 -2
- package/src/scripts/hooks/{block_unauthorized_git.ts → git_command_classifier.ts} +175 -364
- package/src/scripts/hooks/host_lowering.ts +215 -0
- package/src/scripts/hooks/host_lowering.yaml +185 -0
- package/src/scripts/hooks/host_semantics.ts +105 -37
- package/src/scripts/hooks/journal_record_hook.ts +10 -0
- package/src/scripts/hooks/permission_gate.ts +117 -0
- package/src/scripts/hooks/push_settle_hook.ts +250 -0
- package/src/scripts/hooks/ship_diff_volume_hook.ts +1 -1
- package/src/scripts/hooks_status.ts +12 -10
- package/src/scripts/install-hooks.sh +134 -1
- package/src/scripts/install.ts +53 -82
- package/src/scripts/install_anthropic_key.sh +2 -2
- package/src/scripts/language_mirror_hook.ts +27 -5
- package/src/scripts/lint_design_antipattern_parity.ts +80 -0
- package/src/scripts/lint_evidence_artifacts.ts +45 -1
- package/src/scripts/lint_hook_manifest.ts +87 -3
- package/src/scripts/lint_motion_authority_drift.ts +731 -0
- package/src/scripts/lint_readme_size.ts +158 -12
- package/src/scripts/lint_reasoning_fixtures.ts +216 -0
- package/src/scripts/lint_skill_trigger_contradiction.ts +161 -0
- package/src/scripts/measure_sibling_naming.ts +150 -0
- package/src/scripts/redact_hook_capture.ts +1 -1
- package/src/scripts/release.ts +31 -143
- package/src/scripts/release_drill.ts +71 -1
- package/src/scripts/release_publication.ts +243 -3
- package/src/scripts/release_verify.ts +220 -0
- package/src/scripts/report_skill_activation.ts +319 -7
- package/src/scripts/schemas/review-findings.schema.json +6 -1
- package/src/scripts/schemas/skill.schema.json +12 -2
- package/src/scripts/self_review_gate.ts +10 -1
- package/src/scripts/session_canary_hook.ts +1 -1
- package/src/scripts/session_register_hook.ts +4 -3
- package/src/scripts/trigger_eval_grandfather.json +5 -1
- package/src/scripts/validate_agent_settings.ts +1 -1
- package/src/shared/settingsConsent.ts +1 -1
|
@@ -36,6 +36,37 @@ export interface RawEdge {
|
|
|
36
36
|
enclosingClassId?: string;
|
|
37
37
|
/** scope token for `Scope::m()` scoped calls (a class name / self / static). */
|
|
38
38
|
scopeName?: string;
|
|
39
|
+
/**
|
|
40
|
+
* `imports` only: the module specifier as written (`'./types.js'`,
|
|
41
|
+
* `'node:path'`), stripped of its quotes.
|
|
42
|
+
*
|
|
43
|
+
* Before this field the extractor read the import CLAUSE and threw the
|
|
44
|
+
* `from` away, so the build pass had nothing to resolve against but a
|
|
45
|
+
* repo-wide same-name table — which is how `import * as path from
|
|
46
|
+
* 'node:path'` came to bind to this repository's own `path()` function in
|
|
47
|
+
* `query.ts`, at `EXTRACTED`, in four of eleven files. The specifier is the
|
|
48
|
+
* one piece of evidence that says WHERE the name came from, and it is in
|
|
49
|
+
* the source text; discarding it turned a syntactic fact into a guess.
|
|
50
|
+
*
|
|
51
|
+
* Absent for PHP `use`, which names a fully-qualified symbol rather than a
|
|
52
|
+
* module path — those still resolve by name, and the build pass labels them
|
|
53
|
+
* accordingly.
|
|
54
|
+
*/
|
|
55
|
+
moduleSpecifier?: string;
|
|
56
|
+
/**
|
|
57
|
+
* `imports` only: which import form produced this binding. `namespace`
|
|
58
|
+
* (`import * as x`) and `default` bind the MODULE (or its default export),
|
|
59
|
+
* never a named export, so neither may be matched against a same-named
|
|
60
|
+
* symbol inside the target file.
|
|
61
|
+
*/
|
|
62
|
+
importKind?: 'namespace' | 'named' | 'default';
|
|
63
|
+
/**
|
|
64
|
+
* `imports` only: the LOCAL binding name, when it differs from
|
|
65
|
+
* `targetName` (`import { foo as bar }` → targetName `foo`, localName
|
|
66
|
+
* `bar`). The file's scope is keyed on the local name; the target file is
|
|
67
|
+
* searched for the remote one.
|
|
68
|
+
*/
|
|
69
|
+
localName?: string;
|
|
39
70
|
}
|
|
40
71
|
|
|
41
72
|
export interface FileExtract {
|
|
@@ -245,29 +276,101 @@ function extractPhp(root: TsNode, file: string, out: FileExtract): void {
|
|
|
245
276
|
|
|
246
277
|
// ── TypeScript / JavaScript ───────────────────────────────────────────────────
|
|
247
278
|
|
|
279
|
+
/**
|
|
280
|
+
* Node types that open a new function or class scope. A `const` inside one of
|
|
281
|
+
* these is a LOCAL variable, not a module-level declaration, and emitting a
|
|
282
|
+
* node for it would put every loop counter in the symbol table — the
|
|
283
|
+
* count-inflation failure `2.1` is explicitly not allowed to cause.
|
|
284
|
+
*/
|
|
285
|
+
const TS_SCOPE_INTRODUCERS = new Set([
|
|
286
|
+
'arrow_function',
|
|
287
|
+
'function_expression',
|
|
288
|
+
'function_declaration',
|
|
289
|
+
'generator_function',
|
|
290
|
+
'generator_function_declaration',
|
|
291
|
+
'method_definition',
|
|
292
|
+
'class_declaration',
|
|
293
|
+
'class',
|
|
294
|
+
'class_body',
|
|
295
|
+
]);
|
|
296
|
+
|
|
248
297
|
function extractTsJs(root: TsNode, file: string, out: FileExtract): void {
|
|
249
298
|
const fileId = file;
|
|
250
299
|
|
|
251
|
-
const walk = (n: TsNode, classId: string | null, scopeId: string): void => {
|
|
300
|
+
const walk = (n: TsNode, classId: string | null, scopeId: string, topLevel: boolean): void => {
|
|
301
|
+
// A declaration is module-level until the walk descends through a
|
|
302
|
+
// function or class scope; from there down it is a local.
|
|
303
|
+
const inner = topLevel && !TS_SCOPE_INTRODUCERS.has(n.type);
|
|
252
304
|
switch (n.type) {
|
|
253
305
|
case 'import_statement': {
|
|
306
|
+
const src = n.childForFieldName('source');
|
|
307
|
+
// The specifier node is a `string`; its text carries the quotes.
|
|
308
|
+
const specifier = src ? src.text.replace(/^['"`]/, '').replace(/['"`]$/, '') : undefined;
|
|
254
309
|
const clause = firstNamed(n, new Set(['import_clause']));
|
|
310
|
+
const emitImport = (
|
|
311
|
+
remote: string,
|
|
312
|
+
local: string,
|
|
313
|
+
importKind: 'namespace' | 'named' | 'default',
|
|
314
|
+
): void => {
|
|
315
|
+
out.rawEdges.push({
|
|
316
|
+
sourceId: fileId,
|
|
317
|
+
relation: 'imports',
|
|
318
|
+
targetName: baseName(remote),
|
|
319
|
+
confidenceHint: 'EXTRACTED',
|
|
320
|
+
...(specifier === undefined ? {} : { moduleSpecifier: specifier }),
|
|
321
|
+
importKind,
|
|
322
|
+
...(local === remote ? {} : { localName: local }),
|
|
323
|
+
});
|
|
324
|
+
};
|
|
255
325
|
if (clause) {
|
|
256
|
-
for (const
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
326
|
+
for (const child of namedChildren(clause)) {
|
|
327
|
+
if (child.type === 'namespace_import') {
|
|
328
|
+
// `import * as path from 'node:path'` — the binding
|
|
329
|
+
// is the MODULE. Matching `path` against a local
|
|
330
|
+
// symbol of the same name is the false edge 1.1
|
|
331
|
+
// exists to remove.
|
|
332
|
+
const idn = firstNamed(child, new Set(['identifier']));
|
|
333
|
+
if (idn) emitImport(idn.text, idn.text, 'namespace');
|
|
334
|
+
} else if (child.type === 'named_imports') {
|
|
335
|
+
for (const sp of namedChildren(child)) {
|
|
336
|
+
if (sp.type !== 'import_specifier') continue;
|
|
337
|
+
const nameNode = sp.childForFieldName('name');
|
|
338
|
+
const aliasNode = sp.childForFieldName('alias');
|
|
339
|
+
const remote = nameNode ? nameNode.text : sp.text;
|
|
340
|
+
emitImport(remote, aliasNode ? aliasNode.text : remote, 'named');
|
|
266
341
|
}
|
|
342
|
+
} else if (child.type === 'identifier') {
|
|
343
|
+
emitImport(child.text, child.text, 'default');
|
|
344
|
+
}
|
|
267
345
|
}
|
|
268
346
|
}
|
|
269
347
|
return;
|
|
270
348
|
}
|
|
349
|
+
// `const`, `type`, `interface`, `enum` — the shapes the v2 corpus
|
|
350
|
+
// asks `references` questions about (`EXT_LANG` is a const,
|
|
351
|
+
// `SettingsClass` a type alias). The extractor used to emit none of
|
|
352
|
+
// them, which is the named mechanical cause of `references` recall
|
|
353
|
+
// 0.333 against grep's 1.000.
|
|
354
|
+
//
|
|
355
|
+
// The body is not walked: a type or interface position holds no
|
|
356
|
+
// call sites, and an enum body holds member names rather than
|
|
357
|
+
// symbols this graph answers questions about.
|
|
358
|
+
case 'interface_declaration':
|
|
359
|
+
case 'type_alias_declaration':
|
|
360
|
+
case 'enum_declaration': {
|
|
361
|
+
const nmNode = n.childForFieldName('name') ?? firstNamed(n, NAME_TYPES);
|
|
362
|
+
const nm = nmNode ? nmNode.text : '<anon>';
|
|
363
|
+
const kind =
|
|
364
|
+
n.type === 'interface_declaration'
|
|
365
|
+
? 'interface'
|
|
366
|
+
: n.type === 'type_alias_declaration'
|
|
367
|
+
? 'type'
|
|
368
|
+
: 'enum';
|
|
369
|
+
const id = `${file}#${nm}`;
|
|
370
|
+
out.nodes.push({ id, label: nm, kind, source_file: file, source_location: loc(n) });
|
|
371
|
+
out.rawEdges.push({ sourceId: fileId, relation: 'member', targetName: nm, confidenceHint: 'EXTRACTED' });
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
271
374
|
case 'class_declaration': {
|
|
272
375
|
const nm = nameField(n) ?? '<anon>';
|
|
273
376
|
const id = `${file}#${nm}`;
|
|
@@ -280,7 +383,7 @@ function extractTsJs(root: TsNode, file: string, out: FileExtract): void {
|
|
|
280
383
|
if (idn.type === 'identifier' || idn.type === 'type_identifier')
|
|
281
384
|
out.inherits.push({ classId: id, parentName: baseName(idn.text) });
|
|
282
385
|
const body = n.childForFieldName('body');
|
|
283
|
-
if (body) for (const c of namedChildren(body)) walk(c, id, id);
|
|
386
|
+
if (body) for (const c of namedChildren(body)) walk(c, id, id, false);
|
|
284
387
|
return;
|
|
285
388
|
}
|
|
286
389
|
case 'method_definition': {
|
|
@@ -294,7 +397,7 @@ function extractTsJs(root: TsNode, file: string, out: FileExtract): void {
|
|
|
294
397
|
confidenceHint: 'EXTRACTED',
|
|
295
398
|
});
|
|
296
399
|
const body = n.childForFieldName('body');
|
|
297
|
-
if (body) for (const c of namedChildren(body)) walk(c, classId, id);
|
|
400
|
+
if (body) for (const c of namedChildren(body)) walk(c, classId, id, false);
|
|
298
401
|
return;
|
|
299
402
|
}
|
|
300
403
|
case 'function_declaration': {
|
|
@@ -303,7 +406,7 @@ function extractTsJs(root: TsNode, file: string, out: FileExtract): void {
|
|
|
303
406
|
out.nodes.push({ id, label: nm, kind: 'function', source_file: file, source_location: loc(n) });
|
|
304
407
|
out.rawEdges.push({ sourceId: fileId, relation: 'member', targetName: nm, confidenceHint: 'EXTRACTED' });
|
|
305
408
|
const body = n.childForFieldName('body');
|
|
306
|
-
if (body) for (const c of namedChildren(body)) walk(c, classId, id);
|
|
409
|
+
if (body) for (const c of namedChildren(body)) walk(c, classId, id, false);
|
|
307
410
|
return;
|
|
308
411
|
}
|
|
309
412
|
// Modern TS declares most of its functions as bindings, not as
|
|
@@ -313,17 +416,58 @@ function extractTsJs(root: TsNode, file: string, out: FileExtract): void {
|
|
|
313
416
|
// 170-vs-13,428 TS/PHP symbol gap: the six handled kinds simply do
|
|
314
417
|
// not cover the dominant declaration form.
|
|
315
418
|
//
|
|
316
|
-
//
|
|
317
|
-
//
|
|
318
|
-
//
|
|
319
|
-
//
|
|
320
|
-
//
|
|
419
|
+
// The scoping note that stood here said a `const x = 3` is "data,
|
|
420
|
+
// not a symbol this graph answers questions about", and that
|
|
421
|
+
// emitting a node per constant would raise the count without
|
|
422
|
+
// improving recall. **The v2 benchmark falsified the first half and
|
|
423
|
+
// the second half no longer follows.** Two of its three
|
|
424
|
+
// `references` questions probe exactly this shape — `EXT_LANG` (a
|
|
425
|
+
// const) and `SettingsClass` (a type alias) — and the class scored
|
|
426
|
+
// recall 0.333 against grep's 1.000 because neither had a node to
|
|
427
|
+
// resolve to. The count-inflation worry was real and is answered by
|
|
428
|
+
// SCOPE rather than by refusal: a binding earns a node only at
|
|
429
|
+
// MODULE level (`topLevel`), so a loop counter inside a function
|
|
430
|
+
// body still gets none. The reason is kept rather than deleted,
|
|
431
|
+
// because a reversed decision whose reason disappears gets re-taken.
|
|
321
432
|
case 'lexical_declaration':
|
|
322
433
|
case 'variable_declaration': {
|
|
323
434
|
for (const d of namedChildren(n)) {
|
|
324
435
|
if (d.type !== 'variable_declarator') continue;
|
|
325
436
|
const value = d.childForFieldName('value');
|
|
326
|
-
|
|
437
|
+
const nmNode = d.childForFieldName('name');
|
|
438
|
+
const isFn =
|
|
439
|
+
value !== null &&
|
|
440
|
+
value !== undefined &&
|
|
441
|
+
(value.type === 'arrow_function' || value.type === 'function_expression');
|
|
442
|
+
const isClassExpr = value?.type === 'class';
|
|
443
|
+
if (!isFn) {
|
|
444
|
+
// Only a plain `identifier` name: a destructuring
|
|
445
|
+
// pattern (`const { a, b } = x`) binds several names and
|
|
446
|
+
// none of them is a declaration this graph can id.
|
|
447
|
+
if (topLevel && nmNode?.type === 'identifier') {
|
|
448
|
+
const nm = nmNode.text;
|
|
449
|
+
const id = classId ? `${classId}::${nm}` : `${file}#${nm}`;
|
|
450
|
+
out.nodes.push({
|
|
451
|
+
id,
|
|
452
|
+
label: nm,
|
|
453
|
+
// `const Widget = class {}` IS constructible;
|
|
454
|
+
// calling it a constant would let the build pass
|
|
455
|
+
// reject a `new Widget()` that is perfectly real.
|
|
456
|
+
kind: isClassExpr ? 'class' : 'constant',
|
|
457
|
+
source_file: file,
|
|
458
|
+
source_location: loc(d),
|
|
459
|
+
});
|
|
460
|
+
out.rawEdges.push({
|
|
461
|
+
sourceId: classId ?? fileId,
|
|
462
|
+
relation: 'member',
|
|
463
|
+
targetName: nm,
|
|
464
|
+
confidenceHint: 'EXTRACTED',
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
// Non-function declarators still need walking for their
|
|
468
|
+
// calls — returning early on the whole declaration
|
|
469
|
+
// silently drops call edges from initialisers.
|
|
470
|
+
walk(d, classId, scopeId, inner);
|
|
327
471
|
continue;
|
|
328
472
|
}
|
|
329
473
|
const nm = nameField(d) ?? '<anon>';
|
|
@@ -353,16 +497,7 @@ function extractTsJs(root: TsNode, file: string, out: FileExtract): void {
|
|
|
353
497
|
// can iterate children because a `statement_block` is never
|
|
354
498
|
// the interesting node; here it often is.
|
|
355
499
|
const body = value.childForFieldName('body');
|
|
356
|
-
if (body) walk(body, classId, id);
|
|
357
|
-
}
|
|
358
|
-
// Non-function declarators still need walking for their calls.
|
|
359
|
-
for (const d of namedChildren(n)) {
|
|
360
|
-
if (d.type !== 'variable_declarator') continue;
|
|
361
|
-
const value = d.childForFieldName('value');
|
|
362
|
-
if (value && (value.type === 'arrow_function' || value.type === 'function_expression')) {
|
|
363
|
-
continue;
|
|
364
|
-
}
|
|
365
|
-
walk(d, classId, scopeId);
|
|
500
|
+
if (body) walk(body, classId, id, false);
|
|
366
501
|
}
|
|
367
502
|
return;
|
|
368
503
|
}
|
|
@@ -388,7 +523,7 @@ function extractTsJs(root: TsNode, file: string, out: FileExtract): void {
|
|
|
388
523
|
confidenceHint: 'EXTRACTED',
|
|
389
524
|
});
|
|
390
525
|
const body = value.childForFieldName('body');
|
|
391
|
-
if (body) walk(body, classId, id);
|
|
526
|
+
if (body) walk(body, classId, id, false);
|
|
392
527
|
return;
|
|
393
528
|
}
|
|
394
529
|
break;
|
|
@@ -481,11 +616,11 @@ function extractTsJs(root: TsNode, file: string, out: FileExtract): void {
|
|
|
481
616
|
default:
|
|
482
617
|
break;
|
|
483
618
|
}
|
|
484
|
-
for (const c of namedChildren(n)) walk(c, classId, scopeId);
|
|
619
|
+
for (const c of namedChildren(n)) walk(c, classId, scopeId, inner);
|
|
485
620
|
};
|
|
486
621
|
|
|
487
622
|
out.nodes.push({ id: fileId, label: file, kind: 'file', source_file: file, source_location: [] });
|
|
488
|
-
walk(root, null, fileId);
|
|
623
|
+
walk(root, null, fileId, true);
|
|
489
624
|
}
|
|
490
625
|
|
|
491
626
|
/**
|
|
@@ -21,7 +21,20 @@ export interface CodeNode {
|
|
|
21
21
|
/** Path-qualified from day one: `<relpath>#<symbol>` (collision-free). */
|
|
22
22
|
id: string;
|
|
23
23
|
label: string;
|
|
24
|
-
|
|
24
|
+
/**
|
|
25
|
+
* `constant` / `type` / `enum` were added by
|
|
26
|
+
* `road-to-the-graph-that-lies-confidently` 2.1: the v2 benchmark's
|
|
27
|
+
* `references` class probes a const (`EXT_LANG`) and a type alias
|
|
28
|
+
* (`SettingsClass`), and neither had a node to resolve to. `interface` is
|
|
29
|
+
* reused rather than forked — a TS interface and a PHP interface are the
|
|
30
|
+
* same thing to a caller.
|
|
31
|
+
*
|
|
32
|
+
* The kind is also a CAPABILITY claim the build pass reads: a `constant` is
|
|
33
|
+
* never callable and never constructible, so a bare `foo()` may not resolve
|
|
34
|
+
* to one by name. `const Widget = class {}` is emitted as `class` for
|
|
35
|
+
* exactly that reason.
|
|
36
|
+
*/
|
|
37
|
+
kind: 'file' | 'class' | 'interface' | 'trait' | 'function' | 'method' | 'constant' | 'type' | 'enum' | 'skipped';
|
|
25
38
|
source_file: string;
|
|
26
39
|
/** 1-based [startLine, startCol, endLine, endCol]; [] for synthetic nodes. */
|
|
27
40
|
source_location: readonly number[];
|
|
@@ -74,11 +87,33 @@ export interface CodeGraph {
|
|
|
74
87
|
grammar_abi: number;
|
|
75
88
|
/** per-confidence-class edge counts, so the honesty split is visible. */
|
|
76
89
|
edge_confidence_counts: Record<EdgeConfidence, number>;
|
|
90
|
+
/**
|
|
91
|
+
* Edges the build pass REFUSED to emit, by reason. Present so a smaller
|
|
92
|
+
* edge total cannot be read as a better graph without saying what was
|
|
93
|
+
* dropped: an engine that quietly deletes its worst edges publishes a
|
|
94
|
+
* flattering confidence ratio and no evidence.
|
|
95
|
+
*
|
|
96
|
+
* `dynamic_no_candidate` — a dynamic member call (`x.push()`) whose method
|
|
97
|
+
* name matches NO method declared in this repository. The edge could only
|
|
98
|
+
* ever have pointed at a `symbol:` pseudo-node, which is not a node, so no
|
|
99
|
+
* query verb could reach it: `affected` and `path` resolve their seeds
|
|
100
|
+
* against real nodes. It was 257 of 660 edges on this engine's own source.
|
|
101
|
+
*/
|
|
102
|
+
suppressed_edge_counts: { dynamic_no_candidate: number };
|
|
77
103
|
nodes: CodeNode[];
|
|
78
104
|
edges: CodeEdge[];
|
|
79
105
|
}
|
|
80
106
|
|
|
81
|
-
|
|
107
|
+
/**
|
|
108
|
+
* Bumped 1 → 2 by `road-to-the-graph-that-lies-confidently`: `CodeNode.kind`
|
|
109
|
+
* gained three members, `CodeGraph` gained `suppressed_edge_counts`, and the
|
|
110
|
+
* per-file extract sidecar gained the import specifier. A cached sidecar
|
|
111
|
+
* written at v1 carries raw edges with no `moduleSpecifier`, which would make
|
|
112
|
+
* `--update` resolve imports the old (name-lookup) way for every unchanged
|
|
113
|
+
* file — a silently mixed graph. `readSidecar` refuses a version mismatch, so
|
|
114
|
+
* the bump is what makes that impossible rather than merely unlikely.
|
|
115
|
+
*/
|
|
116
|
+
export const SCHEMA_VERSION = 2;
|
|
82
117
|
|
|
83
118
|
/** Deterministic per-file byte cap — files above this become a SKIPPED node. */
|
|
84
119
|
export const MAX_FILE_BYTES = 1_000_000;
|
|
@@ -6,7 +6,18 @@ import type { CodeGraph } from './types.js';
|
|
|
6
6
|
|
|
7
7
|
const RELATIONS = new Set(['calls', 'imports', 'uses', 'inherits', 'member']);
|
|
8
8
|
const CONFIDENCES = new Set(['EXTRACTED', 'INFERRED', 'AMBIGUOUS']);
|
|
9
|
-
const KINDS = new Set([
|
|
9
|
+
const KINDS = new Set([
|
|
10
|
+
'file',
|
|
11
|
+
'class',
|
|
12
|
+
'interface',
|
|
13
|
+
'trait',
|
|
14
|
+
'function',
|
|
15
|
+
'method',
|
|
16
|
+
'constant',
|
|
17
|
+
'type',
|
|
18
|
+
'enum',
|
|
19
|
+
'skipped',
|
|
20
|
+
]);
|
|
10
21
|
|
|
11
22
|
export interface ValidateResult {
|
|
12
23
|
ok: boolean;
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*
|
|
14
14
|
* language-pin ← language_mirror_hook.classify
|
|
15
15
|
* git-authorization ← git_authorization_hook.classifyAuthorization
|
|
16
|
-
* +
|
|
16
|
+
* + git_command_classifier.commandOp / BLOCK_OPS
|
|
17
17
|
* vacuous-evidence ← before_complete_hook.isVacuousOutput / isCiPoll / pendingCount
|
|
18
18
|
* evidence-steering ← evidence_independence.isEvaluationPrompt / preloadedVerdict
|
|
19
19
|
* completion-claim ← turn_end_gate_hook.detectCompletionClaim (round 7)
|
|
@@ -53,8 +53,13 @@ import { entryText, isSidechain } from "./_lib/transcript_entry.js";
|
|
|
53
53
|
|
|
54
54
|
import { classify } from "./language_mirror_hook.js";
|
|
55
55
|
import { isSyntheticPrompt } from "./_lib/prompt_shape.js";
|
|
56
|
-
import {
|
|
57
|
-
|
|
56
|
+
import {
|
|
57
|
+
classifyAuthorization,
|
|
58
|
+
extractObjects,
|
|
59
|
+
OBJECT_REQUIRED_OPS,
|
|
60
|
+
type GitOp,
|
|
61
|
+
} from "./git_authorization_hook.js";
|
|
62
|
+
import { BLOCK_OPS, commandObject, commandOp } from "./hooks/git_command_classifier.js";
|
|
58
63
|
import { isVacuousOutput, isCiPoll, pendingCount } from "./before_complete_hook.js";
|
|
59
64
|
// Round 7 § 1.5 — the SAME predicate `turn-end-gate` refuses on, imported rather
|
|
60
65
|
// than reimplemented, so the measured rate and the gate cannot disagree.
|
|
@@ -579,6 +584,8 @@ export function scanSession(sessionId: string, lines: string[]): SessionReport {
|
|
|
579
584
|
let pinned: "de" | "en" | null = null;
|
|
580
585
|
let pendingPoll: { at: string; cmd: string } | null = null;
|
|
581
586
|
let authorized = new Set<GitOp>();
|
|
587
|
+
// Per-op objects the current turn's prompt named. Reset with `authorized`.
|
|
588
|
+
let authorizedObjects = new Map<GitOp, Set<string>>();
|
|
582
589
|
let sawPending = false;
|
|
583
590
|
let evaluationsThisTurn = 0;
|
|
584
591
|
// Round-5 provenance for language violations. The round-5 audit could only
|
|
@@ -723,7 +730,15 @@ export function scanSession(sessionId: string, lines: string[]): SessionReport {
|
|
|
723
730
|
if (c.language !== "und") {
|
|
724
731
|
pinned = c.language;
|
|
725
732
|
}
|
|
726
|
-
|
|
733
|
+
const classified = classifyAuthorization(ut);
|
|
734
|
+
authorized = new Set(classified.authorized);
|
|
735
|
+
// Step 2.2 — the objects the turn NAMED, per operation. Rebuilt on every
|
|
736
|
+
// counted user turn for the same reason `authorized` is: an authorization
|
|
737
|
+
// for one table does not carry into the next prompt any more than the
|
|
738
|
+
// operation does.
|
|
739
|
+
authorizedObjects = new Map(
|
|
740
|
+
classified.authorized.map((op) => [op, new Set(extractObjects(op, ut))]),
|
|
741
|
+
);
|
|
727
742
|
sawPending = false;
|
|
728
743
|
evaluationsThisTurn = 0;
|
|
729
744
|
pendingPoll = null;
|
|
@@ -811,6 +826,32 @@ export function scanSession(sessionId: string, lines: string[]): SessionReport {
|
|
|
811
826
|
at,
|
|
812
827
|
detail: `irreversible \`${op}\` with no authorization in the turn's prompt: ${cmd.slice(0, 110)}`,
|
|
813
828
|
});
|
|
829
|
+
} else if (op !== null && authorized.has(op) && OBJECT_REQUIRED_OPS.has(op)) {
|
|
830
|
+
// Step 2.2 — the operation WAS authorized and ran against something
|
|
831
|
+
// the turn never named. An authorization for one table is not an
|
|
832
|
+
// authorization for another, and until the ledger could carry an
|
|
833
|
+
// object this was indistinguishable from a clean turn.
|
|
834
|
+
//
|
|
835
|
+
// This REPORTS and refuses nothing — ADR-254 removed the enforcing
|
|
836
|
+
// reader, and the shape it preserved is a count after the fact.
|
|
837
|
+
//
|
|
838
|
+
// A command naming NO object produces no finding: `commandObject`
|
|
839
|
+
// returns null there, and a guessed object would manufacture a
|
|
840
|
+
// violation out of a parse failure. Under-reporting is the safe
|
|
841
|
+
// direction for a measurement.
|
|
842
|
+
const object = commandObject(op, cmd);
|
|
843
|
+
const named = authorizedObjects.get(op);
|
|
844
|
+
if (object !== null && !(named?.has(object) ?? false)) {
|
|
845
|
+
report.violations.push({
|
|
846
|
+
check: "git-authorization",
|
|
847
|
+
session: sessionId,
|
|
848
|
+
at,
|
|
849
|
+
detail:
|
|
850
|
+
`\`${op}\` authorized, but its object \`${object}\` is not one the ` +
|
|
851
|
+
`turn's prompt named (${named && named.size > 0 ? [...named].join(", ") : "no object named"}): ` +
|
|
852
|
+
cmd.slice(0, 110),
|
|
853
|
+
});
|
|
854
|
+
}
|
|
814
855
|
}
|
|
815
856
|
if (isCiPoll(cmd)) {
|
|
816
857
|
// The RESULT of this call arrives on the NEXT entry, and that entry is
|