pi-harness-runtime 1.1.394 → 1.1.396
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.md +135 -4
- package/harness/glm-quota-logger.ts +17 -0
- package/harness/langchain/planner-logger.ts +15 -0
- package/harness/service-diagnostics.ts +32 -1
- package/index.ts +92 -3
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/agent-policy/package.json +1 -1
- package/packages/architecture-generator/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/clipboard-plugin/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/codex-watcher/package.json +1 -1
- package/packages/config-capture/package.json +1 -1
- package/packages/connection-runtime/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/contracts/dist/workspace-env-format.d.ts +87 -0
- package/packages/contracts/dist/workspace-env-format.js +174 -6
- package/packages/contracts/dist/workspace-env.js +120 -9
- package/packages/contracts/package.json +1 -1
- package/packages/contracts/src/workspace-env-format.ts +209 -6
- package/packages/contracts/src/workspace-env.ts +128 -7
- package/packages/contracts/test/workspace-env.test.ts +177 -0
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/durable-review/package.json +1 -1
- package/packages/e2e-tester/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-sink/package.json +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/file-copy-helper/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/jev-judge/dist/continuation-controller.d.ts +47 -0
- package/packages/jev-judge/dist/continuation-controller.d.ts.map +1 -1
- package/packages/jev-judge/dist/continuation-controller.js +142 -16
- package/packages/jev-judge/dist/continuation-controller.js.map +1 -1
- package/packages/jev-judge/dist/index.d.ts +6 -0
- package/packages/jev-judge/dist/index.d.ts.map +1 -1
- package/packages/jev-judge/dist/index.js +6 -0
- package/packages/jev-judge/dist/index.js.map +1 -1
- package/packages/jev-judge/dist/validation-ledger.d.ts +129 -0
- package/packages/jev-judge/dist/validation-ledger.d.ts.map +1 -0
- package/packages/jev-judge/dist/validation-ledger.js +234 -0
- package/packages/jev-judge/dist/validation-ledger.js.map +1 -0
- package/packages/jev-judge/dist/validation-plan.d.ts +176 -0
- package/packages/jev-judge/dist/validation-plan.d.ts.map +1 -0
- package/packages/jev-judge/dist/validation-plan.js +293 -0
- package/packages/jev-judge/dist/validation-plan.js.map +1 -0
- package/packages/jev-judge/dist/validation-tie-breaker.d.ts +48 -0
- package/packages/jev-judge/dist/validation-tie-breaker.d.ts.map +1 -0
- package/packages/jev-judge/dist/validation-tie-breaker.js +83 -0
- package/packages/jev-judge/dist/validation-tie-breaker.js.map +1 -0
- package/packages/jev-judge/package.json +1 -1
- package/packages/jev-judge/src/continuation-controller.ts +179 -20
- package/packages/jev-judge/src/index.ts +41 -0
- package/packages/jev-judge/src/validation-ledger.ts +290 -0
- package/packages/jev-judge/src/validation-plan.ts +406 -0
- package/packages/jev-judge/src/validation-tie-breaker.ts +123 -0
- package/packages/jev-judge/tests/continuation-controller.test.ts +167 -0
- package/packages/jev-judge/tests/validation-ledger.test.ts +181 -0
- package/packages/jev-judge/tests/validation-plan.test.ts +170 -0
- package/packages/jev-judge/tests/validation-tie-breaker.test.ts +88 -0
- package/packages/knowledge-graph/package.json +1 -1
- package/packages/knowledge-retrieval/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/logging/README.md +37 -0
- package/packages/logging/dist/buffer.d.ts +33 -0
- package/packages/logging/dist/buffer.d.ts.map +1 -0
- package/packages/logging/dist/buffer.js +60 -0
- package/packages/logging/dist/buffer.js.map +1 -0
- package/packages/logging/dist/config.d.ts +40 -0
- package/packages/logging/dist/config.d.ts.map +1 -0
- package/packages/logging/dist/config.js +114 -0
- package/packages/logging/dist/config.js.map +1 -0
- package/packages/logging/dist/index.d.ts +32 -0
- package/packages/logging/dist/index.d.ts.map +1 -0
- package/packages/logging/dist/index.js +31 -0
- package/packages/logging/dist/index.js.map +1 -0
- package/packages/logging/dist/redact.d.ts +43 -0
- package/packages/logging/dist/redact.d.ts.map +1 -0
- package/packages/logging/dist/redact.js +220 -0
- package/packages/logging/dist/redact.js.map +1 -0
- package/packages/logging/dist/sampler.d.ts +37 -0
- package/packages/logging/dist/sampler.d.ts.map +1 -0
- package/packages/logging/dist/sampler.js +78 -0
- package/packages/logging/dist/sampler.js.map +1 -0
- package/packages/logging/dist/shipper.d.ts +82 -0
- package/packages/logging/dist/shipper.d.ts.map +1 -0
- package/packages/logging/dist/shipper.js +238 -0
- package/packages/logging/dist/shipper.js.map +1 -0
- package/packages/logging/dist/singleton.d.ts +38 -0
- package/packages/logging/dist/singleton.d.ts.map +1 -0
- package/packages/logging/dist/singleton.js +95 -0
- package/packages/logging/dist/singleton.js.map +1 -0
- package/packages/logging/dist/spool.d.ts +39 -0
- package/packages/logging/dist/spool.d.ts.map +1 -0
- package/packages/logging/dist/spool.js +110 -0
- package/packages/logging/dist/spool.js.map +1 -0
- package/packages/logging/dist/transports/r2.d.ts +31 -0
- package/packages/logging/dist/transports/r2.d.ts.map +1 -0
- package/packages/logging/dist/transports/r2.js +60 -0
- package/packages/logging/dist/transports/r2.js.map +1 -0
- package/packages/logging/dist/transports/webhook.d.ts +22 -0
- package/packages/logging/dist/transports/webhook.d.ts.map +1 -0
- package/packages/logging/dist/transports/webhook.js +37 -0
- package/packages/logging/dist/transports/webhook.js.map +1 -0
- package/packages/logging/dist/types.d.ts +73 -0
- package/packages/logging/dist/types.d.ts.map +1 -0
- package/packages/logging/dist/types.js +19 -0
- package/packages/logging/dist/types.js.map +1 -0
- package/packages/logging/package.json +37 -0
- package/packages/logging/src/buffer.ts +77 -0
- package/packages/logging/src/config.ts +163 -0
- package/packages/logging/src/index.ts +87 -0
- package/packages/logging/src/redact.ts +271 -0
- package/packages/logging/src/sampler.ts +97 -0
- package/packages/logging/src/shipper.ts +281 -0
- package/packages/logging/src/singleton.ts +142 -0
- package/packages/logging/src/spool.ts +139 -0
- package/packages/logging/src/transports/r2.ts +86 -0
- package/packages/logging/src/transports/webhook.ts +54 -0
- package/packages/logging/src/types.ts +85 -0
- package/packages/logging/test/buffer.test.ts +44 -0
- package/packages/logging/test/config.test.ts +97 -0
- package/packages/logging/test/integration.test.ts +135 -0
- package/packages/logging/test/redact.test.ts +109 -0
- package/packages/logging/test/sampler.test.ts +57 -0
- package/packages/logging/test/shipper.test.ts +152 -0
- package/packages/logging/test/spool.test.ts +93 -0
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/milestone-manager/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/okf-indexer/package.json +1 -1
- package/packages/paperclip-integration/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/permission-mode/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/project-bootstrap/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/qdrant-skills/package.json +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/relay/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-mcp-client/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/skills/package.json +1 -1
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/telegram/package.json +1 -1
- package/packages/tencentdb-memory/package.json +1 -1
- package/packages/tencentdb-sync/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/trajectory/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/voice-api/package.json +1 -1
- package/packages/webmcp-tester/package.json +1 -1
- package/packages/wiki/package.json +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/packages/write-review/package.json +1 -1
- package/scripts/unified-webhook-server.ts +102 -0
- package/scripts/validation-run.ts +191 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation Plan - staged (fast -> full) test tiers for a todo.
|
|
3
|
+
*
|
|
4
|
+
* The harness NEVER guesses a tier from a command string. A tier is declared
|
|
5
|
+
* by the task author in the todo metadata, so the plan stays truthful and
|
|
6
|
+
* reviewable:
|
|
7
|
+
*
|
|
8
|
+
* ```json
|
|
9
|
+
* {
|
|
10
|
+
* "metadata": {
|
|
11
|
+
* "validationPlan": {
|
|
12
|
+
* "fast": { "command": "bun test tests/fast", "expectedDurationMs": 18000, "datasetSize": 100 },
|
|
13
|
+
* "full": { "command": "bun test tests/full", "expectedDurationMs": 2400000, "datasetSize": 10000 },
|
|
14
|
+
* "budgetMinutes": 90,
|
|
15
|
+
* "finalTierRequired": true
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Every field is optional. A todo without a plan keeps the current behaviour
|
|
22
|
+
* (no validation context is injected), so small tasks are unaffected.
|
|
23
|
+
*/
|
|
24
|
+
import type { TodoItem } from "./todo-provider.js";
|
|
25
|
+
/**
|
|
26
|
+
* Which side of the ladder a tier sits on.
|
|
27
|
+
*
|
|
28
|
+
* - `fast`: representative, cheap, safe to run after every edit
|
|
29
|
+
* - `full`: complete, expensive, run once as the final acceptance check
|
|
30
|
+
*/
|
|
31
|
+
export type ValidationTierKind = "fast" | "full";
|
|
32
|
+
/**
|
|
33
|
+
* One declared validation tier.
|
|
34
|
+
*/
|
|
35
|
+
export interface ValidationTier {
|
|
36
|
+
kind: ValidationTierKind;
|
|
37
|
+
/** Exact command for this tier. Never rewritten by the harness. */
|
|
38
|
+
command?: string;
|
|
39
|
+
/** Human label, e.g. "fixture regression". */
|
|
40
|
+
label?: string;
|
|
41
|
+
/** Expected cost of the tier in milliseconds (measured or estimated). */
|
|
42
|
+
expectedDurationMs?: number;
|
|
43
|
+
/** Dataset size the tier exercises, when it is data-volume bound. */
|
|
44
|
+
datasetSize?: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* State of one tier for one todo item.
|
|
48
|
+
*/
|
|
49
|
+
export interface ValidationTierState {
|
|
50
|
+
/** `not-run` when no run was recorded for this tier. */
|
|
51
|
+
status: "passed" | "failed" | "timeout" | "error" | "skipped" | "not-run";
|
|
52
|
+
/** Timestamp of the latest run. */
|
|
53
|
+
at?: string;
|
|
54
|
+
/** Duration of the latest run. */
|
|
55
|
+
durationMs?: number;
|
|
56
|
+
/** Command of the latest run. */
|
|
57
|
+
command?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Aggregated validation state of a todo item.
|
|
61
|
+
*/
|
|
62
|
+
export interface ValidationState {
|
|
63
|
+
/** True when the item declares a validation plan. */
|
|
64
|
+
hasPlan: boolean;
|
|
65
|
+
/** State of the cheap tier. */
|
|
66
|
+
fast: ValidationTierState;
|
|
67
|
+
/** State of the expensive tier. */
|
|
68
|
+
full: ValidationTierState;
|
|
69
|
+
/** True when the plan declares the full tier as the final acceptance check. */
|
|
70
|
+
finalTierRequired: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* True when the final tier is required but has not passed yet.
|
|
73
|
+
*
|
|
74
|
+
* A todo in this state must not be reported as complete.
|
|
75
|
+
*/
|
|
76
|
+
finalTierPending: boolean;
|
|
77
|
+
/** Soft time budget of the plan, in minutes. */
|
|
78
|
+
budgetMinutes?: number;
|
|
79
|
+
/** True when the plan requires a final tier but does not declare one. */
|
|
80
|
+
planIncomplete: boolean;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The full staged validation plan for a todo.
|
|
84
|
+
*/
|
|
85
|
+
export interface ValidationPlan {
|
|
86
|
+
/** Cheap representative tier, used while the code is changing. */
|
|
87
|
+
fast?: ValidationTier;
|
|
88
|
+
/** Expensive complete tier, used once the implementation is stable. */
|
|
89
|
+
full?: ValidationTier;
|
|
90
|
+
/** Extra guidance for the agent (e.g. "fast tier must cover aggregation"). */
|
|
91
|
+
notes?: string;
|
|
92
|
+
/** Soft time budget for this todo, in minutes. */
|
|
93
|
+
budgetMinutes?: number;
|
|
94
|
+
/** When true, the todo must not be completed before the full tier passed. */
|
|
95
|
+
finalTierRequired?: boolean;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Parse a duration into milliseconds.
|
|
99
|
+
*
|
|
100
|
+
* Strings must carry a unit (`45s`, `40m`, `1h`, `1h30m`). A bare number is
|
|
101
|
+
* milliseconds when it is at least 1000 and seconds below that, because a
|
|
102
|
+
* bare "40" is ambiguous between milliseconds and minutes.
|
|
103
|
+
*/
|
|
104
|
+
export declare function parseDurationMs(value: unknown): number | undefined;
|
|
105
|
+
/**
|
|
106
|
+
* Format a duration for a human-readable status line.
|
|
107
|
+
*/
|
|
108
|
+
export declare function formatDuration(ms: number): string;
|
|
109
|
+
/**
|
|
110
|
+
* Parse one tier declaration.
|
|
111
|
+
*
|
|
112
|
+
* Accepts a plain command string (`"bun test fast"`) or an object with
|
|
113
|
+
* `command`/`label`/`expectedDurationMs`/`datasetSize` fields.
|
|
114
|
+
*/
|
|
115
|
+
export declare function parseTier(value: unknown, kind: ValidationTierKind): ValidationTier | undefined;
|
|
116
|
+
/**
|
|
117
|
+
* Read the validation plan of a todo.
|
|
118
|
+
*
|
|
119
|
+
* Returns `null` when the todo declares no plan: ordinary tasks must keep the
|
|
120
|
+
* current behaviour.
|
|
121
|
+
*/
|
|
122
|
+
export declare function parseValidationPlan(item: TodoItem | null | undefined): ValidationPlan | null;
|
|
123
|
+
/**
|
|
124
|
+
* Describe one tier in a single line: command, expected cost, dataset size.
|
|
125
|
+
*/
|
|
126
|
+
export declare function describeTier(tier: ValidationTier): string;
|
|
127
|
+
/**
|
|
128
|
+
* Status of the soft time budget of a plan.
|
|
129
|
+
*/
|
|
130
|
+
export interface ValidationBudgetStatus {
|
|
131
|
+
/** The budget in milliseconds, when the plan declares one. */
|
|
132
|
+
budgetMs?: number;
|
|
133
|
+
/** Time already spent on the item, when it is known. */
|
|
134
|
+
elapsedMs?: number;
|
|
135
|
+
/** Time left before the budget is exhausted. */
|
|
136
|
+
remainingMs?: number;
|
|
137
|
+
/** True when the budget is spent. */
|
|
138
|
+
exhausted: boolean;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Compute the budget status of a plan.
|
|
142
|
+
*
|
|
143
|
+
* There is no implicit budget: only a declared `budgetMinutes` arms it. An
|
|
144
|
+
* invented budget could pause legitimate long work, so the harness never
|
|
145
|
+
* guesses one.
|
|
146
|
+
*/
|
|
147
|
+
export declare function validationBudgetStatus(plan: ValidationPlan | null | undefined, elapsedMs?: number): ValidationBudgetStatus;
|
|
148
|
+
/**
|
|
149
|
+
* Aggregate recorded runs into the validation state of an item.
|
|
150
|
+
*
|
|
151
|
+
* The runs are expected in chronological order; the latest run of a tier
|
|
152
|
+
* defines its state.
|
|
153
|
+
*/
|
|
154
|
+
export declare function summarizeValidationState(plan: ValidationPlan | null | undefined, runs: {
|
|
155
|
+
ts: string;
|
|
156
|
+
tier: ValidationTierKind;
|
|
157
|
+
status: string;
|
|
158
|
+
}[]): ValidationState;
|
|
159
|
+
/**
|
|
160
|
+
* Render the validation context that is injected into a continuation message.
|
|
161
|
+
*
|
|
162
|
+
* The text is deliberately short: it is added to the steer payload that the
|
|
163
|
+
* agent reads when the harness continues a todo on its own.
|
|
164
|
+
*/
|
|
165
|
+
export declare function formatValidationContext(plan: ValidationPlan, opts?: {
|
|
166
|
+
elapsedMs?: number;
|
|
167
|
+
state?: ValidationState;
|
|
168
|
+
}): string;
|
|
169
|
+
/**
|
|
170
|
+
* Convenience wrapper: the validation context of a todo, or an empty string.
|
|
171
|
+
*/
|
|
172
|
+
export declare function buildValidationSteerSuffix(item: TodoItem | null | undefined, opts?: {
|
|
173
|
+
elapsedMs?: number;
|
|
174
|
+
state?: ValidationState;
|
|
175
|
+
}): string;
|
|
176
|
+
//# sourceMappingURL=validation-plan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-plan.d.ts","sourceRoot":"","sources":["../src/validation-plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation Plan - staged (fast -> full) test tiers for a todo.
|
|
3
|
+
*
|
|
4
|
+
* The harness NEVER guesses a tier from a command string. A tier is declared
|
|
5
|
+
* by the task author in the todo metadata, so the plan stays truthful and
|
|
6
|
+
* reviewable:
|
|
7
|
+
*
|
|
8
|
+
* ```json
|
|
9
|
+
* {
|
|
10
|
+
* "metadata": {
|
|
11
|
+
* "validationPlan": {
|
|
12
|
+
* "fast": { "command": "bun test tests/fast", "expectedDurationMs": 18000, "datasetSize": 100 },
|
|
13
|
+
* "full": { "command": "bun test tests/full", "expectedDurationMs": 2400000, "datasetSize": 10000 },
|
|
14
|
+
* "budgetMinutes": 90,
|
|
15
|
+
* "finalTierRequired": true
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Every field is optional. A todo without a plan keeps the current behaviour
|
|
22
|
+
* (no validation context is injected), so small tasks are unaffected.
|
|
23
|
+
*/
|
|
24
|
+
function asRecord(value) {
|
|
25
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
26
|
+
return null;
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
function firstString(source, keys) {
|
|
30
|
+
for (const key of keys) {
|
|
31
|
+
const value = source[key];
|
|
32
|
+
if (typeof value === "string" && value.trim().length > 0)
|
|
33
|
+
return value.trim();
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
function firstNumber(source, keys) {
|
|
38
|
+
for (const key of keys) {
|
|
39
|
+
const value = source[key];
|
|
40
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Parse a duration into milliseconds.
|
|
47
|
+
*
|
|
48
|
+
* Strings must carry a unit (`45s`, `40m`, `1h`, `1h30m`). A bare number is
|
|
49
|
+
* milliseconds when it is at least 1000 and seconds below that, because a
|
|
50
|
+
* bare "40" is ambiguous between milliseconds and minutes.
|
|
51
|
+
*/
|
|
52
|
+
export function parseDurationMs(value) {
|
|
53
|
+
if (typeof value === "number") {
|
|
54
|
+
if (!Number.isFinite(value))
|
|
55
|
+
return undefined;
|
|
56
|
+
return value >= 1000 ? value : Math.round(value * 1000);
|
|
57
|
+
}
|
|
58
|
+
if (typeof value !== "string")
|
|
59
|
+
return undefined;
|
|
60
|
+
const text = value.trim().toLowerCase();
|
|
61
|
+
if (!text)
|
|
62
|
+
return undefined;
|
|
63
|
+
const match = /^(?:(\d+(?:\.\d+)?)h)?\s*(?:(\d+(?:\.\d+)?)m)?\s*(?:(\d+(?:\.\d+)?)s)?$/.exec(text);
|
|
64
|
+
if (!match || (!match[1] && !match[2] && !match[3]))
|
|
65
|
+
return undefined;
|
|
66
|
+
const hours = match[1] ? Number(match[1]) : 0;
|
|
67
|
+
const minutes = match[2] ? Number(match[2]) : 0;
|
|
68
|
+
const seconds = match[3] ? Number(match[3]) : 0;
|
|
69
|
+
if (hours === 0 && minutes === 0 && seconds === 0)
|
|
70
|
+
return undefined;
|
|
71
|
+
return Math.round((hours * 3600 + minutes * 60 + seconds) * 1000);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Format a duration for a human-readable status line.
|
|
75
|
+
*/
|
|
76
|
+
export function formatDuration(ms) {
|
|
77
|
+
if (!Number.isFinite(ms) || ms < 0)
|
|
78
|
+
return "0s";
|
|
79
|
+
const seconds = Math.round(ms / 1000);
|
|
80
|
+
if (seconds < 60)
|
|
81
|
+
return `${seconds}s`;
|
|
82
|
+
const minutes = Math.round(seconds / 60);
|
|
83
|
+
if (minutes < 60)
|
|
84
|
+
return `${minutes}m`;
|
|
85
|
+
const hours = Math.floor(minutes / 60);
|
|
86
|
+
const rest = minutes % 60;
|
|
87
|
+
return rest === 0 ? `${hours}h` : `${hours}h ${rest}m`;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Parse one tier declaration.
|
|
91
|
+
*
|
|
92
|
+
* Accepts a plain command string (`"bun test fast"`) or an object with
|
|
93
|
+
* `command`/`label`/`expectedDurationMs`/`datasetSize` fields.
|
|
94
|
+
*/
|
|
95
|
+
export function parseTier(value, kind) {
|
|
96
|
+
if (typeof value === "string") {
|
|
97
|
+
const command = value.trim();
|
|
98
|
+
if (!command)
|
|
99
|
+
return undefined;
|
|
100
|
+
return { kind, command };
|
|
101
|
+
}
|
|
102
|
+
const record = asRecord(value);
|
|
103
|
+
if (!record)
|
|
104
|
+
return undefined;
|
|
105
|
+
const command = firstString(record, ["command", "cmd", "run"]);
|
|
106
|
+
const label = firstString(record, ["label", "name", "description"]);
|
|
107
|
+
const expectedDurationMs = firstNumber(record, ["expectedDurationMs", "expectedCostMs", "durationMs"])
|
|
108
|
+
?? parseDurationMs(record.expectedDuration ?? record.expectedCost ?? record.duration);
|
|
109
|
+
const datasetSize = firstNumber(record, ["datasetSize", "records", "rows"]);
|
|
110
|
+
if (!command && !label && expectedDurationMs === undefined && datasetSize === undefined) {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
return { kind, command, label, expectedDurationMs, datasetSize };
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Read the validation plan of a todo.
|
|
117
|
+
*
|
|
118
|
+
* Returns `null` when the todo declares no plan: ordinary tasks must keep the
|
|
119
|
+
* current behaviour.
|
|
120
|
+
*/
|
|
121
|
+
export function parseValidationPlan(item) {
|
|
122
|
+
const metadata = asRecord(item?.metadata);
|
|
123
|
+
if (!metadata)
|
|
124
|
+
return null;
|
|
125
|
+
const raw = asRecord(metadata.validationPlan)
|
|
126
|
+
?? asRecord(metadata.validation)
|
|
127
|
+
?? asRecord(metadata.validation_plan);
|
|
128
|
+
if (!raw)
|
|
129
|
+
return null;
|
|
130
|
+
const tiers = asRecord(raw.tiers);
|
|
131
|
+
const plan = {};
|
|
132
|
+
const fast = parseTier(raw.fast, "fast")
|
|
133
|
+
?? parseTier(raw.fastCommand ?? raw.fastTier ?? tiers?.fast, "fast");
|
|
134
|
+
const full = parseTier(raw.full, "full")
|
|
135
|
+
?? parseTier(raw.fullCommand ?? raw.fullTier ?? tiers?.full, "full");
|
|
136
|
+
if (fast)
|
|
137
|
+
plan.fast = fast;
|
|
138
|
+
if (full)
|
|
139
|
+
plan.full = full;
|
|
140
|
+
const notes = firstString(raw, ["notes", "note"]);
|
|
141
|
+
if (notes)
|
|
142
|
+
plan.notes = notes;
|
|
143
|
+
const budgetMinutes = firstNumber(raw, ["budgetMinutes", "budgetMins", "timeBudgetMinutes"]);
|
|
144
|
+
if (budgetMinutes !== undefined)
|
|
145
|
+
plan.budgetMinutes = budgetMinutes;
|
|
146
|
+
if (typeof raw.finalTierRequired === "boolean")
|
|
147
|
+
plan.finalTierRequired = raw.finalTierRequired;
|
|
148
|
+
if (!plan.fast && !plan.full && plan.notes === undefined && plan.budgetMinutes === undefined) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
return plan;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Describe one tier in a single line: command, expected cost, dataset size.
|
|
155
|
+
*/
|
|
156
|
+
export function describeTier(tier) {
|
|
157
|
+
const what = tier.command ? `\`${tier.command}\`` : tier.label ?? "unspecified tier";
|
|
158
|
+
const extras = [];
|
|
159
|
+
if (tier.expectedDurationMs !== undefined)
|
|
160
|
+
extras.push(`~${formatDuration(tier.expectedDurationMs)}`);
|
|
161
|
+
if (tier.datasetSize !== undefined)
|
|
162
|
+
extras.push(`${tier.datasetSize} records`);
|
|
163
|
+
return extras.length > 0 ? `${what} (${extras.join(", ")})` : what;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Compute the budget status of a plan.
|
|
167
|
+
*
|
|
168
|
+
* There is no implicit budget: only a declared `budgetMinutes` arms it. An
|
|
169
|
+
* invented budget could pause legitimate long work, so the harness never
|
|
170
|
+
* guesses one.
|
|
171
|
+
*/
|
|
172
|
+
export function validationBudgetStatus(plan, elapsedMs) {
|
|
173
|
+
if (!plan || plan.budgetMinutes === undefined) {
|
|
174
|
+
return { elapsedMs, exhausted: false };
|
|
175
|
+
}
|
|
176
|
+
const budgetMs = Math.max(0, plan.budgetMinutes * 60_000);
|
|
177
|
+
const elapsed = elapsedMs ?? 0;
|
|
178
|
+
const remainingMs = Math.max(0, budgetMs - elapsed);
|
|
179
|
+
return {
|
|
180
|
+
budgetMs,
|
|
181
|
+
elapsedMs: elapsed,
|
|
182
|
+
remainingMs,
|
|
183
|
+
exhausted: elapsed >= budgetMs,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Aggregate recorded runs into the validation state of an item.
|
|
188
|
+
*
|
|
189
|
+
* The runs are expected in chronological order; the latest run of a tier
|
|
190
|
+
* defines its state.
|
|
191
|
+
*/
|
|
192
|
+
export function summarizeValidationState(plan, runs) {
|
|
193
|
+
const notRun = { status: "not-run" };
|
|
194
|
+
if (!plan) {
|
|
195
|
+
return {
|
|
196
|
+
hasPlan: false,
|
|
197
|
+
fast: { ...notRun },
|
|
198
|
+
full: { ...notRun },
|
|
199
|
+
finalTierRequired: false,
|
|
200
|
+
finalTierPending: false,
|
|
201
|
+
planIncomplete: false,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
const stateOf = (tier) => {
|
|
205
|
+
const matching = runs.filter((run) => run.tier === tier);
|
|
206
|
+
if (matching.length === 0)
|
|
207
|
+
return { ...notRun };
|
|
208
|
+
// The ledger is append-only, so the array order is the chronological
|
|
209
|
+
// order: with an equal timestamp the LATER run wins.
|
|
210
|
+
const latest = matching.reduce((a, b) => (a.ts > b.ts ? a : b));
|
|
211
|
+
const state = { status: latest.status };
|
|
212
|
+
state.at = latest.ts;
|
|
213
|
+
return state;
|
|
214
|
+
};
|
|
215
|
+
const finalTierRequired = plan.finalTierRequired === true;
|
|
216
|
+
const planIncomplete = finalTierRequired && plan.full === undefined;
|
|
217
|
+
const full = stateOf("full");
|
|
218
|
+
const state = {
|
|
219
|
+
hasPlan: true,
|
|
220
|
+
fast: stateOf("fast"),
|
|
221
|
+
full,
|
|
222
|
+
finalTierRequired,
|
|
223
|
+
finalTierPending: finalTierRequired && plan.full !== undefined && full.status !== "passed",
|
|
224
|
+
planIncomplete,
|
|
225
|
+
};
|
|
226
|
+
if (plan.budgetMinutes !== undefined)
|
|
227
|
+
state.budgetMinutes = plan.budgetMinutes;
|
|
228
|
+
return state;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Render the validation context that is injected into a continuation message.
|
|
232
|
+
*
|
|
233
|
+
* The text is deliberately short: it is added to the steer payload that the
|
|
234
|
+
* agent reads when the harness continues a todo on its own.
|
|
235
|
+
*/
|
|
236
|
+
export function formatValidationContext(plan, opts = {}) {
|
|
237
|
+
const lines = [];
|
|
238
|
+
const tiers = [];
|
|
239
|
+
if (plan.fast)
|
|
240
|
+
tiers.push(`fast=${describeTier(plan.fast)}`);
|
|
241
|
+
if (plan.full)
|
|
242
|
+
tiers.push(`full=${describeTier(plan.full)}`);
|
|
243
|
+
if (tiers.length === 0 && plan.notes === undefined && plan.budgetMinutes === undefined) {
|
|
244
|
+
return "";
|
|
245
|
+
}
|
|
246
|
+
lines.push(`VALIDATION PLAN (staged): ${tiers.join(" | ") || "no tiers declared"}`);
|
|
247
|
+
if (plan.fast && plan.full) {
|
|
248
|
+
lines.push("Run the fast tier after every edit; run the full tier once when the implementation is stable. " +
|
|
249
|
+
"Do not repeat the full tier after an edit that cannot affect the behavior it covers.");
|
|
250
|
+
}
|
|
251
|
+
if (plan.finalTierRequired) {
|
|
252
|
+
lines.push("The full tier is the final acceptance check: do not complete this todo while it is pending or failed.");
|
|
253
|
+
}
|
|
254
|
+
if (plan.budgetMinutes !== undefined) {
|
|
255
|
+
const budgetMs = plan.budgetMinutes * 60_000;
|
|
256
|
+
const elapsed = opts.elapsedMs;
|
|
257
|
+
const elapsedPart = elapsed === undefined
|
|
258
|
+
? ""
|
|
259
|
+
: ` (elapsed ${formatDuration(elapsed)}, remaining ${formatDuration(Math.max(0, budgetMs - elapsed))})`;
|
|
260
|
+
lines.push(`Time budget: ${plan.budgetMinutes}m${elapsedPart}. When the budget is reached: stop, report what passed ` +
|
|
261
|
+
"and what is still pending, and do not mark the todo complete.");
|
|
262
|
+
}
|
|
263
|
+
if (plan.notes)
|
|
264
|
+
lines.push(`Notes: ${plan.notes}`);
|
|
265
|
+
// The recorded runs tell the agent what already happened, so it neither
|
|
266
|
+
// repeats a tier that passed nor forgets a pending final tier.
|
|
267
|
+
const state = opts.state;
|
|
268
|
+
if (state?.hasPlan) {
|
|
269
|
+
if (state.fast.status !== "not-run") {
|
|
270
|
+
lines.push(`Fast tier: ${state.fast.status}${state.fast.at ? ` (last run ${state.fast.at})` : ""}.`);
|
|
271
|
+
}
|
|
272
|
+
if (state.full.status !== "not-run") {
|
|
273
|
+
lines.push(`Full tier: ${state.full.status}${state.full.at ? ` (last run ${state.full.at})` : ""}.`);
|
|
274
|
+
}
|
|
275
|
+
if (state.full.status === "passed") {
|
|
276
|
+
lines.push("The final tier already passed. Do not repeat it unless the next change can affect what it covers.");
|
|
277
|
+
}
|
|
278
|
+
if (state.planIncomplete) {
|
|
279
|
+
lines.push("The plan requires a final tier but declares none: report that instead of completing the todo silently.");
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return lines.join("\n");
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Convenience wrapper: the validation context of a todo, or an empty string.
|
|
286
|
+
*/
|
|
287
|
+
export function buildValidationSteerSuffix(item, opts = {}) {
|
|
288
|
+
const plan = parseValidationPlan(item);
|
|
289
|
+
if (!plan)
|
|
290
|
+
return "";
|
|
291
|
+
return formatValidationContext(plan, opts);
|
|
292
|
+
}
|
|
293
|
+
//# sourceMappingURL=validation-plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-plan.js","sourceRoot":"","sources":["../src/validation-plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation tie-breaker - a typed verdict about one todo item.
|
|
3
|
+
*
|
|
4
|
+
* The judge (Jev) and the harness both need the same question answered with
|
|
5
|
+
* a value instead of prose: "may this item count as done?".
|
|
6
|
+
*
|
|
7
|
+
* The verdict is derived from the declared plan and the recorded runs:
|
|
8
|
+
*
|
|
9
|
+
* - `no-plan` the item declares no validation plan
|
|
10
|
+
* - `complete` the final tier passed, or none was required
|
|
11
|
+
* - `final-tier-pending` the final tier is required and has not passed yet
|
|
12
|
+
* - `final-tier-failed` the final tier ran and did not pass
|
|
13
|
+
* - `plan-incomplete` the plan requires a final tier but declares none
|
|
14
|
+
*
|
|
15
|
+
* A `final-tier-pending` or `final-tier-failed` verdict means the item must
|
|
16
|
+
* not be reported as complete.
|
|
17
|
+
*/
|
|
18
|
+
import type { TodoItem } from "./todo-provider.js";
|
|
19
|
+
import type { ValidationState } from "./validation-plan.js";
|
|
20
|
+
/**
|
|
21
|
+
* Typed verdict about the validation state of one item.
|
|
22
|
+
*/
|
|
23
|
+
export type ValidationVerdict = "no-plan" | "complete" | "final-tier-pending" | "final-tier-failed" | "plan-incomplete";
|
|
24
|
+
/**
|
|
25
|
+
* The verdict plus the context a caller needs to report it.
|
|
26
|
+
*/
|
|
27
|
+
export interface ValidationTieBreaker {
|
|
28
|
+
verdict: ValidationVerdict;
|
|
29
|
+
/** Human readable reason for the verdict. */
|
|
30
|
+
reason: string;
|
|
31
|
+
/** The item the verdict is about. */
|
|
32
|
+
itemId?: number;
|
|
33
|
+
/** Subject of the item. */
|
|
34
|
+
subject?: string;
|
|
35
|
+
/** Status of the final tier, when one ran. */
|
|
36
|
+
tierStatus?: string;
|
|
37
|
+
/** True when the item must not be reported as complete. */
|
|
38
|
+
blocksCompletion: boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Derive the verdict from the validation state of an item.
|
|
42
|
+
*/
|
|
43
|
+
export declare function tieBreakValidation(item: TodoItem | null | undefined, state: ValidationState): ValidationTieBreaker;
|
|
44
|
+
/**
|
|
45
|
+
* Format a verdict for a log line or a status line.
|
|
46
|
+
*/
|
|
47
|
+
export declare function formatTieBreaker(result: ValidationTieBreaker): string;
|
|
48
|
+
//# sourceMappingURL=validation-tie-breaker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-tie-breaker.d.ts","sourceRoot":"","sources":["../src/validation-tie-breaker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAC1B,SAAS,GACT,UAAU,GACV,oBAAoB,GACpB,mBAAmB,GACnB,iBAAiB,CAAC;AAErB;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,gBAAgB,EAAE,OAAO,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CACjC,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,SAAS,EACjC,KAAK,EAAE,eAAe,GACpB,oBAAoB,CA4DtB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAGrE"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation tie-breaker - a typed verdict about one todo item.
|
|
3
|
+
*
|
|
4
|
+
* The judge (Jev) and the harness both need the same question answered with
|
|
5
|
+
* a value instead of prose: "may this item count as done?".
|
|
6
|
+
*
|
|
7
|
+
* The verdict is derived from the declared plan and the recorded runs:
|
|
8
|
+
*
|
|
9
|
+
* - `no-plan` the item declares no validation plan
|
|
10
|
+
* - `complete` the final tier passed, or none was required
|
|
11
|
+
* - `final-tier-pending` the final tier is required and has not passed yet
|
|
12
|
+
* - `final-tier-failed` the final tier ran and did not pass
|
|
13
|
+
* - `plan-incomplete` the plan requires a final tier but declares none
|
|
14
|
+
*
|
|
15
|
+
* A `final-tier-pending` or `final-tier-failed` verdict means the item must
|
|
16
|
+
* not be reported as complete.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Derive the verdict from the validation state of an item.
|
|
20
|
+
*/
|
|
21
|
+
export function tieBreakValidation(item, state) {
|
|
22
|
+
const base = {
|
|
23
|
+
itemId: item?.id,
|
|
24
|
+
subject: item?.subject,
|
|
25
|
+
};
|
|
26
|
+
if (!state.hasPlan) {
|
|
27
|
+
return {
|
|
28
|
+
...base,
|
|
29
|
+
verdict: "no-plan",
|
|
30
|
+
reason: "no validation plan declared",
|
|
31
|
+
blocksCompletion: false,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (state.planIncomplete) {
|
|
35
|
+
return {
|
|
36
|
+
...base,
|
|
37
|
+
verdict: "plan-incomplete",
|
|
38
|
+
reason: "the plan requires a final tier but declares none",
|
|
39
|
+
blocksCompletion: true,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
if (!state.finalTierRequired) {
|
|
43
|
+
return {
|
|
44
|
+
...base,
|
|
45
|
+
verdict: "complete",
|
|
46
|
+
reason: "no final tier required",
|
|
47
|
+
blocksCompletion: false,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (state.full.status === "passed") {
|
|
51
|
+
return {
|
|
52
|
+
...base,
|
|
53
|
+
verdict: "complete",
|
|
54
|
+
reason: "the final tier passed",
|
|
55
|
+
tierStatus: state.full.status,
|
|
56
|
+
blocksCompletion: false,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (state.full.status === "not-run") {
|
|
60
|
+
return {
|
|
61
|
+
...base,
|
|
62
|
+
verdict: "final-tier-pending",
|
|
63
|
+
reason: "the final tier has not run yet",
|
|
64
|
+
tierStatus: state.full.status,
|
|
65
|
+
blocksCompletion: true,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
...base,
|
|
70
|
+
verdict: "final-tier-failed",
|
|
71
|
+
reason: `the final tier did not pass (${state.full.status})`,
|
|
72
|
+
tierStatus: state.full.status,
|
|
73
|
+
blocksCompletion: true,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Format a verdict for a log line or a status line.
|
|
78
|
+
*/
|
|
79
|
+
export function formatTieBreaker(result) {
|
|
80
|
+
const subject = result.subject ? `${result.subject}: ` : "";
|
|
81
|
+
return `${subject}${result.verdict} (${result.reason})`;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=validation-tie-breaker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-tie-breaker.js","sourceRoot":"","sources":["../src/validation-tie-breaker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAgCH;;GAEG;AACH,MAAM,UAAU,kBAAkB,CACjC,IAAiC,EACjC,KAAsB;IAEtB,MAAM,IAAI,GAAG;QACZ,MAAM,EAAE,IAAI,EAAE,EAAE;QAChB,OAAO,EAAE,IAAI,EAAE,OAAO;KACtB,CAAC;IAEF,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO;YACN,GAAG,IAAI;YACP,OAAO,EAAE,SAAS;YAClB,MAAM,EAAE,6BAA6B;YACrC,gBAAgB,EAAE,KAAK;SACvB,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;QAC1B,OAAO;YACN,GAAG,IAAI;YACP,OAAO,EAAE,iBAAiB;YAC1B,MAAM,EAAE,kDAAkD;YAC1D,gBAAgB,EAAE,IAAI;SACtB,CAAC;IACH,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC9B,OAAO;YACN,GAAG,IAAI;YACP,OAAO,EAAE,UAAU;YACnB,MAAM,EAAE,wBAAwB;YAChC,gBAAgB,EAAE,KAAK;SACvB,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO;YACN,GAAG,IAAI;YACP,OAAO,EAAE,UAAU;YACnB,MAAM,EAAE,uBAAuB;YAC/B,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM;YAC7B,gBAAgB,EAAE,KAAK;SACvB,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACrC,OAAO;YACN,GAAG,IAAI;YACP,OAAO,EAAE,oBAAoB;YAC7B,MAAM,EAAE,gCAAgC;YACxC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM;YAC7B,gBAAgB,EAAE,IAAI;SACtB,CAAC;IACH,CAAC;IAED,OAAO;QACN,GAAG,IAAI;QACP,OAAO,EAAE,mBAAmB;QAC5B,MAAM,EAAE,gCAAgC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG;QAC5D,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM;QAC7B,gBAAgB,EAAE,IAAI;KACtB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAA4B;IAC5D,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC,OAAO,KAAK,MAAM,CAAC,MAAM,GAAG,CAAC;AACzD,CAAC"}
|