@event4u/agent-config 14.13.0 → 14.14.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/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +138 -376
- package/README.md +1 -1
- package/dist/agent-src/commands/analyze/inbox.md +36 -0
- package/dist/agent-src/commands/pr/create.md +16 -1
- package/dist/agent-src/contexts/execution/terminal-states.md +25 -4
- package/dist/agent-src/rules/code-comment-discipline.md +6 -0
- package/dist/agent-src/rules/missing-skill-recovery.md +2 -2
- package/dist/agent-src/rules/token-budget-discipline.md +2 -2
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +6 -6
- package/dist/agent-src/scripts/guarded_baseline.ts +22 -7
- package/dist/agent-src/scripts/stubs_due.ts +118 -2
- package/dist/agent-src/scripts/update_roadmap_progress.ts +8 -8
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli/registry.js +1 -0
- package/dist/cli-delegate/{chunk-ILMUPLGW.js → chunk-7RXIKF62.js} +159 -86
- package/dist/cli-delegate/cmd_conformance.js +39 -2
- package/dist/cli-delegate/cmd_doctor.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +7 -7
- 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 +1696 -812
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +297 -115
- package/docs/guidelines/agent-infra/guarded-baseline.md +1 -1
- package/docs/guidelines/code-clarity.md +18 -0
- package/package.json +1 -1
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +6 -6
- package/src/agent-src/scripts/guarded_baseline.ts +22 -7
- package/src/agent-src/scripts/stubs_due.ts +118 -2
- package/src/agent-src/scripts/update_roadmap_progress.ts +8 -8
- package/src/config/assurance-capability-registry.json +1 -1
- package/src/config/estate-count-budget.json +20 -1
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +211 -1
- package/src/config/gate-reachability-exemptions.json +1 -0
- package/src/config/gate-violation-baselines.json +9 -3
- package/src/config/preamble-payload-budget.json +19 -11
- package/src/config/rule-stub-ceilings.json +14 -7
- package/src/config/web-launch-readiness.json +4 -2
- package/src/scripts/_cli/_doctor_emit.ts +71 -0
- package/src/scripts/_cli/_doctor_strict.ts +163 -0
- package/src/scripts/_cli/cmd_doctor.ts +16 -37
- package/src/scripts/_dispatch.bash +11 -4
- package/src/scripts/_lib/activation_ladder.ts +47 -3
- package/src/scripts/_lib/activation_receipt_producer.ts +341 -0
- package/src/scripts/_lib/adr_frontmatter.ts +26 -0
- package/src/scripts/_lib/branch_convergence.ts +186 -0
- package/src/scripts/_lib/candidate_pair_delta.ts +349 -0
- package/src/scripts/_lib/carrier_status.ts +118 -0
- package/src/scripts/_lib/cascade_stage_enumeration.ts +92 -0
- package/src/scripts/_lib/context_observation.ts +132 -0
- package/src/scripts/_lib/continuation_ladder.ts +188 -0
- package/src/scripts/_lib/corpus_manifest.ts +726 -0
- package/src/scripts/_lib/delivery_arm_experiment.ts +18 -2
- package/src/scripts/_lib/estate_carrier_cases.ts +72 -0
- package/src/scripts/_lib/evaluation_cascade.ts +452 -0
- package/src/scripts/_lib/evolution_roi.ts +562 -0
- package/src/scripts/_lib/experiment_binding.ts +95 -0
- package/src/scripts/_lib/harness_evolution_guards.ts +10 -0
- package/src/scripts/_lib/ignored_blocker.ts +8 -1
- package/src/scripts/_lib/lexical_shortlist.ts +215 -0
- package/src/scripts/_lib/llm_candidate_proposer.ts +461 -0
- package/src/scripts/_lib/llm_proposer_transport.ts +153 -0
- package/src/scripts/_lib/outcome_envelope.ts +6 -1
- package/src/scripts/_lib/outcome_vocabularies.ts +135 -5
- package/src/scripts/_lib/pathology_archive.ts +393 -0
- package/src/scripts/_lib/promotion_capability.ts +315 -0
- package/src/scripts/_lib/promotion_evidence.ts +414 -0
- package/src/scripts/_lib/promotion_review.ts +294 -0
- package/src/scripts/_lib/prompt_shape.ts +92 -0
- package/src/scripts/_lib/release_highlights.ts +79 -1
- package/src/scripts/_lib/release_material.ts +125 -2
- package/src/scripts/_lib/repeated_failure.ts +19 -2
- package/src/scripts/_lib/routing_corpus.ts +307 -0
- package/src/scripts/_lib/routing_index_input.ts +104 -0
- package/src/scripts/_lib/rule_injection.ts +22 -1
- package/src/scripts/_lib/runtime_journal.ts +11 -4
- package/src/scripts/_lib/semantic_noop.ts +167 -0
- package/src/scripts/activation_receipt.ts +258 -0
- package/src/scripts/ai_council/cross_exam.ts +128 -0
- package/src/scripts/ai_council/explain_route.ts +157 -0
- package/src/scripts/ai_council/information_gain.ts +293 -0
- package/src/scripts/ai_council/leakage_corpus.ts +385 -0
- package/src/scripts/ai_council/leakage_patterns.ts +453 -0
- package/src/scripts/ai_council/minority_retention.ts +171 -0
- package/src/scripts/ai_council/recouncil_savings.ts +299 -0
- package/src/scripts/ai_council/replay_route.ts +223 -0
- package/src/scripts/ai_council/reviewer_assignment.ts +279 -0
- package/src/scripts/ai_council/routing_training_row.ts +197 -0
- package/src/scripts/ai_council/synthesis_strategy.ts +159 -0
- package/src/scripts/check_adr_frontmatter.ts +4 -9
- package/src/scripts/check_agent_artifact_location.ts +337 -0
- package/src/scripts/check_artefact_count_messaging.ts +74 -8
- package/src/scripts/check_enforcement_coverage.ts +40 -1
- package/src/scripts/check_estate_count.ts +205 -24
- package/src/scripts/check_release_highlights.ts +113 -14
- package/src/scripts/check_roadmap_trackable.ts +17 -2
- package/src/scripts/check_web_launch_readiness.ts +310 -20
- package/src/scripts/corpus_manifest.ts +235 -0
- package/src/scripts/evolution_lab.ts +234 -9
- package/src/scripts/generate_capability_matrix.ts +16 -9
- package/src/scripts/grade_target_readiness.ts +221 -2
- package/src/scripts/hook_effect_doctor.ts +47 -4
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +28 -6
- package/src/scripts/hooks/comment_discipline_hook.ts +146 -0
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/run_continuation_hook.ts +78 -88
- package/src/scripts/hooks/session_eol_hook.ts +12 -1
- package/src/scripts/hooks/turn_end_gate_hook.ts +9 -1
- package/src/scripts/install-hooks.sh +18 -0
- package/src/scripts/language_mirror_hook.ts +14 -2
- package/src/scripts/lint_carrier_integrity.ts +820 -0
- package/src/scripts/lint_code_comments.ts +748 -0
- package/src/scripts/lint_plan_risk_register.ts +39 -19
- package/src/scripts/lint_promotion_paths.ts +779 -0
- package/src/scripts/llm_propose.ts +256 -0
- package/src/scripts/measure_delivery_sets.ts +361 -0
- package/src/scripts/measure_routing_signal.ts +307 -0
- package/src/scripts/model_rule_injection.ts +19 -3
- package/src/scripts/probe_council_retention.ts +495 -0
- package/src/scripts/release.ts +21 -37
- package/src/scripts/release_drill.ts +199 -0
- package/src/scripts/release_env.ts +35 -0
- package/src/scripts/release_publication.ts +142 -0
- package/src/scripts/roadmap_context.ts +15 -0
- package/src/scripts/skill_scout.ts +633 -0
- package/src/scripts/sync_pr_branch.ts +521 -42
|
@@ -64,6 +64,13 @@
|
|
|
64
64
|
* inert mechanism that says nothing is
|
|
65
65
|
* indistinguishable from a healthy idle run,
|
|
66
66
|
* which is the failure this file exists over)
|
|
67
|
+
* plan premise moved → allow (event: halt-premise-invalidated, ONCE per
|
|
68
|
+
* run. Engaged-under fingerprint and newest
|
|
69
|
+
* observation both known and differing. Before the
|
|
70
|
+
* counter rungs: iterating against a stale plan
|
|
71
|
+
* does not make it current, and capping out would
|
|
72
|
+
* report `exhausted`, a budget word, for staleness.
|
|
73
|
+
* Never fires on traffic the run did not observe)
|
|
67
74
|
* quality-gate refusal → defer (event: deferred-quality-gate)
|
|
68
75
|
* duplicate stop fire → repeat the BLOCK, no count (event: none —
|
|
69
76
|
* an allow here would END the reply the block
|
|
@@ -173,8 +180,35 @@ import {
|
|
|
173
180
|
readUnavailableDependency,
|
|
174
181
|
stallSignal,
|
|
175
182
|
type StallLevel,
|
|
176
|
-
type UnavailableDependency,
|
|
177
183
|
} from '../_lib/loop_guards.js';
|
|
184
|
+
import { premiseMoved, readContextObservation } from '../_lib/context_observation.js';
|
|
185
|
+
import { RUN_TERMINAL_VOCABULARY_VERSION } from '../_lib/outcome_vocabularies.js';
|
|
186
|
+
import {
|
|
187
|
+
HALT_ACTIONS,
|
|
188
|
+
ladder,
|
|
189
|
+
MAX_ITERATIONS,
|
|
190
|
+
parseHaltStamp,
|
|
191
|
+
STALL_WINDOW,
|
|
192
|
+
terminalStateFor,
|
|
193
|
+
WALL_CLOCK_CAP_MS,
|
|
194
|
+
type LadderAction,
|
|
195
|
+
} from '../_lib/continuation_ladder.js';
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* DECLARED in `_lib/continuation_ladder.ts`, re-exported here: one declaration,
|
|
199
|
+
* two import paths, no second copy to drift. That module's header says why the
|
|
200
|
+
* move happened (`road-to-wired-instruments` Phase 2).
|
|
201
|
+
*/
|
|
202
|
+
export {
|
|
203
|
+
HALT_ACTIONS,
|
|
204
|
+
ladder,
|
|
205
|
+
MAX_ITERATIONS,
|
|
206
|
+
parseHaltStamp,
|
|
207
|
+
STALL_WINDOW,
|
|
208
|
+
terminalStateFor,
|
|
209
|
+
WALL_CLOCK_CAP_MS,
|
|
210
|
+
type LadderAction,
|
|
211
|
+
};
|
|
178
212
|
|
|
179
213
|
/** Re-exported so a test can assert the IDENTITY, not two matching literals. */
|
|
180
214
|
export { TRANSCRIPT_READ_MAX_BYTES };
|
|
@@ -198,11 +232,6 @@ export const EVENTS_RELPATH = path.join(
|
|
|
198
232
|
);
|
|
199
233
|
const STATE_DIR_REL = path.join('agents', 'runtime', 'state');
|
|
200
234
|
|
|
201
|
-
/** Ladder defaults. Phase 1.1 pre-registers all three for revisit, not tuning. */
|
|
202
|
-
export const MAX_ITERATIONS = 25;
|
|
203
|
-
export const WALL_CLOCK_CAP_MS = 4 * 60 * 60 * 1000;
|
|
204
|
-
export const STALL_WINDOW = 3;
|
|
205
|
-
|
|
206
235
|
/**
|
|
207
236
|
* How many consecutive absent-roadmap fires confirm the absence.
|
|
208
237
|
*
|
|
@@ -285,6 +314,14 @@ export interface RunState {
|
|
|
285
314
|
* cannot finish") named these rungs as its mitigation.
|
|
286
315
|
*/
|
|
287
316
|
halted?: LadderAction;
|
|
317
|
+
/**
|
|
318
|
+
* The fingerprint this run ENGAGED under — its plan premise, recorded once on
|
|
319
|
+
* the first engagement from `_lib/context_observation` and then left alone.
|
|
320
|
+
* Refreshing it every fire would make both sides of the premise comparison
|
|
321
|
+
* equal by construction and the rung unreachable. Absent means the run never
|
|
322
|
+
* observed one, which is never a disagreement (`premiseMoved`).
|
|
323
|
+
*/
|
|
324
|
+
context_fingerprint?: string;
|
|
288
325
|
}
|
|
289
326
|
|
|
290
327
|
/**
|
|
@@ -347,34 +384,6 @@ export interface ScanResult {
|
|
|
347
384
|
next: NextStep | null;
|
|
348
385
|
}
|
|
349
386
|
|
|
350
|
-
export type LadderAction =
|
|
351
|
-
| 'engage'
|
|
352
|
-
| 'complete'
|
|
353
|
-
| 'blocked'
|
|
354
|
-
| 'halt-max-iterations'
|
|
355
|
-
| 'halt-wall-clock'
|
|
356
|
-
| 'halt-stall'
|
|
357
|
-
| 'halt-dependency-unavailable';
|
|
358
|
-
|
|
359
|
-
/** The terminal rungs — the set `RunState.halted` may hold. */
|
|
360
|
-
/**
|
|
361
|
-
* `halt-roadmap-absent` is deliberately NOT in this union and not in
|
|
362
|
-
* `LadderAction`. It is an event name the caller emits directly when the claimed
|
|
363
|
-
* roadmap is unreadable from the authoritative tree, and it CLEARS the state
|
|
364
|
-
* rather than stamping `halted` — widening the union would let `parseRecord`
|
|
365
|
-
* accept it as a `halted` value, which would mean a run whose budget was cleared
|
|
366
|
-
* also carried a halt stamp. The two are mutually exclusive by construction.
|
|
367
|
-
*/
|
|
368
|
-
export const HALT_ACTIONS: readonly LadderAction[] = [
|
|
369
|
-
'halt-max-iterations',
|
|
370
|
-
'halt-wall-clock',
|
|
371
|
-
'halt-stall',
|
|
372
|
-
// Phase 5.4. Checked BEFORE the counter rungs: a dependency the run cannot
|
|
373
|
-
// obtain is not something more iterations close, so consuming the budget
|
|
374
|
-
// against it is the waste the rung exists to stop.
|
|
375
|
-
'halt-dependency-unavailable',
|
|
376
|
-
];
|
|
377
|
-
|
|
378
387
|
/**
|
|
379
388
|
* Frontmatter `execution.mode`, or null. Line-oriented on purpose: the
|
|
380
389
|
* frontmatter this repo writes is two levels deep at most, and a YAML parser
|
|
@@ -480,50 +489,6 @@ export function extractVerify(stepText: string): string | null {
|
|
|
480
489
|
return null;
|
|
481
490
|
}
|
|
482
491
|
|
|
483
|
-
/**
|
|
484
|
-
* The termination ladder, pure. `state` is the record BEFORE this stop;
|
|
485
|
-
* `openCount` is the scan of the claimed roadmap as it stands now.
|
|
486
|
-
*/
|
|
487
|
-
export function ladder(
|
|
488
|
-
state: RunState,
|
|
489
|
-
openCount: number,
|
|
490
|
-
nowMs: number,
|
|
491
|
-
// No default: `= 0` would silently restore the complete-instead-of-blocked
|
|
492
|
-
// behaviour for any caller that omitted it.
|
|
493
|
-
blockedCount: number,
|
|
494
|
-
caps: { maxIterations: number; wallClockMs: number; stallWindow: number } = {
|
|
495
|
-
maxIterations: MAX_ITERATIONS,
|
|
496
|
-
wallClockMs: WALL_CLOCK_CAP_MS,
|
|
497
|
-
stallWindow: STALL_WINDOW,
|
|
498
|
-
},
|
|
499
|
-
// Phase 5.4. `null` when nothing unobtainable was detected. Optional so every
|
|
500
|
-
// existing caller and test keeps its meaning unchanged.
|
|
501
|
-
unavailable: UnavailableDependency | null = null,
|
|
502
|
-
): LadderAction {
|
|
503
|
-
// A halt is terminal for this run id. Checked BEFORE `complete` so a
|
|
504
|
-
// halted run whose roadmap later reads zero-open does not report a
|
|
505
|
-
// completion it never reached.
|
|
506
|
-
if (state.halted) return state.halted;
|
|
507
|
-
// `scanOpenSteps` EXCLUDES `blocked-by:` steps from `openCount`, so zero-open
|
|
508
|
-
// with blocked steps left is exhaustion of runnable work, not completion —
|
|
509
|
-
// ADR-235's own terminal outcome, and never a sixth halt.
|
|
510
|
-
if (openCount === 0) return blockedCount > 0 ? 'blocked' : 'complete';
|
|
511
|
-
// BEFORE the counter rungs, deliberately: a missing credential, an absent
|
|
512
|
-
// binary or an exhausted quota is not closed by iterating, so spending the
|
|
513
|
-
// budget on it converts a nameable blocker into an anonymous cap-out.
|
|
514
|
-
if (unavailable !== null) return 'halt-dependency-unavailable';
|
|
515
|
-
if (state.iterations >= caps.maxIterations) return 'halt-max-iterations';
|
|
516
|
-
const started = Date.parse(state.started_at);
|
|
517
|
-
if (Number.isFinite(started) && nowMs - started >= caps.wallClockMs) {
|
|
518
|
-
return 'halt-wall-clock';
|
|
519
|
-
}
|
|
520
|
-
const tail = state.history.slice(-caps.stallWindow);
|
|
521
|
-
if (tail.length >= caps.stallWindow && tail.every((n) => n === openCount)) {
|
|
522
|
-
return 'halt-stall';
|
|
523
|
-
}
|
|
524
|
-
return 'engage';
|
|
525
|
-
}
|
|
526
|
-
|
|
527
492
|
/**
|
|
528
493
|
* Where a run's state lives: keyed on the session AND the roadmap.
|
|
529
494
|
*
|
|
@@ -686,16 +651,17 @@ function readState(file: string): RunState | null {
|
|
|
686
651
|
if (o['inert_reported'] === true) {
|
|
687
652
|
rec.inert_reported = true;
|
|
688
653
|
}
|
|
689
|
-
//
|
|
690
|
-
//
|
|
691
|
-
//
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
typeof halted === 'string' &&
|
|
695
|
-
(HALT_ACTIONS as readonly string[]).includes(halted)
|
|
696
|
-
) {
|
|
697
|
-
rec.halted = halted as LadderAction;
|
|
654
|
+
// Round-tripped for the same reason `history_source` is: dropped, the
|
|
655
|
+
// premise would be re-recorded every fire from the newest observation, so
|
|
656
|
+
// the two sides could never differ and the rung would be dead code.
|
|
657
|
+
if (typeof o['context_fingerprint'] === 'string' && o['context_fingerprint'] !== '') {
|
|
658
|
+
rec.context_fingerprint = o['context_fingerprint'];
|
|
698
659
|
}
|
|
660
|
+
// Tolerant, not permissive — see `parseHaltStamp` for what it accepts
|
|
661
|
+
// beyond the halt set and why dropping a newer build's stamp was the
|
|
662
|
+
// wrong failure direction for a budget.
|
|
663
|
+
const halted = parseHaltStamp(o['halted']);
|
|
664
|
+
if (halted !== null) rec.halted = halted;
|
|
699
665
|
return rec;
|
|
700
666
|
} catch {
|
|
701
667
|
return null;
|
|
@@ -1412,7 +1378,21 @@ export function main(): number {
|
|
|
1412
1378
|
// differently. One producer, one definition.
|
|
1413
1379
|
state.stall = stallSignal(state.history, STALL_WINDOW).level;
|
|
1414
1380
|
|
|
1415
|
-
|
|
1381
|
+
// 2.1 — repository drift, from the newest observation `roadmap:context`
|
|
1382
|
+
// recorded. No probe here: the fingerprint costs a `gh` call and this is the
|
|
1383
|
+
// Stop path. An unknown on either side is never a halt.
|
|
1384
|
+
const observed = readContextObservation(workspaceRoot)?.fingerprint ?? null;
|
|
1385
|
+
const premiseInvalidated = premiseMoved(state.context_fingerprint, observed);
|
|
1386
|
+
|
|
1387
|
+
const action = ladder(
|
|
1388
|
+
state,
|
|
1389
|
+
scan.open,
|
|
1390
|
+
Date.now(),
|
|
1391
|
+
scan.blocked,
|
|
1392
|
+
undefined,
|
|
1393
|
+
unavailable,
|
|
1394
|
+
premiseInvalidated,
|
|
1395
|
+
);
|
|
1416
1396
|
|
|
1417
1397
|
if (action !== 'engage') {
|
|
1418
1398
|
// A run that is ALREADY stamped emits nothing further — round 6 finding 6.
|
|
@@ -1436,6 +1416,12 @@ export function main(): number {
|
|
|
1436
1416
|
iterations: state.iterations,
|
|
1437
1417
|
open: scan.open,
|
|
1438
1418
|
blocked: scan.blocked,
|
|
1419
|
+
// A ledger line is a persisted shape carrying a `RunTerminalState`,
|
|
1420
|
+
// so it names the vocabulary version it was written against: a
|
|
1421
|
+
// reader meeting an unknown value can then tell a newer writer
|
|
1422
|
+
// from a corrupt row.
|
|
1423
|
+
terminal_state: terminalStateFor(action),
|
|
1424
|
+
terminal_vocabulary_version: RUN_TERMINAL_VOCABULARY_VERSION,
|
|
1439
1425
|
at: new Date().toISOString(),
|
|
1440
1426
|
...roots,
|
|
1441
1427
|
});
|
|
@@ -1472,6 +1458,10 @@ export function main(): number {
|
|
|
1472
1458
|
|
|
1473
1459
|
state.iterations += 1;
|
|
1474
1460
|
state.last_turn = turnOrdinal;
|
|
1461
|
+
// Recorded ONCE — the premise this run engaged under. See the field's docblock.
|
|
1462
|
+
if (state.context_fingerprint === undefined && observed !== null) {
|
|
1463
|
+
state.context_fingerprint = observed;
|
|
1464
|
+
}
|
|
1475
1465
|
state.history.push(scan.open);
|
|
1476
1466
|
state.last_engaged_at = new Date().toISOString();
|
|
1477
1467
|
if (!writeState(stateFile, state)) {
|
|
@@ -54,6 +54,7 @@ import {
|
|
|
54
54
|
scanEolSlice,
|
|
55
55
|
type EolCounters,
|
|
56
56
|
} from '../_lib/session_eol.js';
|
|
57
|
+
import { readContextObservation } from '../_lib/context_observation.js';
|
|
57
58
|
import { buildCheckpoint, writeCheckpoint } from '../_lib/run_checkpoint.js';
|
|
58
59
|
import { read_claimed_slug } from '../session_register_hook.js';
|
|
59
60
|
import { unwrap, type JsonObject, type JsonValue } from './envelope.js';
|
|
@@ -381,7 +382,17 @@ export function main(): number {
|
|
|
381
382
|
try {
|
|
382
383
|
const slug = read_claimed_slug(workspaceRoot, checkpointRunId);
|
|
383
384
|
if (slug !== null) {
|
|
384
|
-
|
|
385
|
+
// `road-to-wired-instruments` 2.1. The fingerprint was never
|
|
386
|
+
// passed here, so `context_fingerprint` was null in every
|
|
387
|
+
// checkpoint this package has ever written and the resume-time
|
|
388
|
+
// drift check it exists for could not fire. The value comes from
|
|
389
|
+
// the newest recorded probe rather than from a fresh one: this is
|
|
390
|
+
// the Stop path, and the probe costs a `gh` call. Absent stays
|
|
391
|
+
// absent, which reads as "not known" and never as "unchanged".
|
|
392
|
+
const observed = readContextObservation(workspaceRoot)?.fingerprint ?? null;
|
|
393
|
+
const cp = buildCheckpoint(workspaceRoot, eolSessionKey(checkpointRunId), slug, {
|
|
394
|
+
...(observed !== null ? { contextFingerprint: observed } : {}),
|
|
395
|
+
});
|
|
385
396
|
if (cp !== null) writeCheckpoint(workspaceRoot, cp);
|
|
386
397
|
}
|
|
387
398
|
} catch {
|
|
@@ -579,12 +579,20 @@ export function readLanguagePin(workspaceRoot: string, session_id: string): Verd
|
|
|
579
579
|
* WHAT IS ACTUALLY CLASSIFIED, stated accurately because R2 finding 9 caught
|
|
580
580
|
* this file claiming otherwise in three places. `visibleProse` strips code,
|
|
581
581
|
* quotes, tables, URLs and paths from the whole reply — but `classify` then
|
|
582
|
-
* applies `
|
|
582
|
+
* applies `stripInjectedRegions` (which removes balanced host wrapper regions
|
|
583
|
+
* such as `<launch-selected-element>`, plus the host's advisory sentence beside
|
|
584
|
+
* them), then `instructionText` (which drops output-shaped lines and their
|
|
583
585
|
* followers) and `humanAuthoredLead`, and RETURNS ON THE LEAD ALONE when the
|
|
584
586
|
* lead is determined. So in the common case the verdict comes from the reply's
|
|
585
587
|
* opening chunk, not from all of it, and indented prose is discarded before
|
|
586
588
|
* scoring.
|
|
587
589
|
*
|
|
590
|
+
* The region strip reaches this path too, and its effect here is small by
|
|
591
|
+
* construction: `visibleProse` has already removed fenced code, so a balanced
|
|
592
|
+
* bare-tag pair surviving into the scorer is prose the reply wrote around a tag
|
|
593
|
+
* rather than markup. Named rather than omitted, because enumerating the
|
|
594
|
+
* scoring surface accurately is this comment's entire job.
|
|
595
|
+
*
|
|
588
596
|
* That is deliberately left as-is rather than swapped for a full-text scorer:
|
|
589
597
|
* sharing one classifier with `language_mirror_hook` is what stops the pin and
|
|
590
598
|
* the detector disagreeing about what language a turn is in, and changing the
|
|
@@ -26,6 +26,24 @@ cat > "$HOOKS_DIR/pre-push" << 'EOF'
|
|
|
26
26
|
# Pre-push hook: mirror the CI "Sync + Generate Tools Consistency" gate LOCALLY
|
|
27
27
|
# so derived-output drift is caught BEFORE push, not in remote CI.
|
|
28
28
|
#
|
|
29
|
+
# THIS HOOK REFUSES. IT NEVER MERGES, AND NO ONE MAY "IMPROVE" IT INTO ONE.
|
|
30
|
+
# A merge inside pre-push rewrites the working tree at the exact moment the
|
|
31
|
+
# contributor believes their work is finished: one rejected push silently
|
|
32
|
+
# becomes an unreviewed commit, and a conflict lands them mid-merge with no
|
|
33
|
+
# warning and no way back to the state they typed `git push` from. Detection
|
|
34
|
+
# belongs here; resolution belongs to a step run with the result in front of
|
|
35
|
+
# you. When this hook refuses for staleness, the thing that fixes it is
|
|
36
|
+
#
|
|
37
|
+
# task push-ready # fetch -> integrate the base SET -> regenerate
|
|
38
|
+
# # -> verify -> re-check freshness -> push
|
|
39
|
+
# task push-ready DRY=1 # the same six steps, read-only
|
|
40
|
+
#
|
|
41
|
+
# The base is a SET: a branch targeting a release line or a stacked parent may
|
|
42
|
+
# also have to integrate the default branch, per the branch-convergence policy
|
|
43
|
+
# read at the TARGET commit (src/scripts/_lib/branch_convergence.ts). The
|
|
44
|
+
# default is merged FIRST, so a conflict surfaces against the broader base
|
|
45
|
+
# where it is cheapest to abandon.
|
|
46
|
+
#
|
|
29
47
|
# History: the remote "Consistency" check failed in a large share of PRs because
|
|
30
48
|
# the old hook only verified dist sync + the COMMAND count — it missed
|
|
31
49
|
# guideline/skill/rule count drift and the generate-tools / router / corpus
|
|
@@ -83,7 +83,11 @@ import {
|
|
|
83
83
|
session_state_file,
|
|
84
84
|
} from "./hooks/state_io.js";
|
|
85
85
|
import { readHookStdin } from "./hooks/hook_stdin.js";
|
|
86
|
-
import {
|
|
86
|
+
import {
|
|
87
|
+
humanAuthoredLead,
|
|
88
|
+
isSyntheticPrompt,
|
|
89
|
+
stripInjectedRegions,
|
|
90
|
+
} from "./_lib/prompt_shape.js";
|
|
87
91
|
|
|
88
92
|
const EXIT_ALLOW = 0;
|
|
89
93
|
// Severity is taken from the EXIT CODE, not from the `decision` field in the
|
|
@@ -296,9 +300,17 @@ export function instructionText(prompt: string): string {
|
|
|
296
300
|
* an English instruction over a German paste resolves to English by the same
|
|
297
301
|
* step. The fallback is what keeps it conservative: a prompt with no document
|
|
298
302
|
* marker classifies exactly as it did before.
|
|
303
|
+
*
|
|
304
|
+
* `stripInjectedRegions` runs FIRST, and the order is load-bearing rather than
|
|
305
|
+
* tidy. A host wrapper the user never typed — `<launch-selected-element>` — is
|
|
306
|
+
* a bare tag line, which `humanAuthoredLead` read as the END of the human lead;
|
|
307
|
+
* prepended, as the host prepends it, that returned an empty lead and handed the
|
|
308
|
+
* verdict to ~4 KB of injected markup. Stripping before `instructionText` also
|
|
309
|
+
* keeps the block's indented lines from arming that filter's paste state, which
|
|
310
|
+
* was deleting the user's own sentence outright.
|
|
299
311
|
*/
|
|
300
312
|
export function classify(prompt: string): Classification {
|
|
301
|
-
const text = instructionText(prompt);
|
|
313
|
+
const text = instructionText(stripInjectedRegions(prompt));
|
|
302
314
|
const lead = humanAuthoredLead(text);
|
|
303
315
|
const leadVerdict = _score(lead);
|
|
304
316
|
if (leadVerdict.language !== "und") {
|