selftune 0.2.16 → 0.2.19

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.
Files changed (91) hide show
  1. package/README.md +32 -22
  2. package/apps/local-dashboard/dist/assets/index-DnhnXQm6.js +60 -0
  3. package/apps/local-dashboard/dist/assets/index-_EcLywDg.css +1 -0
  4. package/apps/local-dashboard/dist/assets/vendor-table-BIiI3YhS.js +1 -0
  5. package/apps/local-dashboard/dist/assets/vendor-ui-CGEmUayx.js +12 -0
  6. package/apps/local-dashboard/dist/index.html +5 -5
  7. package/cli/selftune/alpha-upload/build-payloads.ts +14 -1
  8. package/cli/selftune/alpha-upload/client.ts +51 -1
  9. package/cli/selftune/alpha-upload/flush.ts +46 -5
  10. package/cli/selftune/alpha-upload/stage-canonical.ts +32 -10
  11. package/cli/selftune/alpha-upload-contract.ts +9 -0
  12. package/cli/selftune/constants.ts +92 -5
  13. package/cli/selftune/contribute/contribute.ts +30 -2
  14. package/cli/selftune/contribute/sanitize.ts +52 -5
  15. package/cli/selftune/contribution-config.ts +249 -0
  16. package/cli/selftune/contribution-relay.ts +177 -0
  17. package/cli/selftune/contribution-signals.ts +219 -0
  18. package/cli/selftune/contribution-staging.ts +147 -0
  19. package/cli/selftune/contributions.ts +532 -0
  20. package/cli/selftune/creator-contributions.ts +333 -0
  21. package/cli/selftune/dashboard-contract.ts +305 -1
  22. package/cli/selftune/dashboard-server.ts +47 -13
  23. package/cli/selftune/eval/family-overlap.ts +395 -0
  24. package/cli/selftune/eval/hooks-to-evals.ts +182 -28
  25. package/cli/selftune/eval/synthetic-evals.ts +298 -11
  26. package/cli/selftune/evolution/description-quality.ts +12 -11
  27. package/cli/selftune/evolution/evolve.ts +214 -51
  28. package/cli/selftune/evolution/validate-proposal.ts +9 -6
  29. package/cli/selftune/export.ts +2 -2
  30. package/cli/selftune/grading/grade-session.ts +20 -0
  31. package/cli/selftune/hooks/commit-track.ts +188 -0
  32. package/cli/selftune/hooks/prompt-log.ts +10 -1
  33. package/cli/selftune/hooks/session-stop.ts +2 -2
  34. package/cli/selftune/hooks/skill-eval.ts +15 -1
  35. package/cli/selftune/hooks/stdin-preview.ts +32 -0
  36. package/cli/selftune/index.ts +41 -5
  37. package/cli/selftune/ingestors/codex-rollout.ts +31 -35
  38. package/cli/selftune/ingestors/codex-wrapper.ts +32 -24
  39. package/cli/selftune/localdb/db.ts +2 -2
  40. package/cli/selftune/localdb/direct-write.ts +69 -6
  41. package/cli/selftune/localdb/queries.ts +1253 -37
  42. package/cli/selftune/localdb/schema.ts +66 -0
  43. package/cli/selftune/orchestrate.ts +32 -4
  44. package/cli/selftune/recover.ts +153 -0
  45. package/cli/selftune/repair/skill-usage.ts +363 -4
  46. package/cli/selftune/routes/actions.ts +35 -1
  47. package/cli/selftune/routes/analytics.ts +14 -0
  48. package/cli/selftune/routes/index.ts +1 -0
  49. package/cli/selftune/routes/overview.ts +150 -4
  50. package/cli/selftune/routes/skill-report.ts +648 -18
  51. package/cli/selftune/status.ts +81 -2
  52. package/cli/selftune/sync.ts +56 -2
  53. package/cli/selftune/trust-model.ts +66 -0
  54. package/cli/selftune/types.ts +80 -0
  55. package/cli/selftune/utils/skill-detection.ts +43 -0
  56. package/cli/selftune/utils/transcript.ts +210 -1
  57. package/cli/selftune/watchlist.ts +65 -0
  58. package/node_modules/@selftune/telemetry-contract/src/types.ts +11 -0
  59. package/package.json +1 -1
  60. package/packages/telemetry-contract/src/types.ts +11 -0
  61. package/packages/ui/src/components/ActivityTimeline.tsx +165 -150
  62. package/packages/ui/src/components/EvidenceViewer.tsx +335 -144
  63. package/packages/ui/src/components/EvolutionTimeline.tsx +58 -28
  64. package/packages/ui/src/components/OrchestrateRunsPanel.tsx +33 -16
  65. package/packages/ui/src/components/RecentActivityFeed.tsx +72 -41
  66. package/packages/ui/src/components/section-cards.tsx +12 -9
  67. package/packages/ui/src/primitives/card.tsx +1 -1
  68. package/skill/SKILL.md +40 -2
  69. package/skill/Workflows/AlphaUpload.md +4 -0
  70. package/skill/Workflows/Composability.md +64 -0
  71. package/skill/Workflows/Contribute.md +6 -3
  72. package/skill/Workflows/Contributions.md +97 -0
  73. package/skill/Workflows/CreatorContributions.md +74 -0
  74. package/skill/Workflows/Dashboard.md +31 -0
  75. package/skill/Workflows/Evals.md +57 -8
  76. package/skill/Workflows/Evolve.md +31 -13
  77. package/skill/Workflows/ExportCanonical.md +121 -0
  78. package/skill/Workflows/Hook.md +131 -0
  79. package/skill/Workflows/Ingest.md +7 -0
  80. package/skill/Workflows/Initialize.md +29 -9
  81. package/skill/Workflows/Orchestrate.md +27 -5
  82. package/skill/Workflows/Quickstart.md +94 -0
  83. package/skill/Workflows/Recover.md +84 -0
  84. package/skill/Workflows/RepairSkillUsage.md +95 -0
  85. package/skill/Workflows/Sync.md +18 -12
  86. package/skill/Workflows/Uninstall.md +82 -0
  87. package/skill/settings_snippet.json +11 -0
  88. package/apps/local-dashboard/dist/assets/index-BMIS6uUh.css +0 -2
  89. package/apps/local-dashboard/dist/assets/index-DOu3iLD9.js +0 -16
  90. package/apps/local-dashboard/dist/assets/vendor-table-pHbDxq36.js +0 -8
  91. package/apps/local-dashboard/dist/assets/vendor-ui-DIwlrGlb.js +0 -12
@@ -239,6 +239,21 @@ CREATE TABLE IF NOT EXISTS upload_queue (
239
239
  last_error TEXT
240
240
  )`;
241
241
 
242
+ // -- Creator contribution staging --------------------------------------------
243
+
244
+ export const CREATE_CREATOR_CONTRIBUTION_STAGING = `
245
+ CREATE TABLE IF NOT EXISTS creator_contribution_staging (
246
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
247
+ dedupe_key TEXT NOT NULL,
248
+ skill_name TEXT NOT NULL,
249
+ creator_id TEXT NOT NULL,
250
+ payload_json TEXT NOT NULL,
251
+ status TEXT NOT NULL DEFAULT 'pending',
252
+ staged_at TEXT NOT NULL,
253
+ updated_at TEXT NOT NULL,
254
+ last_error TEXT
255
+ )`;
256
+
242
257
  // -- Canonical upload staging -------------------------------------------------
243
258
 
244
259
  export const CREATE_CANONICAL_UPLOAD_STAGING = `
@@ -260,6 +275,20 @@ CREATE TABLE IF NOT EXISTS upload_watermarks (
260
275
  updated_at TEXT NOT NULL
261
276
  )`;
262
277
 
278
+ // -- Commit tracking table ----------------------------------------------------
279
+
280
+ export const CREATE_COMMIT_TRACKING = `
281
+ CREATE TABLE IF NOT EXISTS commit_tracking (
282
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
283
+ session_id TEXT NOT NULL,
284
+ commit_sha TEXT NOT NULL,
285
+ commit_title TEXT,
286
+ branch TEXT,
287
+ repo_remote TEXT,
288
+ timestamp TEXT NOT NULL,
289
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
290
+ )`;
291
+
263
292
  // -- Metadata table -----------------------------------------------------------
264
293
 
265
294
  export const CREATE_META = `
@@ -313,10 +342,19 @@ export const CREATE_INDEXES = [
313
342
  // -- Alpha upload queue indexes ---------------------------------------------
314
343
  `CREATE INDEX IF NOT EXISTS idx_upload_queue_status ON upload_queue(status)`,
315
344
  `CREATE INDEX IF NOT EXISTS idx_upload_queue_type_status ON upload_queue(payload_type, status)`,
345
+ // -- Creator contribution staging indexes -----------------------------------
346
+ `CREATE INDEX IF NOT EXISTS idx_creator_contrib_status ON creator_contribution_staging(status)`,
347
+ `CREATE INDEX IF NOT EXISTS idx_creator_contrib_skill ON creator_contribution_staging(skill_name)`,
348
+ `CREATE UNIQUE INDEX IF NOT EXISTS idx_creator_contrib_dedup ON creator_contribution_staging(dedupe_key)`,
316
349
  // -- Canonical upload staging indexes ---------------------------------------
317
350
  `CREATE INDEX IF NOT EXISTS idx_staging_kind ON canonical_upload_staging(record_kind)`,
318
351
  `CREATE INDEX IF NOT EXISTS idx_staging_session ON canonical_upload_staging(session_id)`,
319
352
  `CREATE UNIQUE INDEX IF NOT EXISTS idx_staging_dedup ON canonical_upload_staging(record_kind, record_id)`,
353
+ // -- Commit tracking indexes ------------------------------------------------
354
+ `CREATE INDEX IF NOT EXISTS idx_commit_sha ON commit_tracking(commit_sha)`,
355
+ `CREATE INDEX IF NOT EXISTS idx_commit_session ON commit_tracking(session_id)`,
356
+ `CREATE INDEX IF NOT EXISTS idx_commit_ts ON commit_tracking(timestamp)`,
357
+ `CREATE UNIQUE INDEX IF NOT EXISTS idx_commit_dedup ON commit_tracking(session_id, commit_sha)`,
320
358
  ];
321
359
 
322
360
  /**
@@ -353,6 +391,31 @@ export const MIGRATIONS = [
353
391
  `ALTER TABLE execution_facts ADD COLUMN normalizer_version TEXT`,
354
392
  `ALTER TABLE execution_facts ADD COLUMN capture_mode TEXT`,
355
393
  `ALTER TABLE execution_facts ADD COLUMN raw_source_ref TEXT`,
394
+ // -- Win 2+3: File change metrics + token granularity + cost (execution_facts) --
395
+ `ALTER TABLE execution_facts ADD COLUMN files_changed INTEGER`,
396
+ `ALTER TABLE execution_facts ADD COLUMN lines_added INTEGER`,
397
+ `ALTER TABLE execution_facts ADD COLUMN lines_removed INTEGER`,
398
+ `ALTER TABLE execution_facts ADD COLUMN lines_modified INTEGER`,
399
+ `ALTER TABLE execution_facts ADD COLUMN cached_input_tokens INTEGER`,
400
+ `ALTER TABLE execution_facts ADD COLUMN reasoning_output_tokens INTEGER`,
401
+ `ALTER TABLE execution_facts ADD COLUMN cost_usd REAL`,
402
+ // -- Win 2+3: File change metrics + token granularity + cost (session_telemetry) --
403
+ `ALTER TABLE session_telemetry ADD COLUMN files_changed INTEGER`,
404
+ `ALTER TABLE session_telemetry ADD COLUMN lines_added INTEGER`,
405
+ `ALTER TABLE session_telemetry ADD COLUMN lines_removed INTEGER`,
406
+ `ALTER TABLE session_telemetry ADD COLUMN lines_modified INTEGER`,
407
+ `ALTER TABLE session_telemetry ADD COLUMN cached_input_tokens INTEGER`,
408
+ `ALTER TABLE session_telemetry ADD COLUMN reasoning_output_tokens INTEGER`,
409
+ `ALTER TABLE session_telemetry ADD COLUMN cost_usd REAL`,
410
+ // -- Generalized metrics: artifact count + session type --
411
+ `ALTER TABLE execution_facts ADD COLUMN artifact_count INTEGER`,
412
+ `ALTER TABLE execution_facts ADD COLUMN session_type TEXT`,
413
+ `ALTER TABLE session_telemetry ADD COLUMN artifact_count INTEGER`,
414
+ `ALTER TABLE session_telemetry ADD COLUMN session_type TEXT`,
415
+ // -- Session summary (heuristic, no LLM) --
416
+ `ALTER TABLE session_telemetry ADD COLUMN agent_summary TEXT`,
417
+ // -- SHA256 content hashing for upload dedup --
418
+ `ALTER TABLE canonical_upload_staging ADD COLUMN content_sha256 TEXT`,
356
419
  ];
357
420
 
358
421
  /** Indexes that depend on migration columns — must run AFTER MIGRATIONS. */
@@ -360,6 +423,7 @@ export const POST_MIGRATION_INDEXES = [
360
423
  `CREATE INDEX IF NOT EXISTS idx_skill_inv_query_triggered ON skill_invocations(query, triggered)`,
361
424
  `CREATE INDEX IF NOT EXISTS idx_skill_inv_scope ON skill_invocations(skill_name, skill_scope, occurred_at)`,
362
425
  `CREATE INDEX IF NOT EXISTS idx_skill_inv_dedup ON skill_invocations(session_id, skill_name, query, occurred_at, triggered)`,
426
+ `CREATE INDEX IF NOT EXISTS idx_staging_sha256 ON canonical_upload_staging(content_sha256)`,
363
427
  ];
364
428
 
365
429
  /** All DDL statements in creation order. */
@@ -377,8 +441,10 @@ export const ALL_DDL = [
377
441
  CREATE_GRADING_RESULTS,
378
442
  CREATE_IMPROVEMENT_SIGNALS,
379
443
  CREATE_UPLOAD_QUEUE,
444
+ CREATE_CREATOR_CONTRIBUTION_STAGING,
380
445
  CREATE_UPLOAD_WATERMARKS,
381
446
  CREATE_CANONICAL_UPLOAD_STAGING,
447
+ CREATE_COMMIT_TRACKING,
382
448
  CREATE_META,
383
449
  ...CREATE_INDEXES,
384
450
  ];
@@ -16,9 +16,9 @@ import { parseArgs } from "node:util";
16
16
 
17
17
  import { readAlphaIdentity } from "./alpha-identity.js";
18
18
  import type { UploadCycleSummary } from "./alpha-upload/index.js";
19
- import { ORCHESTRATE_LOCK, SELFTUNE_CONFIG_PATH } from "./constants.js";
19
+ import { getOrchestrateLockPath, SELFTUNE_CONFIG_PATH } from "./constants.js";
20
20
  import type { OrchestrateRunReport, OrchestrateRunSkillAction } from "./dashboard-contract.js";
21
- import type { EvolveResult } from "./evolution/evolve.js";
21
+ import type { EvolveOptions, EvolveResult } from "./evolution/evolve.js";
22
22
  import {
23
23
  buildDefaultGradingOutputPath,
24
24
  deriveExpectationsFromSkill,
@@ -74,7 +74,7 @@ interface LockInfo {
74
74
 
75
75
  const LOCK_STALE_MS = 30 * 60 * 1000; // 30 minutes
76
76
 
77
- export function acquireLock(lockPath: string = ORCHESTRATE_LOCK): boolean {
77
+ export function acquireLock(lockPath: string = getOrchestrateLockPath()): boolean {
78
78
  try {
79
79
  if (existsSync(lockPath)) {
80
80
  try {
@@ -98,7 +98,7 @@ export function acquireLock(lockPath: string = ORCHESTRATE_LOCK): boolean {
98
98
  }
99
99
  }
100
100
 
101
- export function releaseLock(lockPath: string = ORCHESTRATE_LOCK): void {
101
+ export function releaseLock(lockPath: string = getOrchestrateLockPath()): void {
102
102
  try {
103
103
  unlinkSync(lockPath);
104
104
  } catch {
@@ -377,6 +377,33 @@ export const MIN_CANDIDATE_EVIDENCE = 3;
377
377
  /** Default cooldown hours after a deploy before re-evolving the same skill. */
378
378
  export const DEFAULT_COOLDOWN_HOURS = 24;
379
379
 
380
+ type AutonomousEvolveDefaults = Pick<
381
+ EvolveOptions,
382
+ | "paretoEnabled"
383
+ | "candidateCount"
384
+ | "tokenEfficiencyEnabled"
385
+ | "withBaseline"
386
+ | "validationModel"
387
+ | "cheapLoop"
388
+ | "gateModel"
389
+ | "adaptiveGate"
390
+ | "proposalModel"
391
+ >;
392
+
393
+ // Keep the autonomous loop aligned with the evolve CLI defaults so scheduled
394
+ // runs stay cheap by default and still get a stronger gate before deploy.
395
+ const AUTONOMOUS_EVOLVE_DEFAULTS: AutonomousEvolveDefaults = {
396
+ paretoEnabled: true,
397
+ candidateCount: 3,
398
+ tokenEfficiencyEnabled: false,
399
+ withBaseline: false,
400
+ validationModel: "haiku",
401
+ cheapLoop: true,
402
+ gateModel: "sonnet",
403
+ adaptiveGate: true,
404
+ proposalModel: "haiku",
405
+ };
406
+
380
407
  function candidatePriority(skill: SkillStatus, signalCount = 0): number {
381
408
  const statusWeight = skill.status === "CRITICAL" ? 300 : skill.status === "WARNING" ? 200 : 100;
382
409
  const missedWeight = Math.min(skill.missedQueries, 50);
@@ -1012,6 +1039,7 @@ export async function orchestrate(
1012
1039
  maxIterations: 3,
1013
1040
  gradingResults: _readGradingResults(candidate.skill),
1014
1041
  syncFirst: false, // We already synced
1042
+ ...AUTONOMOUS_EVOLVE_DEFAULTS,
1015
1043
  });
1016
1044
 
1017
1045
  candidate.evolveResult = evolveResult;
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { parseArgs } from "node:util";
4
+
5
+ import {
6
+ CANONICAL_LOG,
7
+ EVOLUTION_AUDIT_LOG,
8
+ EVOLUTION_EVIDENCE_LOG,
9
+ ORCHESTRATE_RUN_LOG,
10
+ TELEMETRY_LOG,
11
+ } from "./constants.js";
12
+ import { getDb } from "./localdb/db.js";
13
+ import {
14
+ materializeFull,
15
+ materializeIncremental,
16
+ type MaterializeOptions,
17
+ type MaterializeResult,
18
+ } from "./localdb/materialize.js";
19
+ import { CLIError, handleCLIError } from "./utils/cli-error.js";
20
+
21
+ interface RecoverSummary {
22
+ mode: "incremental" | "full";
23
+ source: "legacy_jsonl_or_export_snapshot";
24
+ since: string | null;
25
+ force: boolean;
26
+ result: MaterializeResult;
27
+ }
28
+
29
+ function buildMaterializeOptions(values: Record<string, unknown>): MaterializeOptions {
30
+ return {
31
+ canonicalLogPath: (values["canonical-log"] as string | undefined) ?? CANONICAL_LOG,
32
+ telemetryLogPath: (values["telemetry-log"] as string | undefined) ?? TELEMETRY_LOG,
33
+ evolutionAuditPath:
34
+ (values["evolution-audit-log"] as string | undefined) ?? EVOLUTION_AUDIT_LOG,
35
+ evolutionEvidencePath:
36
+ (values["evolution-evidence-log"] as string | undefined) ?? EVOLUTION_EVIDENCE_LOG,
37
+ orchestrateRunLogPath:
38
+ (values["orchestrate-run-log"] as string | undefined) ?? ORCHESTRATE_RUN_LOG,
39
+ force: (values.force as boolean | undefined) ?? false,
40
+ };
41
+ }
42
+
43
+ function printHumanSummary(summary: RecoverSummary): void {
44
+ const rows = [
45
+ `mode: ${summary.mode}`,
46
+ "source: legacy JSONL or explicit export snapshot",
47
+ `sessions: ${summary.result.sessions}`,
48
+ `prompts: ${summary.result.prompts}`,
49
+ `skill invocations: ${summary.result.skillInvocations}`,
50
+ `execution facts: ${summary.result.executionFacts}`,
51
+ `session telemetry: ${summary.result.sessionTelemetry}`,
52
+ `legacy skill usage: ${summary.result.skillUsage}`,
53
+ `evolution audit: ${summary.result.evolutionAudit}`,
54
+ `evolution evidence: ${summary.result.evolutionEvidence}`,
55
+ `orchestrate runs: ${summary.result.orchestrateRuns}`,
56
+ ];
57
+ console.log(`selftune recover\n${rows.map((row) => ` ${row}`).join("\n")}`);
58
+ }
59
+
60
+ export function cliMain(): void {
61
+ const { values } = parseArgs({
62
+ args: process.argv.slice(2),
63
+ options: {
64
+ full: { type: "boolean", default: false },
65
+ force: { type: "boolean", default: false },
66
+ since: { type: "string" },
67
+ json: { type: "boolean", default: false },
68
+ "canonical-log": { type: "string", default: CANONICAL_LOG },
69
+ "telemetry-log": { type: "string", default: TELEMETRY_LOG },
70
+ "evolution-audit-log": { type: "string", default: EVOLUTION_AUDIT_LOG },
71
+ "evolution-evidence-log": { type: "string", default: EVOLUTION_EVIDENCE_LOG },
72
+ "orchestrate-run-log": { type: "string", default: ORCHESTRATE_RUN_LOG },
73
+ help: { type: "boolean", short: "h", default: false },
74
+ },
75
+ strict: true,
76
+ });
77
+
78
+ if (values.help) {
79
+ console.log(`selftune recover — Recover SQLite from legacy/exported JSONL
80
+
81
+ Usage:
82
+ selftune recover [options]
83
+
84
+ Use this only for legacy backfill or explicit export-based recovery. Normal
85
+ operation should use \`selftune sync\`, which replays native source data into
86
+ SQLite and preserves alpha-upload compatibility.
87
+
88
+ Options:
89
+ --full Rebuild SQLite tables from scratch
90
+ --force Skip preflight rebuild guard for SQLite-only rows
91
+ --since <date> Incrementally materialize records on/after date
92
+ --canonical-log <path> Canonical JSONL path
93
+ --telemetry-log <path> Session telemetry JSONL path
94
+ --evolution-audit-log <path> Evolution audit JSONL path
95
+ --evolution-evidence-log <path> Evolution evidence JSONL path
96
+ --orchestrate-run-log <path> Orchestrate runs JSONL path
97
+ --json Output JSON summary
98
+ -h, --help Show this help`);
99
+ process.exit(0);
100
+ }
101
+
102
+ if (values.full && values.since) {
103
+ throw new CLIError(
104
+ "Cannot combine --full with --since.",
105
+ "INVALID_FLAG",
106
+ "Use either `selftune recover --full` or `selftune recover --since 2026-01-01`.",
107
+ );
108
+ }
109
+
110
+ let sinceIso: string | null = null;
111
+ if (values.since) {
112
+ const parsed = new Date(values.since as string);
113
+ if (Number.isNaN(parsed.getTime())) {
114
+ throw new CLIError(
115
+ `Invalid --since date: ${values.since}`,
116
+ "INVALID_FLAG",
117
+ "selftune recover --since 2026-01-01",
118
+ );
119
+ }
120
+ sinceIso = parsed.toISOString();
121
+ }
122
+
123
+ const db = getDb();
124
+ const materializeOptions = buildMaterializeOptions(values);
125
+ if (!values.full) materializeOptions.since = sinceIso;
126
+
127
+ const result = values.full
128
+ ? materializeFull(db, materializeOptions)
129
+ : materializeIncremental(db, materializeOptions);
130
+
131
+ const summary: RecoverSummary = {
132
+ mode: values.full ? "full" : "incremental",
133
+ source: "legacy_jsonl_or_export_snapshot",
134
+ since: sinceIso,
135
+ force: (values.force as boolean | undefined) ?? false,
136
+ result,
137
+ };
138
+
139
+ if (values.json || !process.stdout.isTTY) {
140
+ console.log(JSON.stringify(summary, null, 2));
141
+ return;
142
+ }
143
+
144
+ printHumanSummary(summary);
145
+ }
146
+
147
+ if (import.meta.main) {
148
+ try {
149
+ cliMain();
150
+ } catch (error) {
151
+ handleCLIError(error);
152
+ }
153
+ }